stall 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -21
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/input.coffee +8 -1
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/variant.coffee +9 -0
- data/app/assets/javascripts/stall.coffee +7 -1
- data/app/assets/javascripts/stall/add-to-cart-form.coffee +1 -4
- data/app/assets/javascripts/stall/products-filters.coffee +29 -0
- data/app/assets/stylesheets/para/stall.sass +5 -0
- data/app/assets/stylesheets/stall.sass +0 -0
- data/app/controllers/stall/checkout/steps_controller.rb +6 -5
- data/app/controllers/stall/checkout_base_controller.rb +14 -0
- data/app/controllers/stall/checkouts_controller.rb +7 -4
- data/app/controllers/stall/curated_product_lists_controller.rb +10 -0
- data/app/controllers/stall/line_items_controller.rb +1 -5
- data/app/controllers/stall/manufacturers_controller.rb +12 -0
- data/app/controllers/stall/omniauth_callbacks_controller.rb +49 -0
- data/app/controllers/stall/product_categories_controller.rb +13 -0
- data/app/controllers/stall/products_breadcrumbs.rb +16 -0
- data/app/controllers/stall/products_controller.rb +20 -0
- data/app/controllers/stall/products_search.rb +11 -0
- data/app/helpers/stall/customers_helper.rb +0 -10
- data/app/helpers/stall/omniauth_helper.rb +7 -0
- data/app/helpers/stall/prices_helper.rb +12 -0
- data/app/helpers/stall/products_filters_helper.rb +34 -0
- data/app/mailers/stall/customer_mailer.rb +4 -3
- data/app/models/curated_list_product.rb +3 -0
- data/app/models/curated_product_list.rb +3 -0
- data/app/models/image.rb +3 -0
- data/app/models/product_suggestion.rb +3 -0
- data/app/models/stall/models/curated_list_product.rb +15 -0
- data/app/models/stall/models/curated_product_list.rb +22 -0
- data/app/models/stall/models/customer.rb +5 -8
- data/app/models/stall/models/image.rb +21 -0
- data/app/models/stall/models/manufacturer.rb +4 -0
- data/app/models/stall/models/product.rb +30 -7
- data/app/models/stall/models/product_category.rb +5 -2
- data/app/models/stall/models/product_list.rb +1 -1
- data/app/models/stall/models/product_suggestion.rb +14 -0
- data/app/models/stall/models/shipment.rb +0 -2
- data/app/models/stall/models/user.rb +18 -0
- data/app/models/stall/models/user_omniauth_account.rb +13 -0
- data/app/models/stall/models/variant.rb +11 -11
- data/app/models/user.rb +3 -0
- data/app/models/user_omniauth_account.rb +3 -0
- data/app/services/stall/add_to_cart_service.rb +19 -4
- data/app/services/stall/available_stocks_service.rb +11 -0
- data/app/services/stall/cart_credit_note_creation_service.rb +4 -0
- data/app/services/stall/cart_payment_validation_service.rb +5 -3
- data/app/services/stall/credit_usage_service.rb +8 -2
- data/app/services/stall/omniauth_user_authentication_service.rb +48 -0
- data/app/services/stall/product_list_staleness_handling_service.rb +6 -3
- data/app/services/stall/products_search_service.rb +23 -0
- data/app/services/stall/shipping_notification_service.rb +1 -1
- data/app/views/admin/carts/_filters.html.haml +10 -4
- data/app/views/admin/carts/_form.html.haml +9 -9
- data/app/views/admin/manufacturers/_form.html.haml +7 -0
- data/app/views/admin/manufacturers/_table.html.haml +8 -0
- data/app/views/admin/product_categories/_form.html.haml +7 -0
- data/app/views/admin/products/_form.html.haml +23 -0
- data/app/views/admin/products/_table.html.haml +4 -2
- data/app/views/checkout/steps/_informations.html.haml +2 -2
- data/app/views/para/admin/resources/_variant_row.html.haml +9 -1
- data/app/views/para/admin/resources/_variant_row_header.html.haml +14 -0
- data/app/views/para/stall/inputs/_variant_select.html.haml +3 -3
- data/app/views/para/stall/inputs/_variants_matrix.html.haml +7 -16
- data/app/views/para/stall/inputs/shipping_notes/new.html.haml +22 -0
- data/app/views/para/stall/inputs/shipping_notes/sent.html.haml +11 -0
- data/app/views/stall/carts/_cart.html.haml +1 -1
- data/app/views/stall/credit_note_adjustments/_form.html.haml +1 -1
- data/app/views/stall/curated_product_lists/show.html.haml +8 -0
- data/app/views/stall/customers/_fields.html.haml +17 -5
- data/app/views/stall/customers/_sign_in.html.haml +22 -10
- data/app/views/stall/line_items/_form.html.haml +2 -3
- data/app/views/stall/manufacturers/show.html.haml +8 -0
- data/app/views/stall/product_categories/show.html.haml +8 -0
- data/app/views/stall/products/_filters.html.haml +4 -0
- data/app/views/stall/products/_list.html.haml +7 -0
- data/app/views/stall/products/_product.html.haml +4 -0
- data/app/views/stall/products/_product_details.html.haml +13 -0
- data/app/views/stall/products/filters/_category_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_manufacturer_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_price_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_property_filter.html.haml +2 -0
- data/app/views/stall/products/index.html.haml +8 -0
- data/app/views/stall/products/show.html.haml +26 -0
- data/config/locales/stall.fr.yml +97 -11
- data/db/migrate/20170221094450_add_slug_to_stall_manufacturers.rb +5 -0
- data/db/migrate/20170303122616_create_stall_product_suggestions.rb +13 -0
- data/db/migrate/20170303151939_add_position_to_stall_manufacturers.rb +5 -0
- data/db/migrate/20170308162740_create_stall_curated_product_lists.rb +10 -0
- data/db/migrate/20170308163532_create_stall_curated_list_products.rb +14 -0
- data/db/migrate/20170317103740_create_stall_users.rb +28 -0
- data/db/migrate/20170317104332_create_stall_user_omniauth_accounts.rb +14 -0
- data/db/migrate/20170320133513_fix_curated_product_list_bad_foreign_key.rb +6 -0
- data/db/migrate/20170321104203_create_stall_images.rb +11 -0
- data/db/migrate/20170321112248_remove_image_attachment_to_stall_products.rb +5 -0
- data/db/migrate/20170411134756_add_stock_to_stall_variants.rb +5 -0
- data/lib/ext/ransack.rb +13 -0
- data/lib/generators/stall/install/templates/initializer.rb +50 -15
- data/lib/generators/stall/service/service_generator.rb +0 -4
- data/lib/generators/stall/view/view_generator.rb +10 -8
- data/lib/para/stall/inputs/variant_select_input.rb +11 -1
- data/lib/para/stall/inputs/variants_matrix_input.rb +12 -6
- data/lib/stall.rb +14 -0
- data/lib/stall/addressable.rb +2 -2
- data/lib/stall/addresses/copy_source_to_target.rb +7 -3
- data/lib/stall/addresses/prefill_target_from_source.rb +4 -2
- data/lib/stall/cart_helper.rb +3 -3
- data/lib/stall/carts_cleaner.rb +2 -2
- data/lib/stall/checkout/informations_checkout_step.rb +2 -2
- data/lib/stall/config.rb +29 -9
- data/lib/stall/engine.rb +28 -13
- data/lib/stall/omniauth_provider.rb +41 -0
- data/lib/stall/payable.rb +3 -1
- data/lib/stall/product_filters.rb +12 -0
- data/lib/stall/product_filters/base_filter.rb +43 -0
- data/lib/stall/product_filters/builder.rb +59 -0
- data/lib/stall/product_filters/category_filter.rb +28 -0
- data/lib/stall/product_filters/manufacturer_filter.rb +19 -0
- data/lib/stall/product_filters/price_filter.rb +39 -0
- data/lib/stall/product_filters/property_filter.rb +38 -0
- data/lib/stall/routes.rb +40 -0
- data/lib/stall/shipping/calculator.rb +3 -1
- data/lib/stall/version.rb +1 -1
- metadata +158 -7
- data/app/assets/stylesheets/stall/carts.css +0 -4
@@ -0,0 +1,11 @@
|
|
1
|
+
= modal id: "shipment-modal-#{ @cart.id }", fade: false do |modal|
|
2
|
+
= modal.header do
|
3
|
+
= t('para.stall.shipping_note.sent')
|
4
|
+
|
5
|
+
= modal.body do
|
6
|
+
%p= t('para.stall.shipping_note.sent_description').html_safe
|
7
|
+
|
8
|
+
= modal.footer do
|
9
|
+
%button.btn.btn-default{ type: 'button', data: { dismiss: 'modal' } }
|
10
|
+
= t('stall.shared.close')
|
11
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
- if
|
1
|
+
- if user_signed_in? && available_customer_credit_for?(cart) && !cart.paid?
|
2
2
|
= simple_form_for cart, url: cart_credit_path(cart), method: (credit_used_for?(@cart) ? :delete : :patch), html: { class: 'cart-credit-form', data: { :'cart-credit-form' => true } } do |form|
|
3
3
|
= hidden_field_tag :_return_to, request.fullpath
|
4
4
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
-# When stall a user is signed in, a customer autoatically exist and is assigned
|
2
2
|
-# to the cart, by default, we notify the visitor that he's signed in and will
|
3
3
|
-# order with that account, making customer and user related fields unnecessary
|
4
|
-
- if
|
4
|
+
- if user_signed_in?
|
5
5
|
.alert.alert-info
|
6
6
|
%i.fa.fa-info-circle
|
7
|
-
= t('stall.checkout.informations.signed_in_as', email:
|
7
|
+
= t('stall.checkout.informations.signed_in_as', email: current_user.email)
|
8
8
|
|
9
9
|
- else
|
10
10
|
-# The `#with_errors_from_user` helper ensures that user e-mail errors, like
|
@@ -14,9 +14,21 @@
|
|
14
14
|
|
15
15
|
= form.fields_for :customer do |customer_form|
|
16
16
|
= customer_form.fields_for :user, customer_form.object.user_or_default do |user_form|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
.collapse{ class: ('in' if params[:create_account] == '1'), data: { :'user-fields' => true } }
|
18
|
+
%fieldset
|
19
|
+
%legend.password-sign-up= t('stall.checkout.sign_in.password_sign_up')
|
20
|
+
|
21
|
+
= user_form.input :password
|
22
|
+
= user_form.input :password_confirmation
|
23
|
+
|
24
|
+
- if Stall.config.omniauth_providers.any?
|
25
|
+
%fieldset
|
26
|
+
%legend.omniauth-sign-up= t('stall.checkout.sign_in.omniauth_sign_up')
|
27
|
+
|
28
|
+
- Stall.config.omniauth_providers.each do |provider|
|
29
|
+
= link_to user_omniauth_redirect_path(provider.name, _redirect_to: request.path), class: 'btn btn-default' do
|
30
|
+
= fa_icon provider.icon
|
31
|
+
= t('stall.omniauth.sign_in_with', provider: provider.display_name)
|
20
32
|
|
21
33
|
%p.help-block
|
22
34
|
%label
|
@@ -6,15 +6,27 @@
|
|
6
6
|
= t('stall.checkout.sign_in.click_to_sign_in')
|
7
7
|
|
8
8
|
#sign-in-form.panel-body.collapse{ data: { :'sign-in-form' => true } }
|
9
|
-
%
|
10
|
-
= t('stall.checkout.sign_in.
|
9
|
+
%fieldset
|
10
|
+
%legend.email-sign-in= t('stall.checkout.sign_in.email_sign_in')
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
.col-md-6
|
15
|
-
= form.input :email
|
16
|
-
.col-md-6
|
17
|
-
= form.input :password
|
12
|
+
%p.help-block
|
13
|
+
= t('stall.checkout.sign_in.sign_in_instructions', label: t('stall.checkout.sign_in.button_label'))
|
18
14
|
|
19
|
-
|
20
|
-
|
15
|
+
= simple_form_for resource, as: resource_name, url: session_path(resource_name), remote: true, html: { data: { :'stall-remote-sign-in-form' => true } } do |form|
|
16
|
+
.row
|
17
|
+
.col-md-6
|
18
|
+
= form.input :email
|
19
|
+
.col-md-6
|
20
|
+
= form.input :password
|
21
|
+
|
22
|
+
%button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'sign-in-submit-btn' => true, :'loading-text' => t('stall.shared.sending') } }
|
23
|
+
= t('stall.checkout.sign_in.button_label')
|
24
|
+
|
25
|
+
- if Stall.config.omniauth_providers.any?
|
26
|
+
%fieldset
|
27
|
+
%legend.omniauth-sign-in= t('stall.checkout.sign_in.omniauth_sign_in')
|
28
|
+
|
29
|
+
- Stall.config.omniauth_providers.each do |provider|
|
30
|
+
= link_to user_omniauth_redirect_path(provider.name, _redirect_to: request.path), class: 'btn btn-default' do
|
31
|
+
= fa_icon provider.icon
|
32
|
+
= t('stall.omniauth.sign_in_with', provider: provider.display_name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
= simple_form_for line_item, as: :line_item, url: cart_line_items_path(cart), remote: true, data: { :'add-to-cart-form' => true, :'error-messages' => { choose: t('stall.line_items.errors.choose'), quantity: t('stall.line_items.errors.quantity') } } do |form|
|
2
|
-
= form.hidden_field :sellable_type
|
3
|
-
= form.
|
2
|
+
= form.hidden_field :sellable_type, value: 'Variant'
|
3
|
+
= form.input_field :sellable, as: :variant_select, product: @product
|
4
4
|
|
5
5
|
.input-group
|
6
6
|
= form.input_field :quantity, spinner: false, value: 1, class: 'form-group', data: { :'quantity-field' => true }
|
@@ -9,4 +9,3 @@
|
|
9
9
|
%button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'loading-text' => t('stall.shared.sending') } }
|
10
10
|
%i.fa.fa-shopping-cart
|
11
11
|
= t('stall.line_items.form.add_to_cart')
|
12
|
-
|
@@ -0,0 +1,4 @@
|
|
1
|
+
.products-filters
|
2
|
+
= search_form_for search.form, url: request.path, as: :search, builder: SimpleForm::FormBuilder, html: { class: 'products-filters-form', data: { :'products-filters' => true } } do |form|
|
3
|
+
- product_filters_for(products).each do |filter|
|
4
|
+
= render filter.rendering_options(locals: { form: form })
|
@@ -0,0 +1,13 @@
|
|
1
|
+
.row.product-details
|
2
|
+
.col-md-12
|
3
|
+
%ul.nav.nav-tabs{ data: { tabs: 'tabs' } }
|
4
|
+
- product_details.each_with_index do |tab, index|
|
5
|
+
%li{ class: "#{'active' if index == 0}" }
|
6
|
+
= link_to tab.name, "##{tab.id}", data: { toggle: 'tab' }
|
7
|
+
|
8
|
+
.tab-content
|
9
|
+
- product_details.each_with_index do |tab, index|
|
10
|
+
.tab-pane{ id: "#{tab.id}", class: "#{'active' if index == 0}" }
|
11
|
+
= tab.content&.html_safe
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,2 @@
|
|
1
|
+
.filter{ data: { :'filter' => 'price', :'filter-submission' => 'slide' } }
|
2
|
+
= form.input filter.param, as: :slider, label: filter.label, required: false, min: filter.min, max: filter.max, values: [filter.min, filter.max], range: true, input_html: { data: { :'slider-ticks' => filter.ticks, :'slider-ticks-labels' => filter.ticks } }
|
@@ -0,0 +1,26 @@
|
|
1
|
+
.product-page
|
2
|
+
.col-md-4
|
3
|
+
.product-images
|
4
|
+
= image_tag @product.image.url(:show), class: 'img-responsive'
|
5
|
+
|
6
|
+
.col-md-8
|
7
|
+
%h1.product-title= @product.name
|
8
|
+
|
9
|
+
= displayed_price_for_variants(@product.variants)
|
10
|
+
|
11
|
+
= add_to_cart_form_for(@product)
|
12
|
+
|
13
|
+
.description
|
14
|
+
= @product.description.try(:html_safe)
|
15
|
+
|
16
|
+
- if @product.product_details.length > 0
|
17
|
+
= render 'stall/products/product_details', product_details: @product.product_details
|
18
|
+
|
19
|
+
- if @product.suggested_products.length > 0
|
20
|
+
.related.products
|
21
|
+
%h2
|
22
|
+
= t('stall.products.suggested_products.title')
|
23
|
+
|
24
|
+
.products.row
|
25
|
+
- @product.suggested_products.each do |suggested_product|
|
26
|
+
= render partial: 'stall/products/product', locals: { product: suggested_product }
|
data/config/locales/stall.fr.yml
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
fr:
|
2
2
|
para:
|
3
3
|
stall:
|
4
|
+
cart:
|
5
|
+
filters:
|
6
|
+
paid_after: Payé après le
|
7
|
+
paid_before: Payé avant le
|
4
8
|
variants_matrix:
|
5
9
|
enabled: "Publier ?"
|
6
10
|
price: "Prix"
|
@@ -8,6 +12,7 @@ fr:
|
|
8
12
|
choose_properties_to_build_variants: |
|
9
13
|
Choisissez les propriétés ainsi que les valeurs dont vous disposez
|
10
14
|
pour créer automatiquement les déclinaisons de votre produit.
|
15
|
+
apply_to_all: "Appliquer à toutes les déclinaisons"
|
11
16
|
|
12
17
|
variant_select:
|
13
18
|
property_placeholder: "Choisissez une option ..."
|
@@ -35,6 +40,21 @@ fr:
|
|
35
40
|
payment: "Paiement"
|
36
41
|
line_items: "Produits"
|
37
42
|
|
43
|
+
product:
|
44
|
+
informations: "Informations"
|
45
|
+
images: "Images"
|
46
|
+
descriptions: "Descriptions"
|
47
|
+
variants: "Déclinaisons"
|
48
|
+
|
49
|
+
components:
|
50
|
+
section:
|
51
|
+
products: "Catalogue"
|
52
|
+
component:
|
53
|
+
products: "Produits"
|
54
|
+
product_categories: "Catégories de produits"
|
55
|
+
properties: "Propriétés de produit"
|
56
|
+
manufacturers: "Fabricants"
|
57
|
+
|
38
58
|
stall:
|
39
59
|
shared:
|
40
60
|
cancel: "Annuler"
|
@@ -42,6 +62,18 @@ fr:
|
|
42
62
|
send: "Envoyer"
|
43
63
|
sending: "Envoi en cours ..."
|
44
64
|
|
65
|
+
products:
|
66
|
+
index:
|
67
|
+
title: "Notre catalogue"
|
68
|
+
suggester_products:
|
69
|
+
title: "Vous pourriez aussi aimer ..."
|
70
|
+
prices:
|
71
|
+
from: "À partir de %{price}"
|
72
|
+
filters:
|
73
|
+
category_filter: "Catégorie"
|
74
|
+
manufacturer_filter: "Fabricant"
|
75
|
+
price_filter: "Prix"
|
76
|
+
|
45
77
|
carts:
|
46
78
|
actions:
|
47
79
|
view_cart: "Voir mon panier"
|
@@ -93,11 +125,17 @@ fr:
|
|
93
125
|
sign_in:
|
94
126
|
already_have_an_account: "J'ai déjà un compte :"
|
95
127
|
click_to_sign_in: "Cliquez-ici pour vous connecter"
|
128
|
+
|
96
129
|
sign_in_instructions: |
|
97
130
|
Renseigez dans les champs suivant vos identifiants de connexion puis
|
98
131
|
cliquez sur le bouton "%{label}"
|
99
132
|
button_label: "Me connecter"
|
100
133
|
|
134
|
+
email_sign_in: "Connexion par e-mail"
|
135
|
+
omniauth_sign_in: "ou"
|
136
|
+
password_sign_up: "Renseigner un mot de passe"
|
137
|
+
omniauth_sign_up: "ou"
|
138
|
+
|
101
139
|
payment:
|
102
140
|
title: "Paiement"
|
103
141
|
error: |
|
@@ -173,6 +211,9 @@ fr:
|
|
173
211
|
order_paid_email:
|
174
212
|
subject: "Une nouvelle commande a été passée sur le site - %{ref}"
|
175
213
|
|
214
|
+
omniauth:
|
215
|
+
sign_in_with: "%{provider}"
|
216
|
+
|
176
217
|
activerecord:
|
177
218
|
enums:
|
178
219
|
cart:
|
@@ -190,19 +231,51 @@ fr:
|
|
190
231
|
paid: "Payé"
|
191
232
|
|
192
233
|
models:
|
193
|
-
line_item:
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
234
|
+
line_item:
|
235
|
+
one: "Produit"
|
236
|
+
other: "Produits"
|
237
|
+
customer:
|
238
|
+
one: "Client"
|
239
|
+
other: "Clients"
|
240
|
+
address:
|
241
|
+
one: "Adresse"
|
242
|
+
other: "Adresses"
|
243
|
+
cart:
|
244
|
+
one: "Panier"
|
245
|
+
other: "Paniers"
|
246
|
+
shipment:
|
247
|
+
one: "Livraison"
|
248
|
+
other: "Livraisons"
|
249
|
+
payment:
|
250
|
+
one: "Paiement"
|
251
|
+
other: "Paiements"
|
252
|
+
product:
|
253
|
+
one: "Produit"
|
254
|
+
other: "Produits"
|
255
|
+
product_category:
|
256
|
+
one: "Catégorie"
|
257
|
+
other: "Catégories"
|
258
|
+
variant:
|
259
|
+
one: "Déclinaison"
|
260
|
+
other: "Déclinaisons"
|
261
|
+
product_detail:
|
262
|
+
one: "Bloc de description"
|
263
|
+
other: "Blocs de description"
|
264
|
+
manufacturer:
|
265
|
+
one: "Fabricant"
|
266
|
+
other: "Fabricants"
|
267
|
+
curated_product_list:
|
268
|
+
one: "Curated list"
|
269
|
+
other: "Curated lists"
|
270
|
+
curated_list_product:
|
271
|
+
one: "Produit de curated list"
|
272
|
+
other: "Produits de curated list"
|
204
273
|
|
205
274
|
attributes:
|
275
|
+
curated_product_list:
|
276
|
+
curated_list_products: Produits
|
277
|
+
curated_list_product:
|
278
|
+
product: Produit
|
206
279
|
line_item:
|
207
280
|
sellable: "Produit source"
|
208
281
|
name: "Nom du produit"
|
@@ -268,10 +341,21 @@ fr:
|
|
268
341
|
product_category: "Catégorie de produit"
|
269
342
|
name: "Nom du produit"
|
270
343
|
slug: "Fragment d'URL"
|
344
|
+
images: Images du produit
|
271
345
|
description: "Description du produit"
|
272
346
|
properties: "Propriétés"
|
273
347
|
variants: "Déclinaisons"
|
274
348
|
product_details: "Blocs de description produit"
|
349
|
+
manufacturer: "Fabricant"
|
350
|
+
suggested_products: "Produits suggérés"
|
351
|
+
price: "Prix"
|
352
|
+
product_category:
|
353
|
+
name: "Nom"
|
354
|
+
slug: "Fragment d'URL"
|
355
|
+
position: "Position"
|
356
|
+
parent: "Catégorie parente"
|
357
|
+
children: "Catégories enfant"
|
358
|
+
products: "Produits"
|
275
359
|
product_detail:
|
276
360
|
name: "Titre"
|
277
361
|
content: "Contenu"
|
@@ -279,6 +363,8 @@ fr:
|
|
279
363
|
name: "Nom du fabricant"
|
280
364
|
logo: "Logo"
|
281
365
|
products: "Produits"
|
366
|
+
image:
|
367
|
+
file: Image
|
282
368
|
|
283
369
|
simple_form:
|
284
370
|
placeholders:
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateStallProductSuggestions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :stall_product_suggestions do |t|
|
4
|
+
t.references :product, index: true
|
5
|
+
t.references :suggestion, index: true
|
6
|
+
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
|
10
|
+
add_foreign_key :stall_product_suggestions, :stall_products, column: :product_id
|
11
|
+
add_foreign_key :stall_product_suggestions, :stall_products, column: :suggestion_id
|
12
|
+
end
|
13
|
+
end
|