tienda 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/images/tienda/chosen-sprite.png +0 -0
  5. data/app/assets/images/tienda/chosen-sprite@2x.png +0 -0
  6. data/app/assets/images/tienda/document.svg +1 -0
  7. data/app/assets/images/tienda/icons/bag.svg +1 -0
  8. data/app/assets/images/tienda/icons/balance.svg +1 -0
  9. data/app/assets/images/tienda/icons/box.svg +1 -0
  10. data/app/assets/images/tienda/icons/building.svg +1 -0
  11. data/app/assets/images/tienda/icons/chart.svg +1 -0
  12. data/app/assets/images/tienda/icons/chat.svg +1 -0
  13. data/app/assets/images/tienda/icons/checkbox.svg +1 -0
  14. data/app/assets/images/tienda/icons/checkbox2.svg +1 -0
  15. data/app/assets/images/tienda/icons/cloud.svg +1 -0
  16. data/app/assets/images/tienda/icons/cone.svg +1 -0
  17. data/app/assets/images/tienda/icons/credit_card.svg +1 -0
  18. data/app/assets/images/tienda/icons/currency.svg +1 -0
  19. data/app/assets/images/tienda/icons/edit.svg +14 -0
  20. data/app/assets/images/tienda/icons/flowchart.svg +1 -0
  21. data/app/assets/images/tienda/icons/gift.svg +1 -0
  22. data/app/assets/images/tienda/icons/globe.svg +1 -0
  23. data/app/assets/images/tienda/icons/id.svg +1 -0
  24. data/app/assets/images/tienda/icons/id2.svg +1 -0
  25. data/app/assets/images/tienda/icons/locked.svg +1 -0
  26. data/app/assets/images/tienda/icons/report.svg +1 -0
  27. data/app/assets/images/tienda/icons/search.svg +1 -0
  28. data/app/assets/images/tienda/icons/support.svg +1 -0
  29. data/app/assets/images/tienda/icons/tags.svg +1 -0
  30. data/app/assets/images/tienda/icons/toolbox.svg +1 -0
  31. data/app/assets/images/tienda/icons/unlocked.svg +1 -0
  32. data/app/assets/images/tienda/icons/wallet.svg +1 -0
  33. data/app/assets/images/tienda/logo.svg +47 -0
  34. data/app/assets/images/tienda/move.svg +1 -0
  35. data/app/assets/images/tienda/shoppe.svg +25 -0
  36. data/app/assets/images/tienda/square.svg +9 -0
  37. data/app/assets/images/tienda/statuses/accepted.svg +14 -0
  38. data/app/assets/images/tienda/statuses/paid.svg +16 -0
  39. data/app/assets/images/tienda/statuses/received.svg +15 -0
  40. data/app/assets/images/tienda/statuses/rejected.svg +14 -0
  41. data/app/assets/images/tienda/statuses/shipped.svg +14 -0
  42. data/app/assets/images/tienda/table-tear-off.png +0 -0
  43. data/app/assets/javascripts/tienda/application.coffee +119 -0
  44. data/app/assets/javascripts/tienda/chosen.jquery.js +1166 -0
  45. data/app/assets/javascripts/tienda/jquery_ui.js +6 -0
  46. data/app/assets/javascripts/tienda/mousetrap.js +9 -0
  47. data/app/assets/javascripts/tienda/order_form.coffee +47 -0
  48. data/app/assets/stylesheets/tienda/application.scss +585 -0
  49. data/app/assets/stylesheets/tienda/chosen.scss +424 -0
  50. data/app/assets/stylesheets/tienda/dialog.scss +25 -0
  51. data/app/assets/stylesheets/tienda/elements.scss +79 -0
  52. data/app/assets/stylesheets/tienda/printable.scss +67 -0
  53. data/app/assets/stylesheets/tienda/reset.scss +93 -0
  54. data/app/assets/stylesheets/tienda/sub.scss +106 -0
  55. data/app/assets/stylesheets/tienda/variables.scss +1 -0
  56. data/app/controllers/tienda/application_controller.rb +46 -0
  57. data/app/controllers/tienda/attachments_controller.rb +14 -0
  58. data/app/controllers/tienda/countries_controller.rb +47 -0
  59. data/app/controllers/tienda/dashboard_controller.rb +9 -0
  60. data/app/controllers/tienda/delivery_service_prices_controller.rb +45 -0
  61. data/app/controllers/tienda/delivery_services_controller.rb +47 -0
  62. data/app/controllers/tienda/orders_controller.rb +90 -0
  63. data/app/controllers/tienda/payments_controller.rb +33 -0
  64. data/app/controllers/tienda/product_categories_controller.rb +47 -0
  65. data/app/controllers/tienda/products_controller.rb +58 -0
  66. data/app/controllers/tienda/sessions_controller.rb +34 -0
  67. data/app/controllers/tienda/settings_controller.rb +16 -0
  68. data/app/controllers/tienda/stock_level_adjustments_controller.rb +40 -0
  69. data/app/controllers/tienda/tax_rates_controller.rb +49 -0
  70. data/app/controllers/tienda/users_controller.rb +53 -0
  71. data/app/controllers/tienda/variants_controller.rb +50 -0
  72. data/app/helpers/tienda/application_helper.rb +60 -0
  73. data/app/mailers/tienda/order_mailer.rb +25 -0
  74. data/app/mailers/tienda/user_mailer.rb +10 -0
  75. data/app/models/tienda/country.rb +27 -0
  76. data/app/models/tienda/delivery_service.rb +33 -0
  77. data/app/models/tienda/delivery_service_price.rb +31 -0
  78. data/app/models/tienda/order/actions.rb +98 -0
  79. data/app/models/tienda/order/billing.rb +105 -0
  80. data/app/models/tienda/order/delivery.rb +229 -0
  81. data/app/models/tienda/order/states.rb +69 -0
  82. data/app/models/tienda/order.rb +93 -0
  83. data/app/models/tienda/order_item.rb +239 -0
  84. data/app/models/tienda/payment.rb +80 -0
  85. data/app/models/tienda/product/product_attributes.rb +20 -0
  86. data/app/models/tienda/product/variants.rb +51 -0
  87. data/app/models/tienda/product.rb +169 -0
  88. data/app/models/tienda/product_attribute.rb +66 -0
  89. data/app/models/tienda/product_category.rb +23 -0
  90. data/app/models/tienda/setting.rb +68 -0
  91. data/app/models/tienda/stock_level_adjustment.rb +19 -0
  92. data/app/models/tienda/tax_rate.rb +46 -0
  93. data/app/models/tienda/user.rb +49 -0
  94. data/app/validators/permalink_validator.rb +7 -0
  95. data/app/views/layouts/tienda/application.html.haml +34 -0
  96. data/app/views/layouts/tienda/printable.html.haml +11 -0
  97. data/app/views/layouts/tienda/sub.html.haml +10 -0
  98. data/app/views/tienda/countries/_form.html.haml +35 -0
  99. data/app/views/tienda/countries/edit.html.haml +6 -0
  100. data/app/views/tienda/countries/index.html.haml +25 -0
  101. data/app/views/tienda/countries/new.html.haml +7 -0
  102. data/app/views/tienda/delivery_service_prices/_form.html.haml +44 -0
  103. data/app/views/tienda/delivery_service_prices/edit.html.haml +6 -0
  104. data/app/views/tienda/delivery_service_prices/index.html.haml +23 -0
  105. data/app/views/tienda/delivery_service_prices/new.html.haml +6 -0
  106. data/app/views/tienda/delivery_services/_form.html.haml +38 -0
  107. data/app/views/tienda/delivery_services/edit.html.haml +9 -0
  108. data/app/views/tienda/delivery_services/index.html.haml +27 -0
  109. data/app/views/tienda/delivery_services/new.html.haml +6 -0
  110. data/app/views/tienda/order_mailer/accepted.text.erb +12 -0
  111. data/app/views/tienda/order_mailer/received.text.erb +12 -0
  112. data/app/views/tienda/order_mailer/rejected.text.erb +10 -0
  113. data/app/views/tienda/order_mailer/shipped.text.erb +16 -0
  114. data/app/views/tienda/orders/_form.html.haml +55 -0
  115. data/app/views/tienda/orders/_order_details.html.haml +57 -0
  116. data/app/views/tienda/orders/_order_items.html.haml +38 -0
  117. data/app/views/tienda/orders/_order_items_form.html.haml +61 -0
  118. data/app/views/tienda/orders/_payments_form.html.haml +15 -0
  119. data/app/views/tienda/orders/_payments_table.html.haml +37 -0
  120. data/app/views/tienda/orders/_search_form.html.haml +24 -0
  121. data/app/views/tienda/orders/_status_bar.html.haml +35 -0
  122. data/app/views/tienda/orders/despatch_note.html.haml +45 -0
  123. data/app/views/tienda/orders/edit.html.haml +21 -0
  124. data/app/views/tienda/orders/index.html.haml +39 -0
  125. data/app/views/tienda/orders/new.html.haml +14 -0
  126. data/app/views/tienda/orders/show.html.haml +25 -0
  127. data/app/views/tienda/payments/refund.html.haml +13 -0
  128. data/app/views/tienda/product_categories/_form.html.haml +26 -0
  129. data/app/views/tienda/product_categories/edit.html.haml +6 -0
  130. data/app/views/tienda/product_categories/index.html.haml +19 -0
  131. data/app/views/tienda/product_categories/new.html.haml +6 -0
  132. data/app/views/tienda/products/_form.html.haml +118 -0
  133. data/app/views/tienda/products/_table.html.haml +42 -0
  134. data/app/views/tienda/products/edit.html.haml +8 -0
  135. data/app/views/tienda/products/import.html.haml +63 -0
  136. data/app/views/tienda/products/index.html.haml +9 -0
  137. data/app/views/tienda/products/new.html.haml +7 -0
  138. data/app/views/tienda/sessions/new.html.haml +12 -0
  139. data/app/views/tienda/sessions/reset.html.haml +12 -0
  140. data/app/views/tienda/settings/edit.html.haml +19 -0
  141. data/app/views/tienda/shared/error.html.haml +6 -0
  142. data/app/views/tienda/stock_level_adjustments/index.html.haml +40 -0
  143. data/app/views/tienda/tax_rates/form.html.haml +28 -0
  144. data/app/views/tienda/tax_rates/index.html.haml +17 -0
  145. data/app/views/tienda/user_mailer/new_password.text.erb +9 -0
  146. data/app/views/tienda/users/_form.html.haml +27 -0
  147. data/app/views/tienda/users/edit.html.haml +5 -0
  148. data/app/views/tienda/users/index.html.haml +17 -0
  149. data/app/views/tienda/users/new.html.haml +7 -0
  150. data/app/views/tienda/variants/form.html.haml +66 -0
  151. data/app/views/tienda/variants/index.html.haml +33 -0
  152. data/config/locales/en.yml +650 -0
  153. data/config/locales/pl.yml +650 -0
  154. data/config/locales/pt-BR.yml +643 -0
  155. data/config/routes.rb +42 -0
  156. data/db/countries.txt +252 -0
  157. data/db/migrate/20150124094549_create_tienda_initial_schema.rb +184 -0
  158. data/db/seeds.rb +128 -0
  159. data/db/seeds_data/poe400.jpg +0 -0
  160. data/db/seeds_data/snom-870-blk.jpg +0 -0
  161. data/db/seeds_data/snom-870-grey.jpg +0 -0
  162. data/db/seeds_data/snom-mm2.jpg +0 -0
  163. data/db/seeds_data/spa303.jpg +0 -0
  164. data/db/seeds_data/t18p.jpg +0 -0
  165. data/db/seeds_data/t20p.jpg +0 -0
  166. data/db/seeds_data/t22p.jpg +0 -0
  167. data/db/seeds_data/t26p.jpg +0 -0
  168. data/db/seeds_data/t41pn.jpg +0 -0
  169. data/db/seeds_data/t46gn.jpg +0 -0
  170. data/db/seeds_data/w52p.jpg +0 -0
  171. data/db/seeds_data/yhs32.jpg +0 -0
  172. data/lib/tasks/tienda.rake +29 -0
  173. data/lib/tienda/associated_countries.rb +20 -0
  174. data/lib/tienda/country_importer.rb +14 -0
  175. data/lib/tienda/default_navigation.rb +20 -0
  176. data/lib/tienda/engine.rb +48 -0
  177. data/lib/tienda/error.rb +21 -0
  178. data/lib/tienda/errors/inappropriate_delivery_service.rb +6 -0
  179. data/lib/tienda/errors/insufficient_stock_to_fulfil.rb +15 -0
  180. data/lib/tienda/errors/invalid_configuration.rb +6 -0
  181. data/lib/tienda/errors/not_enough_stock.rb +15 -0
  182. data/lib/tienda/errors/payment_declined.rb +6 -0
  183. data/lib/tienda/errors/refund_failed.rb +6 -0
  184. data/lib/tienda/errors/unorderable_item.rb +6 -0
  185. data/lib/tienda/navigation_manager.rb +81 -0
  186. data/lib/tienda/orderable_item.rb +39 -0
  187. data/lib/tienda/settings.rb +26 -0
  188. data/lib/tienda/settings_loader.rb +16 -0
  189. data/lib/tienda/setup_generator.rb +10 -0
  190. data/lib/tienda/version.rb +3 -0
  191. data/lib/tienda/view_helpers.rb +16 -0
  192. data/lib/tienda.rb +59 -0
  193. metadata +604 -0
@@ -0,0 +1,106 @@
1
+ /*
2
+ *= require tienda/reset
3
+ *= require tienda/elements
4
+ *= require_self
5
+ */
6
+
7
+
8
+ @import 'variables';
9
+
10
+ html { overflow-y: scroll; height:100%; background:#fff;}
11
+ body { font-family:$font; font-weight: normal; font-size: 100%; min-width:900px; height:100%; }
12
+ @import 'variables';
13
+
14
+ html.login {
15
+ background:image-url('tienda/logo.svg') #40454D no-repeat center 100px;
16
+ background-size:70px;
17
+
18
+ #flash-alert {
19
+ background:#C17391;
20
+ position:absolute;
21
+ top:0;
22
+ width:100%;
23
+ text-align:center;
24
+ color:#fff;
25
+ padding:15px 0;
26
+ }
27
+
28
+ #flash-notice {
29
+ background:#94C164;
30
+ position:absolute;
31
+ top:0;
32
+ width:100%;
33
+ text-align:center;
34
+ color:#fff;
35
+ padding:15px 0;
36
+ }
37
+
38
+ //
39
+ // Error
40
+ //
41
+ div.error {
42
+ background:#fff;
43
+ width:400px;
44
+ margin:auto;
45
+ margin-top:200px;
46
+ padding:25px;
47
+ line-height:1.5;
48
+ font-size:0.9em;
49
+ text-align:center;
50
+ h2 { color:#C17391; text-transform:uppercase; font-size:0.8em; margin-bottom:15px;}
51
+ p.back { margin-top:25px;}
52
+ p.message { font-size:1.1em;}
53
+ }
54
+
55
+ //
56
+ // Primary login area
57
+ //
58
+ div.loginArea {
59
+ background:#fff;
60
+ width:400px;
61
+ margin:auto;
62
+ margin-top:200px;
63
+ padding-top:50px;
64
+
65
+ h2 {
66
+ text-align:center;
67
+ font-weight:300;
68
+ font-size:1.4em;
69
+ color:#40454D;
70
+ margin-bottom:30px;
71
+ }
72
+ p.field {
73
+ text-align:center;
74
+ margin-bottom:15px;
75
+ input {
76
+ padding:7px;
77
+ border:0;
78
+ border-radius:4px;
79
+ border:1px solid #c0c6ce;
80
+ width:275px;
81
+ font-family:$font;
82
+ font-weight:600;
83
+ background:#eef0f4;
84
+ box-shadow:inset 1px 1px 1px rgba(42,51,61,0.1);
85
+ text-align:center;
86
+ &::-webkit-input-placeholder { color:#b7bfcb; font-weight:normal;}
87
+ &:-moz-placeholder { color:#b7bfcb; font-weight:normal;}
88
+ &::-moz-placeholder { color:#b7bfcb; font-weight:normal;}
89
+ &:-ms-input-placeholder { color:#b7bfcb; font-weight:normal;}
90
+ }
91
+ &:last-child { margin-bottom:0;}
92
+ }
93
+ p.submit {
94
+ padding:15px 0 25px 0;
95
+ text-align:center;
96
+ }
97
+ p.reset {
98
+ background:#353A41;
99
+ font-size:0.9em;
100
+ padding:15px 0;
101
+ text-align:center;
102
+ a { color:rgba(255,255,255,0.5);}
103
+ }
104
+ }
105
+
106
+ }
@@ -0,0 +1 @@
1
+ $font: 'Helvetica Neue', Arial, sans-serif;
@@ -0,0 +1,46 @@
1
+ module Tienda
2
+ class ApplicationController < ActionController::Base
3
+
4
+ before_filter :login_required
5
+
6
+ rescue_from ActiveRecord::DeleteRestrictionError do |e|
7
+ redirect_to request.referer || root_path, alert: e.message
8
+ end
9
+
10
+ rescue_from Tienda::Error do |e|
11
+ @exception = e
12
+ render layout: 'tienda/sub', template: 'tienda/shared/error'
13
+ end
14
+
15
+ private
16
+
17
+ def login_required
18
+ unless logged_in?
19
+ redirect_to login_path
20
+ end
21
+ end
22
+
23
+ def logged_in?
24
+ current_user.is_a?(User)
25
+ end
26
+
27
+ def current_user
28
+ @current_user ||= login_from_session || login_with_demo_mdoe || :false
29
+ end
30
+
31
+ def login_from_session
32
+ if session[:tienda_user_id]
33
+ @user = User.find_by_id(session[:tienda_user_id])
34
+ end
35
+ end
36
+
37
+ def login_with_demo_mdoe
38
+ if Tienda.settings.demo_mode?
39
+ @user = User.first
40
+ end
41
+ end
42
+
43
+ helper_method :current_user, :logged_in?
44
+
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ module Tienda
2
+ class AttachmentsController < Tienda::ApplicationController
3
+
4
+ def destroy
5
+ @attachment = Nifty::Attachments::Attachment.find(params[:id])
6
+ @attachment.destroy
7
+ respond_to do |wants|
8
+ wants.html { redirect_to request.referer, notice: t('tienda.attachments.remove_notice')}
9
+ wants.json { render status: 'complete' }
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ module Tienda
2
+ class CountriesController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :countries }
5
+ before_filter { params[:id] && @country = Tienda::Country.find(params[:id]) }
6
+
7
+ def index
8
+ @countries = Tienda::Country.ordered
9
+ end
10
+
11
+ def new
12
+ @country = Tienda::Country.new
13
+ end
14
+
15
+ def create
16
+ @country = Tienda::Country.new(safe_params)
17
+ if @country.save
18
+ redirect_to :countries, flash: { notice: t('tienda.countries.create_notice') }
19
+ else
20
+ render action: "new"
21
+ end
22
+ end
23
+
24
+ def edit
25
+ end
26
+
27
+ def update
28
+ if @country.update(safe_params)
29
+ redirect_to [:edit, @country], flash: { notice: t('tienda.countries.update_notice') }
30
+ else
31
+ render action: "edit"
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @country.destroy
37
+ redirect_to :countries, flash: { notice: t('tienda.countries.destroy_notice') }
38
+ end
39
+
40
+ private
41
+
42
+ def safe_params
43
+ params[:country].permit(:name, :code2, :code3, :continent, :tld, :currency, :eu_member)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ module Tienda
2
+ class DashboardController < Tienda::ApplicationController
3
+
4
+ def home
5
+ redirect_to :orders
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module Tienda
2
+ class DeliveryServicePricesController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :delivery_services }
5
+ before_filter { @delivery_service = Tienda::DeliveryService.find(params[:delivery_service_id])}
6
+ before_filter { params[:id] && @delivery_service_price = @delivery_service.delivery_service_prices.find(params[:id])}
7
+
8
+ def index
9
+ @delivery_service_prices = @delivery_service.delivery_service_prices.ordered
10
+ end
11
+
12
+ def new
13
+ @delivery_service_price = @delivery_service.delivery_service_prices.build
14
+ end
15
+
16
+ def create
17
+ @delivery_service_price = @delivery_service.delivery_service_prices.build(safe_params)
18
+ if @delivery_service_price.save
19
+ redirect_to [@delivery_service, :delivery_service_prices], notice: t('tienda.delivery_service_prices.create_notice')
20
+ else
21
+ render action: "new"
22
+ end
23
+ end
24
+
25
+ def update
26
+ if @delivery_service_price.update(safe_params)
27
+ redirect_to [@delivery_service, :delivery_service_prices], notice: t('tienda.delivery_service_prices.update_notice')
28
+ else
29
+ render action: "edit"
30
+ end
31
+ end
32
+
33
+ def destroy
34
+ @delivery_service_price.destroy
35
+ redirect_to [@delivery_service, :delivery_service_prices], notice: t('tienda.delivery_service_prices.destroy_notice')
36
+ end
37
+
38
+ private
39
+
40
+ def safe_params
41
+ params[:delivery_service_price].permit(:price, :cost_price, :tax_rate_id, :min_weight, :max_weight, :code, country_ids: [])
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module Tienda
2
+ class DeliveryServicesController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :delivery_services }
5
+ before_filter { params[:id] && @delivery_service = Tienda::DeliveryService.find(params[:id]) }
6
+
7
+ def index
8
+ @delivery_services = Tienda::DeliveryService.all
9
+ end
10
+
11
+ def new
12
+ @delivery_service = Tienda::DeliveryService.new
13
+ end
14
+
15
+ def create
16
+ @delivery_service = Tienda::DeliveryService.new(safe_params)
17
+ if @delivery_service.save
18
+ redirect_to :delivery_services, :flash => {:notice => t('tienda.delivery_services.create_notice')}
19
+ else
20
+ render :action => "new"
21
+ end
22
+ end
23
+
24
+ def edit
25
+ end
26
+
27
+ def update
28
+ if @delivery_service.update(safe_params)
29
+ redirect_to [:edit, @delivery_service], :flash => {:notice => t('tienda.delivery_services.update_notice')}
30
+ else
31
+ render :action => "edit"
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @delivery_service.destroy
37
+ redirect_to :delivery_services, :flash => {:notice =>t('tienda.delivery_services.destroy_notice')}
38
+ end
39
+
40
+ private
41
+
42
+ def safe_params
43
+ params[:delivery_service].permit(:name, :code, :active, :default, :courier, :tracking_url)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,90 @@
1
+ module Tienda
2
+ class OrdersController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :orders }
5
+ before_filter { params[:id] && @order = Tienda::Order.find(params[:id])}
6
+
7
+ def index
8
+ @query = Tienda::Order.ordered.received.includes(:order_items => :ordered_item).page(params[:page]).search(params[:q])
9
+ @orders = @query.result
10
+ end
11
+
12
+ def new
13
+ @order = Tienda::Order.new
14
+ @order.order_items.build(ordered_item_type: 'Tienda::Product')
15
+ end
16
+
17
+ def create
18
+ Tienda::Order.transaction do
19
+ @order = Tienda::Order.new(safe_params)
20
+ @order.status = 'confirming'
21
+ if !request.xhr? && @order.save
22
+ @order.confirm!
23
+ redirect_to @order, notice: t('tienda.orders.create_notice')
24
+ else
25
+ @order.order_items.build(ordered_item_type: 'Tienda::Product')
26
+ render action: "new"
27
+ end
28
+ end
29
+ rescue Tienda::Errors::InsufficientStockToFulfil => e
30
+ flash.now[:alert] = t('tienda.orders.insufficient_stock_order', out_of_stock_items: e.out_of_stock_items.map { |t| t.ordered_item.full_name }.to_sentence)
31
+ render action: 'new'
32
+ end
33
+
34
+ def show
35
+ @payments = @order.payments.to_a
36
+ end
37
+
38
+ def update
39
+ @order.attributes = safe_params
40
+ if !request.xhr? && @order.update_attributes(safe_params)
41
+ redirect_to @order, notice: t('tienda.orders.update_notice')
42
+ else
43
+ render action: "edit"
44
+ end
45
+ end
46
+
47
+ def search
48
+ index
49
+ render action: "index"
50
+ end
51
+
52
+ def accept
53
+ @order.accept!(current_user)
54
+ redirect_to @order, notice: t('tienda.orders.accept_notice')
55
+ rescue Tienda::Errors::PaymentDeclined => e
56
+ redirect_to @order, alert: e.message
57
+ end
58
+
59
+ def reject
60
+ @order.reject!(current_user)
61
+ redirect_to @order, notice: t('tienda.orders.reject_notice')
62
+ rescue Tienda::Errors::PaymentDeclined => e
63
+ redirect_to @order, alert: e.message
64
+ end
65
+
66
+ def ship
67
+ @order.ship!(params[:consignment_number], current_user)
68
+ redirect_to @order, notice: t('tienda.orders.ship_notice')
69
+ end
70
+
71
+ def despatch_note
72
+ render layout: 'tienda/printable'
73
+ end
74
+
75
+ private
76
+
77
+ def safe_params
78
+ params[:order].permit(
79
+ :first_name, :last_name, :company,
80
+ :billing_address1, :billing_address2, :billing_address3, :billing_address4, :billing_postcode, :billing_country_id,
81
+ :separate_delivery_address,
82
+ :delivery_name, :delivery_address1, :delivery_address2, :delivery_address3, :delivery_address4, :delivery_postcode, :delivery_country_id,
83
+ :delivery_price, :delivery_service_id, :delivery_tax_amount,
84
+ :email_address, :phone_number,
85
+ :notes,
86
+ :order_items_attributes => [:ordered_item_id, :ordered_item_type, :quantity, :unit_price, :tax_amount, :id, :weight]
87
+ )
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,33 @@
1
+ module Tienda
2
+ class PaymentsController < ApplicationController
3
+
4
+ before_filter { @order = Tienda::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: t('tienda.payments.create_notice')
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: t('tienda.payments.destroy_notice')
19
+ end
20
+
21
+ def refund
22
+ if request.post?
23
+ @payment.refund!(params[:amount])
24
+ redirect_to @order, notice: t('tienda.payments.refund_notice')
25
+ else
26
+ render layout: false
27
+ end
28
+ rescue Tienda::Errors::RefundFailed => e
29
+ redirect_to @order, alert: e.message
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,47 @@
1
+ module Tienda
2
+ class ProductCategoriesController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :product_categories }
5
+ before_filter { params[:id] && @product_category = Tienda::ProductCategory.find(params[:id]) }
6
+
7
+ def index
8
+ @product_categories = Tienda::ProductCategory.ordered.all
9
+ end
10
+
11
+ def new
12
+ @product_category = Tienda::ProductCategory.new
13
+ end
14
+
15
+ def create
16
+ @product_category = Tienda::ProductCategory.new(safe_params)
17
+ if @product_category.save
18
+ redirect_to :product_categories, flash: { notice: t('tienda.product_category.create_notice') }
19
+ else
20
+ render action: "new"
21
+ end
22
+ end
23
+
24
+ def edit
25
+ end
26
+
27
+ def update
28
+ if @product_category.update(safe_params)
29
+ redirect_to [:edit, @product_category], flash: { notice: t('tienda.product_category.update_notice') }
30
+ else
31
+ render action: "edit"
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @product_category.destroy
37
+ redirect_to :product_categories, flash: { notice: t('tienda.product_category.destroy_notice') }
38
+ end
39
+
40
+ private
41
+
42
+ def safe_params
43
+ params[:product_category].permit(:name, :permalink, :description, :image_file)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,58 @@
1
+ module Tienda
2
+ class ProductsController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :products }
5
+ before_filter { params[:id] && @product = Tienda::Product.root.find(params[:id]) }
6
+
7
+ def index
8
+ @products = Tienda::Product.root.includes(:stock_level_adjustments, :default_image, :product_category, :variants).order(:name).group_by(&:product_category).sort_by { |cat,pro| cat.name }
9
+ end
10
+
11
+ def new
12
+ @product = Tienda::Product.new
13
+ end
14
+
15
+ def create
16
+ @product = Tienda::Product.new(safe_params)
17
+ if @product.save
18
+ redirect_to :products, flash: { notice: t('tienda.products.create_notice') }
19
+ else
20
+ render action: "new"
21
+ end
22
+ end
23
+
24
+ def edit
25
+ end
26
+
27
+ def update
28
+ if @product.update(safe_params)
29
+ redirect_to [:edit, @product], flash: { notice: t('tienda.products.update_notice') }
30
+ else
31
+ render action: "edit"
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @product.destroy
37
+ redirect_to :products, flash: { notice: t('tienda.products.destroy_notice')}
38
+ end
39
+
40
+ def import
41
+ if request.post?
42
+ if params[:import].nil?
43
+ redirect_to import_products_path, flash: { alert: I18n.t('tienda.imports.errors.no_file') }
44
+ else
45
+ Tienda::Product.import(params[:import][:import_file])
46
+ redirect_to products_path, flash: { notice: I18n.t("tienda.products.imports.success") }
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def safe_params
54
+ params[:product].permit(:product_category_id, :name, :sku, :permalink, :description, :short_description, :weight, :price, :cost_price, :tax_rate_id, :stock_control, :default_image_file, :data_sheet_file, :active, :featured, :in_the_box, :product_attributes_array => [:key, :value, :searchable, :public])
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ module Tienda
2
+ class SessionsController < Tienda::ApplicationController
3
+
4
+ layout 'tienda/sub'
5
+ skip_before_filter :login_required, only: [:new, :create, :reset]
6
+
7
+ def create
8
+ if user = Tienda::User.authenticate(params[:email_address], params[:password])
9
+ session[:tienda_user_id] = user.id
10
+ redirect_to :orders
11
+ else
12
+ flash.now[:alert] = t('tienda.sessions.create_alert')
13
+ render action: "new"
14
+ end
15
+ end
16
+
17
+ def destroy
18
+ session[:tienda_user_id] = nil
19
+ redirect_to :login
20
+ end
21
+
22
+ def reset
23
+
24
+ if request.post?
25
+ if user = Tienda::User.find_by_email_address(params[:email_address])
26
+ user.reset_password!
27
+ redirect_to login_path(email_address: params[:email_address]), notice: t('tienda.sessions.reset_notice', email_address: user.email_address)
28
+ else
29
+ flash.now[:alert] = t('tienda.sessions.reset_alert')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ module Tienda
2
+ class SettingsController < ApplicationController
3
+
4
+ before_filter { @active_nav = :settings }
5
+
6
+ def update
7
+ if Tienda.settings.demo_mode?
8
+ raise Tienda::Error, t('tienda.settings.demo_mode_error')
9
+ end
10
+
11
+ Tienda::Setting.update_from_hash(params[:settings].permit!)
12
+ redirect_to :settings, notice: t('tienda.settings.update_notice')
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ module Tienda
2
+ class StockLevelAdjustmentsController < ApplicationController
3
+
4
+ SUITABLE_OBJECTS = ['Tienda::Product']
5
+ before_filter do
6
+ raise Tienda::Error, t('tienda.stock_level_adjustments.invalid_item_type', suitable_objects: SUITABLE_OBJECTS.to_sentence) unless SUITABLE_OBJECTS.include?(params[:item_type])
7
+ @item = params[:item_type].constantize.find(params[:item_id].to_i)
8
+ end
9
+ before_filter { params[:id] && @sla = @item.stock_level_adjustments.find(params[:id].to_i) }
10
+
11
+ def index
12
+ @stock_level_adjustments = @item.stock_level_adjustments.ordered.page(params[:page]).per(10)
13
+ @new_sla = @item.stock_level_adjustments.build if @new_sla.nil?
14
+ if request.xhr?
15
+ render action: 'index', layout: false
16
+ end
17
+ end
18
+
19
+ def create
20
+ @new_sla = @item.stock_level_adjustments.build(params[:stock_level_adjustment].permit(:description, :adjustment))
21
+ if @new_sla.save
22
+ if request.xhr?
23
+ @new_sla = @item.stock_level_adjustments.build
24
+ index
25
+ else
26
+ redirect_to stock_level_adjustments_path(item_id: params[:item_id], item_type: params[:item_type]), notice: t('tienda.stock_level_adjustments.create_notice')
27
+ end
28
+ else
29
+ if request.xhr?
30
+ render text: @new_sla.errors.full_messages.to_sentence, status: 422
31
+ else
32
+ index
33
+ flash.now[:alert] = @new_sla.errors.full_messages.to_sentence
34
+ render action: "index"
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ module Tienda
2
+ class TaxRatesController < Tienda::ApplicationController
3
+
4
+ before_filter { @active_nav = :tax_rates }
5
+ before_filter { params[:id] && @tax_rate = Tienda::TaxRate.find(params[:id]) }
6
+
7
+ def index
8
+ @tax_rates = Tienda::TaxRate.ordered.all
9
+ end
10
+
11
+ def new
12
+ @tax_rate = Tienda::TaxRate.new
13
+ render action: "form"
14
+ end
15
+
16
+ def create
17
+ @tax_rate = Tienda::TaxRate.new(safe_params)
18
+ if @tax_rate.save
19
+ redirect_to :tax_rates, flash: { notice: t('tienda.tax_rates.create_notice') }
20
+ else
21
+ render action: "form"
22
+ end
23
+ end
24
+
25
+ def edit
26
+ render action: "form"
27
+ end
28
+
29
+ def update
30
+ if @tax_rate.update(safe_params)
31
+ redirect_to [:edit, @tax_rate], flash: { notice: t('tienda.tax_rates.update_notice') }
32
+ else
33
+ render action: "form"
34
+ end
35
+ end
36
+
37
+ def destroy
38
+ @tax_rate.destroy
39
+ redirect_to :tax_rates, flash: { notice: t('tienda.tax_rates.destroy_notice') }
40
+ end
41
+
42
+ private
43
+
44
+ def safe_params
45
+ params[:tax_rate].permit(:name, :rate, :address_type, country_ids: [])
46
+ end
47
+
48
+ end
49
+ end