cloudrider 0.3.0 → 0.3.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -1
- data/cloudrider.gemspec +1 -0
- data/generica/.gitignore +18 -0
- data/generica/Gemfile +8 -1
- data/generica/Gemfile.lock +3 -0
- data/generica/app/assets/javascripts/apiv1.js.ls +6 -1
- data/generica/app/assets/javascripts/components/offers-summary.js.em +2 -0
- data/generica/app/assets/javascripts/components/picture-chunk.js.em +17 -0
- data/generica/app/assets/javascripts/components/pictures-group.js.em +21 -0
- data/generica/app/assets/javascripts/components/search-and-filter.js.em +4 -0
- data/generica/app/assets/javascripts/components/site-nav.js.em +5 -1
- data/generica/app/assets/javascripts/components/taggable-field.js.em +28 -0
- data/generica/app/assets/javascripts/components/tree/taxon-li.js.em +6 -2
- data/generica/app/assets/javascripts/controllers/index_controller.js.em +19 -2
- data/generica/app/assets/javascripts/controllers/modals/login_controller.js.em +23 -9
- data/generica/app/assets/javascripts/controllers/modals/register_controller.js.em +24 -0
- data/generica/app/assets/javascripts/controllers/products/index_controller.js.em +23 -13
- data/generica/app/assets/javascripts/controllers/products/product/offers/new_controller.js.em +17 -0
- data/generica/app/assets/javascripts/controllers/users/offers/index_controller.js.em +10 -0
- data/generica/app/assets/javascripts/controllers/users/product/edit_controller.js.em +31 -0
- data/generica/app/assets/javascripts/controllers/users/products/index_controller.js.em +8 -0
- data/generica/app/assets/javascripts/controllers/users/products/new_controller.js.em +22 -0
- data/generica/app/assets/javascripts/controllers/users/products/slice_controller.js.em +4 -0
- data/generica/app/assets/javascripts/helpers/filte_previewer.js.ls +21 -0
- data/generica/app/assets/javascripts/helpers/listing_picture.js.em +17 -0
- data/generica/app/assets/javascripts/models/offer.js.em +9 -8
- data/generica/app/assets/javascripts/models/user.js.em +12 -0
- data/generica/app/assets/javascripts/models/users/product.js.em +12 -0
- data/generica/app/assets/javascripts/routes/application_route.js.em +10 -2
- data/generica/app/assets/javascripts/routes/products/index_route.js.em +23 -2
- data/generica/app/assets/javascripts/routes/products/product/offers/new_route.js.em +18 -0
- data/generica/app/assets/javascripts/routes/users/offers/index_route.js.em +1 -0
- data/generica/app/assets/javascripts/routes/users/product_route.js.em +3 -0
- data/generica/app/assets/javascripts/routes/users/products/index_route.js.em +3 -0
- data/generica/app/assets/javascripts/routes/users/products/new_route.js.em +3 -0
- data/generica/app/assets/javascripts/templates/admin/product/edit.emblem +2 -0
- data/generica/app/assets/javascripts/templates/admin/products/_form-core.emblem +44 -0
- data/generica/app/assets/javascripts/templates/admin/products/new.emblem +4 -42
- data/generica/app/assets/javascripts/templates/components/offers-summary.emblem +9 -0
- data/generica/app/assets/javascripts/templates/components/picture-chunk.emblem +9 -0
- data/generica/app/assets/javascripts/templates/components/pictures-group.emblem +6 -0
- data/generica/app/assets/javascripts/templates/components/search-and-filter.emblem +5 -1
- data/generica/app/assets/javascripts/templates/components/taggable-field.emblem +1 -0
- data/generica/app/assets/javascripts/templates/modals/register.emblem +57 -0
- data/generica/app/assets/javascripts/templates/products/product/offers/_anonymous-form.emblem +11 -0
- data/generica/app/assets/javascripts/templates/products/product/offers/_offer-form.emblem +55 -0
- data/generica/app/assets/javascripts/templates/products/product/offers/new.emblem +37 -0
- data/generica/app/assets/javascripts/templates/products/product/show.emblem +26 -1
- data/generica/app/assets/javascripts/templates/users.emblem +24 -0
- data/generica/app/assets/javascripts/templates/users/index.emblem +3 -0
- data/generica/app/assets/javascripts/templates/users/offers/index.emblem +25 -0
- data/generica/app/assets/javascripts/templates/users/offers/slice.emblem +31 -0
- data/generica/app/assets/javascripts/templates/users/product/edit.emblem +82 -0
- data/generica/app/assets/javascripts/templates/users/products/index.emblem +22 -0
- data/generica/app/assets/javascripts/templates/users/products/new.emblem +28 -0
- data/generica/app/assets/javascripts/templates/users/products/slice.emblem +27 -0
- data/generica/app/assets/stylesheets/apiv1/_application.css.scss +4 -0
- data/generica/app/assets/stylesheets/apiv1/components/_offers-summary.css.scss +20 -0
- data/generica/app/assets/stylesheets/apiv1/components/_pictures-group.css.scss +32 -0
- data/generica/app/assets/stylesheets/apiv1/components/_taggable-field.css.scss +32 -0
- data/generica/app/assets/stylesheets/apiv1/products/product/offers/_new.css.scss +8 -0
- data/generica/app/controllers/admin/base_controller.rb +1 -1
- data/generica/app/controllers/admin/sessions/destroy_controller.rb +16 -0
- data/generica/app/controllers/apiv1/offers/create_controller.rb +30 -0
- data/generica/app/controllers/apiv1/offers/index_controller.rb +22 -0
- data/generica/app/controllers/apiv1/offers/show_controller.rb +12 -0
- data/generica/app/controllers/apiv1/products/destroy_controller.rb +6 -0
- data/generica/app/controllers/apiv1/products/index_controller.rb +8 -2
- data/generica/app/controllers/apiv1/products/show_controller.rb +7 -3
- data/generica/app/controllers/apiv1/taxons/index_controller.rb +5 -1
- data/generica/app/controllers/apiv1/users/create_controller.rb +17 -0
- data/generica/app/controllers/apiv1/users/show_controller.rb +12 -0
- data/generica/app/controllers/apiv1/users_controller.rb +9 -0
- data/generica/app/controllers/application_controller.rb +3 -0
- data/generica/app/controllers/users/offers/create_controller.rb +26 -0
- data/generica/app/controllers/users/products/create_controller.rb +26 -0
- data/generica/app/controllers/users/products/update_controller.rb +35 -0
- data/generica/app/mailers/apiv1/aggregate_mailer.rb +13 -0
- data/generica/app/mailers/apiv1/aggregate_mailer/summary_context.rb +121 -0
- data/generica/app/mailers/apiv1/notifications_mailer.rb +19 -0
- data/generica/app/mailers/apiv1/notifications_mailer/new_offer_context.rb +53 -0
- data/generica/app/models/admin/user.rb +43 -2
- data/generica/app/models/apiv1/attachment.rb +2 -0
- data/generica/app/models/apiv1/email_object.rb +35 -0
- data/generica/app/models/apiv1/email_request.rb +107 -0
- data/generica/app/models/apiv1/offer_message.rb +53 -0
- data/generica/app/models/apiv1/offer_postboy.rb +33 -0
- data/generica/app/models/apiv1/picture.rb +2 -0
- data/generica/app/models/apiv1/product.rb +28 -6
- data/generica/app/models/apiv1/products/offer_message_factory.rb +13 -0
- data/generica/app/models/apiv1/products_machine.rb +8 -2
- data/generica/app/models/apiv1/taxon.rb +1 -1
- data/generica/app/models/apiv1/users/product_factory.rb +22 -0
- data/generica/app/models/apiv1/users/product_relationship.rb +19 -0
- data/generica/app/models/users/products/offer_factory.rb +40 -0
- data/generica/app/varissets/javascripts/templates/application.emblem.erb +2 -2
- data/generica/app/varissets/javascripts/templates/components/offers-overview.emblem.erb +1 -0
- data/generica/app/varissets/javascripts/templates/components/search-and-filter.emblem.erb +33 -0
- data/generica/app/varissets/javascripts/templates/components/site-nav.emblem.erb +8 -0
- data/generica/app/varissets/javascripts/templates/components/taggable-field.emblem.erb +11 -0
- data/generica/app/varissets/javascripts/templates/modals/login.emblem.erb +36 -0
- data/generica/app/varissets/javascripts/templates/products.emblem.erb +4 -0
- data/generica/app/varissets/javascripts/templates/products/index.emblem.erb +17 -0
- data/generica/app/varissets/javascripts/templates/products/product/offers/_anonymous-form.emblem.erb +11 -0
- data/generica/app/varissets/javascripts/templates/products/product/offers/_offer-form.emblem.erb +55 -0
- data/generica/app/varissets/javascripts/templates/products/product/offers/new.emblem.erb +37 -0
- data/generica/app/varissets/javascripts/templates/products/product/show.emblem.erb +108 -0
- data/generica/app/varissets/stylesheets/apiv1/components/_offers-overview.css.scss.erb +3 -0
- data/generica/app/varissets/stylesheets/apiv1/components/_offers_overview.css.scss.erb +3 -0
- data/generica/app/varissets/stylesheets/apiv1/components/_search-and-filter.css.scss.erb +15 -0
- data/generica/app/varissets/stylesheets/apiv1/components/_site-footer.css.scss.erb +23 -0
- data/generica/app/varissets/stylesheets/apiv1/components/_taggable-field.css.scss.erb +32 -0
- data/generica/app/views/apiv1/home/index.html.haml +3 -1
- data/generica/app/views/apiv1/layouts/application.html.haml +37 -2
- data/generica/config/{database.yml.erb → database.yml.str} +3 -3
- data/generica/config/email.yml +11 -0
- data/generica/config/email_slave.god +9 -0
- data/generica/config/initializers/premailer.rb +1 -0
- data/generica/config/initializers/squash.rb.erb +3 -0
- data/generica/config/nginx.conf.erb +4 -4
- data/generica/config/routes.rb +14 -0
- data/generica/db/migrate/20141114213427_add_user_rank_to_admin_users.rb +9 -0
- data/generica/db/migrate/20141114225019_create_apiv1_users_products.rb +9 -0
- data/generica/db/migrate/20141116053522_create_apiv1_offer_messages.rb +16 -0
- data/generica/db/migrate/20141116235011_add_deleted_at_to_apiv1_products.rb +5 -0
- data/generica/db/migrate/20141116235209_add_deleted_at_to_apiv1_offer_messages.rb +5 -0
- data/generica/db/migrate/20141116235651_add_deleted_at_to_apiv1_pictures.rb +5 -0
- data/generica/db/migrate/20141116235808_add_deleted_at_to_apiv1_attachments.rb +5 -0
- data/generica/db/migrate/20141127230304_create_apiv1_email_requests.rb +16 -0
- data/generica/db/migrate/20141127230455_create_apiv1_email_objects.rb +11 -0
- data/generica/lib/generica/assets_unretardifier.rb +32 -0
- data/generica/lib/generica/email_slave.rb +92 -0
- data/generica/lib/tasks/email_slave.rake +11 -0
- data/generica/lib/tasks/production.rake +1 -1
- data/generica/public/tests/bermese.jpg +0 -0
- data/generica/public/tests/chow.jpg +0 -0
- data/generica/public/tests/malamute.jpg +0 -0
- data/generica/public/tests/malamute2.JPG +0 -0
- data/generica/spec/controllers/apiv1/users/create_controller_spec.rb +17 -0
- data/generica/spec/controllers/users/products/create_controller_spec.rb +31 -0
- data/generica/spec/mailers/apiv1/aggregate_mailer_spec.rb +29 -0
- data/generica/spec/models/apiv1/email_request_spec.rb +4 -0
- data/generica/spec/models/apiv1/offer_postboy_spec.rb +22 -0
- data/generica/spec/models/apiv1/product_spec.rb +1 -0
- data/generica/spec/models/apiv1/products/offer_message_factory_spec.rb +37 -0
- data/generica/spec/models/apiv1/products_machine_spec.rb +77 -0
- data/generica/spec/models/apiv1/users/product_factory_spec.rb +47 -0
- data/generica/spec/models/users/products/offer_factory_spec.rb +38 -0
- data/generica/test/mailers/.keep +0 -0
- data/generica/test/mailers/previews/apiv1/aggregate_preview.rb +6 -0
- data/generica/test/mailers/previews/apiv1/notifications_preview.rb +5 -0
- data/lib/cloudrider.rb +1 -1
- data/lib/cloudrider/apiv1/base.rb +2 -2
- data/lib/cloudrider/apiv1/login_modal_emblem.rb +25 -0
- data/lib/cloudrider/apiv1/offers_anonymous_form_partial_emblem.rb +12 -0
- data/lib/cloudrider/apiv1/offers_new_emblem.rb +15 -0
- data/lib/cloudrider/apiv1/offers_overview_component.rb +8 -0
- data/lib/cloudrider/apiv1/offers_overview_sass.rb +8 -0
- data/lib/cloudrider/apiv1/product_show_emblem.rb +31 -0
- data/lib/cloudrider/apiv1/products_emblem.rb +11 -0
- data/lib/cloudrider/apiv1/products_index_emblem.rb +14 -0
- data/lib/cloudrider/apiv1/search_and_filter_component.rb +11 -0
- data/lib/cloudrider/apiv1/search_and_filter_sass.rb +11 -0
- data/lib/cloudrider/apiv1/site_footer_component.rb +7 -7
- data/lib/cloudrider/apiv1/site_footer_sass.rb +9 -0
- data/lib/cloudrider/application_commander.rb +46 -34
- data/lib/cloudrider/backend_commander.rb +15 -9
- data/lib/cloudrider/protofile.rb +18 -2
- data/lib/cloudrider/protosite.example.json +26 -0
- data/lib/cloudrider/protosite.rb +66 -0
- data/lib/cloudrider/serverside/base.rb +2 -2
- data/lib/cloudrider/serverside/database_yaml.rb +9 -4
- data/lib/cloudrider/serverside/nginx_conf.rb +7 -2
- data/lib/cloudrider/serverside/squash_ruby.rb +14 -0
- data/lib/cloudrider/serverside/unicorn_conf_ruby.rb +2 -1
- data/lib/cloudrider/version.rb +1 -1
- data/lib/cloudrider/web_firm.rb +16 -0
- data/lib/cloudrider/web_firm/component_architect.rb +23 -0
- data/lib/cloudrider/web_firm/page_designer.rb +13 -0
- data/lib/cloudrider/web_firm/project_lead.rb +30 -0
- data/lib/cloudrider/web_firm/scumbag_engineer.rb +40 -0
- data/lib/cloudrider/web_firm/support_intern.rb +113 -0
- data/lib/generators/cloudrider/server/server_generator.rb +4 -8
- data/lib/generators/cloudrider/website/website_generator.rb +25 -0
- data/spec/cloudrider/protosite_spec.rb +63 -0
- data/vanilla/.bowerrc +4 -0
- data/vanilla/.editorconfig +33 -0
- data/vanilla/.ember-cli +9 -0
- data/vanilla/.gitignore +17 -0
- data/vanilla/.jshintrc +32 -0
- data/vanilla/.travis.yml +16 -0
- data/vanilla/Brocfile.js +20 -0
- data/vanilla/README.md +51 -0
- data/vanilla/app/app.js +16 -0
- data/vanilla/app/components/.gitkeep +0 -0
- data/vanilla/app/controllers/.gitkeep +0 -0
- data/vanilla/app/controllers/admin.coffee +5 -0
- data/vanilla/app/helpers/.gitkeep +0 -0
- data/vanilla/app/index.html +21 -0
- data/vanilla/app/models/.gitkeep +0 -0
- data/vanilla/app/router.js +11 -0
- data/vanilla/app/routes/.gitkeep +0 -0
- data/vanilla/app/styles/.gitkeep +0 -0
- data/vanilla/app/styles/app.css +3 -0
- data/vanilla/app/templates/.gitkeep +0 -0
- data/vanilla/app/templates/application.hbs +3 -0
- data/vanilla/app/templates/components/.gitkeep +0 -0
- data/vanilla/app/views/.gitkeep +0 -0
- data/vanilla/bower.json +17 -0
- data/vanilla/config/environment.js +47 -0
- data/vanilla/package.json +39 -0
- data/vanilla/public/.gitkeep +0 -0
- data/vanilla/public/crossdomain.xml +15 -0
- data/vanilla/public/robots.txt +3 -0
- data/vanilla/testem.json +11 -0
- data/vanilla/tests/.jshintrc +74 -0
- data/vanilla/tests/helpers/resolver.js +11 -0
- data/vanilla/tests/helpers/start-app.js +25 -0
- data/vanilla/tests/index.html +45 -0
- data/vanilla/tests/test-helper.js +12 -0
- data/vanilla/tests/unit/.gitkeep +0 -0
- data/vanilla/tests/unit/controllers/admin-test.coffee +12 -0
- data/vanilla/vendor/.gitkeep +0 -0
- metadata +189 -5
- data/generica/app/views/layouts/application.html.erb +0 -14
- data/lib/cloudrider/master_context.rb +0 -105
@@ -0,0 +1,19 @@
|
|
1
|
+
class Apiv1::NotificationsMailer < ActionMailer::Base
|
2
|
+
layout 'apiv1/layouts/email'
|
3
|
+
default from: "from@example.com"
|
4
|
+
|
5
|
+
# Subject can be set in your I18n file at config/locales/en.yml
|
6
|
+
# with the following lookup:
|
7
|
+
#
|
8
|
+
# en.notifications.new_offer.subject
|
9
|
+
#
|
10
|
+
def new_offer(offer_message)
|
11
|
+
@ctx = Apiv1::NotificationsMailer::NewOfferContext.new offer_message
|
12
|
+
|
13
|
+
mail to: @ctx.to,
|
14
|
+
from: @ctx.from,
|
15
|
+
cc: @ctx.cc,
|
16
|
+
bcc: @ctx.bcc,
|
17
|
+
subject: @ctx.subject
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Apiv1::NotificationsMailer::NewOfferContext
|
2
|
+
delegate :created_at,
|
3
|
+
:message,
|
4
|
+
:product,
|
5
|
+
:company_address,
|
6
|
+
:sender_email,
|
7
|
+
:phone_number,
|
8
|
+
to: :_offer
|
9
|
+
def initialize(offer_message)
|
10
|
+
@offer = offer_message
|
11
|
+
end
|
12
|
+
def to
|
13
|
+
product.try(:user).try(:email)
|
14
|
+
end
|
15
|
+
def from
|
16
|
+
"secretary@plasticscrapmarket.org"
|
17
|
+
end
|
18
|
+
def cc
|
19
|
+
end
|
20
|
+
def bcc
|
21
|
+
end
|
22
|
+
def product_summary
|
23
|
+
product.try :rough_summary
|
24
|
+
end
|
25
|
+
def subject
|
26
|
+
["new offer", "-", price_terms].join " "
|
27
|
+
end
|
28
|
+
def price_terms
|
29
|
+
_offer.price_terms.present? ? _offer.price_terms : "[missing price terms]"
|
30
|
+
end
|
31
|
+
def product_id
|
32
|
+
product.try :id
|
33
|
+
end
|
34
|
+
def material
|
35
|
+
product.try :material
|
36
|
+
end
|
37
|
+
def link_path(*relative_path)
|
38
|
+
File.join "http://www.plasticscrapmarket.org", '#', *relative_path
|
39
|
+
end
|
40
|
+
def cta_path
|
41
|
+
link_path "products/product", "#{product_id}"
|
42
|
+
end
|
43
|
+
def company_who_made_offer
|
44
|
+
_offer.from_company
|
45
|
+
end
|
46
|
+
def product_owner
|
47
|
+
product.try(:user).try(:company_name) || "listing owner"
|
48
|
+
end
|
49
|
+
private
|
50
|
+
def _offer
|
51
|
+
@offer
|
52
|
+
end
|
53
|
+
end
|
@@ -10,16 +10,57 @@
|
|
10
10
|
# updated_at :datetime
|
11
11
|
# remember_me_token :string(255)
|
12
12
|
# remember_me_token_expires_at :datetime
|
13
|
+
# user_rank :string(255)
|
14
|
+
# company_name :string(255)
|
15
|
+
# phone_number :string(255)
|
16
|
+
# about_me :text
|
17
|
+
# address :string(255)
|
13
18
|
#
|
14
19
|
|
15
20
|
class Admin::User < ActiveRecord::Base
|
16
21
|
authenticates_with_sorcery!
|
17
22
|
validates :email,
|
18
|
-
|
23
|
+
:company_name,
|
24
|
+
presence: true,
|
25
|
+
uniqueness: true
|
26
|
+
validates :password,
|
27
|
+
presence: true,
|
28
|
+
length: { minimum: 2 },
|
29
|
+
confirmation: true
|
30
|
+
|
31
|
+
has_many :product_relationships,
|
32
|
+
class_name: 'Apiv1::Users::ProductRelationship'
|
33
|
+
|
34
|
+
has_many :products,
|
35
|
+
class_name: 'Apiv1::Product',
|
36
|
+
through: :product_relationships
|
37
|
+
|
38
|
+
has_many :offers,
|
39
|
+
-> { order "#{Apiv1::OfferMessage.table_name}.created_at desc" },
|
40
|
+
through: :products,
|
41
|
+
class_name: 'Apiv1::OfferMessage'
|
42
|
+
|
19
43
|
def to_ember_hash
|
20
44
|
{
|
21
45
|
id: id,
|
22
|
-
email: email
|
46
|
+
email: email,
|
47
|
+
user_rank: user_rank,
|
48
|
+
company_name: company_name,
|
49
|
+
phone_number: phone_number,
|
50
|
+
address: address,
|
51
|
+
about_me: about_me
|
23
52
|
}
|
24
53
|
end
|
54
|
+
|
55
|
+
def admin?
|
56
|
+
user_rank.to_s == "admin"
|
57
|
+
end
|
58
|
+
|
59
|
+
def admin!
|
60
|
+
update user_rank: "admin"
|
61
|
+
end
|
62
|
+
|
63
|
+
def owns?(product)
|
64
|
+
product_relationships.exists?(product_id: product.id)
|
65
|
+
end
|
25
66
|
end
|
@@ -11,9 +11,11 @@
|
|
11
11
|
# document_updated_at :datetime
|
12
12
|
# created_at :datetime
|
13
13
|
# updated_at :datetime
|
14
|
+
# deleted_at :datetime
|
14
15
|
#
|
15
16
|
|
16
17
|
class Apiv1::Attachment < ActiveRecord::Base
|
18
|
+
acts_as_paranoid
|
17
19
|
DocumentTypes = [
|
18
20
|
"application/pdf",
|
19
21
|
"application/docx",
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: apiv1_email_objects
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# email_id :integer
|
7
|
+
# class_name :string(255)
|
8
|
+
# permalink_id :string(255)
|
9
|
+
# deleted_at :datetime
|
10
|
+
# created_at :datetime
|
11
|
+
# updated_at :datetime
|
12
|
+
#
|
13
|
+
|
14
|
+
class Apiv1::EmailObject < ActiveRecord::Base
|
15
|
+
acts_as_paranoid
|
16
|
+
belongs_to :email,
|
17
|
+
class_name: 'Apiv1::EmailRequest'
|
18
|
+
|
19
|
+
validates :class_name,
|
20
|
+
:permalink_id,
|
21
|
+
presence: true
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def paramify(some_object)
|
25
|
+
{
|
26
|
+
class_name: some_object.class,
|
27
|
+
permalink_id: some_object.id
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def objectify
|
33
|
+
Object.const_get(class_name).find permalink_id
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: apiv1_email_requests
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# to :string(255) not null
|
7
|
+
# cc :string(255)
|
8
|
+
# bcc :string(255)
|
9
|
+
# subject :string(255)
|
10
|
+
# status :string(255)
|
11
|
+
# from :string(255)
|
12
|
+
# mailer_class :string(255) not null
|
13
|
+
# deleted_at :datetime
|
14
|
+
# created_at :datetime
|
15
|
+
# updated_at :datetime
|
16
|
+
#
|
17
|
+
|
18
|
+
class Apiv1::EmailRequest < ActiveRecord::Base
|
19
|
+
class MailerClassValidator < ActiveModel::Validator
|
20
|
+
def validate(record)
|
21
|
+
_enforce_class_existence!(record)
|
22
|
+
_enforce_method_existence!(record)
|
23
|
+
end
|
24
|
+
private
|
25
|
+
def _enforce_class_existence!(record)
|
26
|
+
begin
|
27
|
+
record.send "_mailer_class"
|
28
|
+
rescue
|
29
|
+
record.errors[:mailer_class] << "There is no #{record.send '_mailer_class_name'} class"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def _enforce_method_existence!(record)
|
33
|
+
begin
|
34
|
+
throw :bad unless record.send("_mailer_class").action_methods.include? record.send("_mailer_method")
|
35
|
+
rescue
|
36
|
+
record.errors[:mailer_class] << "The class #{record.send '_mailer_class_name'} doesn't respond to #{record.send '_mailer_method'}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
acts_as_paranoid
|
41
|
+
has_many :email_objects,
|
42
|
+
class_name: 'Apiv1::EmailObject',
|
43
|
+
foreign_key: 'email_id'
|
44
|
+
|
45
|
+
scope :awaiting_delivery,
|
46
|
+
-> { where "#{self.table_name}.status is null" }
|
47
|
+
|
48
|
+
scope :already_delivered,
|
49
|
+
-> { where "#{self.table_name}.status is not null" }
|
50
|
+
|
51
|
+
scope :meant_for_email,
|
52
|
+
-> (email) { where "#{self.table_name}.to" => email }
|
53
|
+
|
54
|
+
scope :last_delivered_email_for,
|
55
|
+
-> (email) { meant_for_email(email).already_delivered.latest_first.limit 1 }
|
56
|
+
|
57
|
+
scope :latest_first,
|
58
|
+
-> { order "#{self.table_name}.updated_at desc" }
|
59
|
+
|
60
|
+
scope :oldest_first,
|
61
|
+
-> { order "#{self.table_name}.updated_at asc" }
|
62
|
+
|
63
|
+
scope :the_null_scope,
|
64
|
+
-> { where("id != id").limit 0 }
|
65
|
+
|
66
|
+
validates :to,
|
67
|
+
presence: true
|
68
|
+
|
69
|
+
validates :mailer_class,
|
70
|
+
presence: true,
|
71
|
+
format: { with: /[A-Z][a-zA-Z0-9_:]+#[a-z0-9_]+/ }
|
72
|
+
|
73
|
+
validates_with MailerClassValidator
|
74
|
+
|
75
|
+
class << self
|
76
|
+
def oldest_undelivered_request
|
77
|
+
awaiting_delivery.oldest_first.limit(1).first
|
78
|
+
end
|
79
|
+
def belonging_to_the_user_with_oldest_undelivered
|
80
|
+
return the_null_scope if oldest_undelivered_request.blank?
|
81
|
+
awaiting_delivery.oldest_first.meant_for_email oldest_undelivered_request.to
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def mailify
|
86
|
+
_mailer_class.send _mailer_method, *objectified_objects
|
87
|
+
end
|
88
|
+
|
89
|
+
def objectified_objects
|
90
|
+
email_objects.map(&:objectify)
|
91
|
+
end
|
92
|
+
|
93
|
+
def mark_as_delivered!
|
94
|
+
update status: :delivered
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
def _mailer_class
|
99
|
+
Object.const_get _mailer_class_name
|
100
|
+
end
|
101
|
+
def _mailer_class_name
|
102
|
+
mailer_class.to_s.split('#').first
|
103
|
+
end
|
104
|
+
def _mailer_method
|
105
|
+
mailer_class.to_s.split('#').last
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: apiv1_offer_messages
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# product_id :integer
|
7
|
+
# from_company :string(255)
|
8
|
+
# sender_email :string(255)
|
9
|
+
# subject_text :string(255)
|
10
|
+
# phone_number :string(255)
|
11
|
+
# contact_person :string(255)
|
12
|
+
# company_address :string(255)
|
13
|
+
# status :string(255)
|
14
|
+
# message :text
|
15
|
+
# created_at :datetime
|
16
|
+
# updated_at :datetime
|
17
|
+
# deleted_at :datetime
|
18
|
+
#
|
19
|
+
|
20
|
+
class Apiv1::OfferMessage < ActiveRecord::Base
|
21
|
+
acts_as_paranoid
|
22
|
+
belongs_to :product,
|
23
|
+
class_name: 'Apiv1::Product'
|
24
|
+
|
25
|
+
validates :price_terms,
|
26
|
+
:product,
|
27
|
+
presence: true
|
28
|
+
|
29
|
+
def to_ember_hash
|
30
|
+
attributes.merge price_terms: price_terms,
|
31
|
+
notes: notes
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_public_ember_hash
|
35
|
+
to_ember_hash.symbolize_keys.permit(:id, :product_id, :created_at, :price_terms, :status)
|
36
|
+
end
|
37
|
+
|
38
|
+
def price_terms
|
39
|
+
read_attribute :subject_text
|
40
|
+
end
|
41
|
+
|
42
|
+
def price_terms=(value)
|
43
|
+
write_attribute(:subject_text, value)
|
44
|
+
end
|
45
|
+
|
46
|
+
def notes
|
47
|
+
read_attribute :message
|
48
|
+
end
|
49
|
+
|
50
|
+
def notes=(m)
|
51
|
+
write_attribute :message, m
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Apiv1::OfferPostboy
|
2
|
+
def initialize(offer)
|
3
|
+
@offer = offer
|
4
|
+
end
|
5
|
+
|
6
|
+
def request_work!
|
7
|
+
_email_objects && _email_request.valid? && _email_request.tap(&:save!)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def _email_request
|
12
|
+
@email_request ||= Apiv1::EmailRequest.new _request_params
|
13
|
+
end
|
14
|
+
def _email_objects
|
15
|
+
@email_objects ||= _email_request.email_objects.new Apiv1::EmailObject.paramify @offer
|
16
|
+
end
|
17
|
+
def _request_params
|
18
|
+
{
|
19
|
+
to: _mail_to_with_default,
|
20
|
+
cc: _mail.cc.join(","),
|
21
|
+
bcc: _mail.bcc.join(","),
|
22
|
+
from: _mail.from.first,
|
23
|
+
subject: _mail.subject,
|
24
|
+
mailer_class: "Apiv1::NotificationsMailer#new_offer"
|
25
|
+
}
|
26
|
+
end
|
27
|
+
def _mail_to_with_default
|
28
|
+
_mail.to.first || "missing_destination@mailinator.com"
|
29
|
+
end
|
30
|
+
def _mail
|
31
|
+
@mail ||= Apiv1::NotificationsMailer.new_offer @offer
|
32
|
+
end
|
33
|
+
end
|
@@ -14,9 +14,11 @@
|
|
14
14
|
# created_at :datetime
|
15
15
|
# updated_at :datetime
|
16
16
|
# showcase_order :integer
|
17
|
+
# deleted_at :datetime
|
17
18
|
#
|
18
19
|
|
19
20
|
class Apiv1::Product < ActiveRecord::Base
|
21
|
+
acts_as_paranoid
|
20
22
|
include ::Elasticsearch::Model
|
21
23
|
include ::Elasticsearch::Model::Callbacks
|
22
24
|
Fields = [
|
@@ -35,6 +37,9 @@ class Apiv1::Product < ActiveRecord::Base
|
|
35
37
|
has_many :taxons,
|
36
38
|
through: :taxon_relationships,
|
37
39
|
class_name: 'Apiv1::Taxon'
|
40
|
+
has_many :offers,
|
41
|
+
-> { order "#{Apiv1::OfferMessage.table_name}.created_at desc" },
|
42
|
+
class_name: 'Apiv1::OfferMessage'
|
38
43
|
has_many :pictures,
|
39
44
|
class_name: 'Apiv1::Picture',
|
40
45
|
as: :depictable,
|
@@ -43,15 +48,27 @@ class Apiv1::Product < ActiveRecord::Base
|
|
43
48
|
class_name: 'Apiv1::Attachment',
|
44
49
|
as: :attachable,
|
45
50
|
dependent: :destroy
|
51
|
+
has_one :ownership,
|
52
|
+
class_name: 'Apiv1::Users::ProductRelationship',
|
53
|
+
foreign_key: 'product_id'
|
54
|
+
has_one :user,
|
55
|
+
through: :ownership,
|
56
|
+
class_name: 'Admin::User'
|
46
57
|
|
47
58
|
scope :belonging_to_taxon,
|
48
|
-
-> (taxon) {
|
59
|
+
-> (taxon) { union_of_taxon_ids taxon.id }
|
60
|
+
|
61
|
+
scope :union_of_taxon_ids,
|
62
|
+
-> (taxon_ids) { joins(:taxon_relationships).where("#{Apiv1::Listings::TaxonRelationship.table_name}.taxon_id" => taxon_ids) }
|
49
63
|
|
50
|
-
scope :
|
51
|
-
-> (
|
64
|
+
scope :grouped_by_count,
|
65
|
+
-> { select("#{Apiv1::Product.table_name}.*, COUNT(#{Apiv1::Product.table_name}.id) as product_count").group("#{Apiv1::Product.table_name}.id") }
|
52
66
|
|
53
|
-
scope :
|
54
|
-
-> (
|
67
|
+
scope :intersection_of_taxon_ids,
|
68
|
+
-> (taxon_ids) { taxon_ids.count > 1 ? intersection_of_two_or_more_taxon_ids(taxon_ids) : union_of_taxon_ids(taxon_ids) }
|
69
|
+
|
70
|
+
scope :intersection_of_two_or_more_taxon_ids,
|
71
|
+
-> (taxon_ids) { union_of_taxon_ids(taxon_ids).grouped_by_count.having("product_count = ?", taxon_ids.count) }
|
55
72
|
|
56
73
|
scope :order_by_created_at,
|
57
74
|
-> { order "#{self.table_name}.created_at desc"}
|
@@ -78,9 +95,14 @@ class Apiv1::Product < ActiveRecord::Base
|
|
78
95
|
def to_ember_hash
|
79
96
|
attributes.merge pictures: pictures.map(&:id),
|
80
97
|
taxons: taxons.map(&:id),
|
81
|
-
attachments: attachments.map(&:id)
|
98
|
+
attachments: attachments.map(&:id),
|
99
|
+
offers: offers.map(&:id),
|
100
|
+
user_id: user.try(:id)
|
82
101
|
end
|
83
102
|
|
103
|
+
def rough_summary
|
104
|
+
[material, sku, quality, place, amount].select(&:present?).join(" - ")
|
105
|
+
end
|
84
106
|
private
|
85
107
|
def _make_permalink
|
86
108
|
self.permalink ||= Apiv1::Permalinkifier.permalinkify material
|