diff --git a/app/furniture/journal/entry.rb b/app/furniture/journal/entry.rb
index 00d56713d..24c6d4b5a 100644
--- a/app/furniture/journal/entry.rb
+++ b/app/furniture/journal/entry.rb
@@ -19,6 +19,8 @@ class Journal::Entry < ApplicationRecord
attribute :published_at, :datetime
+ # @!attribute journal
+ # @return [Journal::Journal]
belongs_to :journal, class_name: "Journal::Journal", inverse_of: :entries
delegate :room, :space, to: :journal
diff --git a/app/furniture/marketplace.rb b/app/furniture/marketplace.rb
index 3a00f2dfe..2cdbd1d60 100644
--- a/app/furniture/marketplace.rb
+++ b/app/furniture/marketplace.rb
@@ -3,12 +3,15 @@ class Marketplace
include Placeable
def self.append_routes(router)
- router.resource :marketplace, only: [] do
- router.resources :products, only: %i[new create index], module: "marketplace"
+ router.resources :marketplaces, only: [:show], module: "marketplace" do
+ router.resources :products
+ router.resources :carts do
+ router.resources :cart_products
+ end
end
end
- def products
- Marketplace::Product.where(space: space)
+ def self.from_placement(placement)
+ placement.becomes(Marketplace)
end
end
diff --git a/app/furniture/marketplace/_marketplace.html.erb b/app/furniture/marketplace/_marketplace.html.erb
deleted file mode 100644
index 27b30ca34..000000000
--- a/app/furniture/marketplace/_marketplace.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= render partial: "marketplace/marketplace/marketplace", object: marketplace %>
\ No newline at end of file
diff --git a/app/furniture/marketplace/breadcrumbs.rb b/app/furniture/marketplace/breadcrumbs.rb
new file mode 100644
index 000000000..62238802f
--- /dev/null
+++ b/app/furniture/marketplace/breadcrumbs.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# @see https://github.com/kzkn/gretel
+
+crumb :marketplace do |marketplace|
+ parent :room, marketplace.room
+ link 'Marketplace', marketplace.location
+end
+
+crumb :marketplace_products do |marketplace|
+ parent :marketplace, marketplace
+ link 'Products', marketplace.location(:products)
+end
+
+crumb :marketplace_product do |product|
+ parent :marketplace_products, product.marketplace
+ link product.name, product.location
+end
+
+crumb :new_marketplace_product do |product|
+ parent :marketplace_products, product.marketplace
+ link 'Add a Product', [:new] + marketplace.location(:product)
+end
+
+crumb :edit_marketplace_product do |product|
+ parent :marketplace_product, product
+ link 'Edit', [:edit] + product.location
+end
diff --git a/app/furniture/marketplace/cart.rb b/app/furniture/marketplace/cart.rb
new file mode 100644
index 000000000..f0303412b
--- /dev/null
+++ b/app/furniture/marketplace/cart.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Marketplace
+ class Cart < ApplicationRecord
+ self.table_name = 'marketplace_carts'
+
+ belongs_to :marketplace
+ delegate :space, :room, to: :marketplace
+ has_many :cart_products
+ has_many :products, through: :cart_products
+
+ def self.model_name
+ @_model_name ||= ActiveModel::Name.new(self, ::Marketplace)
+ end
+ end
+end
diff --git a/app/furniture/marketplace/cart_product.rb b/app/furniture/marketplace/cart_product.rb
new file mode 100644
index 000000000..bb25dfd5c
--- /dev/null
+++ b/app/furniture/marketplace/cart_product.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Marketplace
+ class CartProduct < ApplicationRecord
+ self.table_name = "marketplace_cart_products"
+
+ belongs_to :cart, inverse_of: :cart_products
+ belongs_to :product, inverse_of: :cart_products
+ validates_uniqueness_of :product, scope: :cart_id
+
+ attribute :quantity, :integer, default: 0
+
+ def self.model_name
+ @_model_name ||= ActiveModel::Name.new(self, ::Marketplace)
+ end
+ end
+end
diff --git a/app/furniture/marketplace/cart_products/_cart_product.html.erb b/app/furniture/marketplace/cart_products/_cart_product.html.erb
new file mode 100644
index 000000000..ad0b7c30b
--- /dev/null
+++ b/app/furniture/marketplace/cart_products/_cart_product.html.erb
@@ -0,0 +1,33 @@
+<%- product = cart_product.product %>
+<%- cart = cart_product.cart %>
+
+
+ <%= product.name %>
+
+ - <%= product.class.human_attribute_name(:price) %>
+ - <%= humanized_money_with_symbol(product.price) %>
+ - <%= product.class.human_attribute_name(:description) %>
+ - <%= product.description %>
+
+
+ |
+
+ <%= product.description %>
+ |
+
+ <%= humanized_money_with_symbol(product.price) %>
+ |
+
+ <%# TODO: Extract minus and plus buttons into components %>
+ <%- minus_quantity = [cart_product.quantity - 1, 0].max %>
+ <%- minus_method = minus_quantity.zero? ? :delete : :put %>
+ <%= render "buttons/minus", disabled: cart_product.quantity.zero?, method: minus_method, title: t('.remove'), disabled: cart_product.quantity.zero?, href: [cart.space, cart.room, cart.marketplace, cart, cart_product, { cart_product: { quantity: minus_quantity, product_id: product.id} }] %>
+
+
+ <%= cart_product.quantity %>
+
+ <%- add_quantity = cart_product.quantity + 1 %>
+ <%- add_method = add_quantity == 1 ? :post : :put %>
+ <%= render "buttons/plus", method: add_method, title: t('.add'), href: [cart.space, cart.room, cart.marketplace, cart, cart_product, { cart_product: {quantity: add_quantity, product_id: product.id} }] %>
+ |
+
diff --git a/app/furniture/marketplace/cart_products_controller.rb b/app/furniture/marketplace/cart_products_controller.rb
new file mode 100644
index 000000000..d230e5145
--- /dev/null
+++ b/app/furniture/marketplace/cart_products_controller.rb
@@ -0,0 +1,91 @@
+class Marketplace
+ class CartProductsController < FurnitureController
+ def create
+ cart_product.save
+
+ respond_to do |format|
+ format.html do
+ if cart_product.errors.empty?
+ flash[:notice] = t(".success",
+ product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ else
+ flash[:alert] = t(".failure",
+ product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ end
+
+ redirect_to [marketplace.space, marketplace.room]
+ end
+
+ format.turbo_stream do
+ render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product)
+ end
+ end
+ end
+
+ def update
+ cart_product.update(cart_product_params)
+ respond_to do |format|
+ format.html do
+ if cart_product.errors.empty?
+ flash[:notice] =
+ t(".success", product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ else
+ flash[:alert] =
+ t(".failure", product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ end
+
+ redirect_to [marketplace.space, marketplace.room]
+ end
+ format.turbo_stream do
+ render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product)
+ end
+ end
+ end
+
+ def destroy
+ cart_product.destroy
+ respond_to do |format|
+ format.html do
+ if cart_product.destroyed?
+ flash[:notice] =
+ t(".success", product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ else
+ flash[:alert] =
+ t(".failure", product: cart_product.product.name.pluralize(cart_product.quantity),
+ quantity: cart_product.quantity)
+ end
+ redirect_to [marketplace.space, marketplace.room]
+ end
+
+ format.turbo_stream do
+ render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart.cart_products.new(product: cart_product.product))
+ end
+ end
+ end
+
+ def cart_product
+ @cart_product ||= if params[:id]
+ cart.cart_products.find(params[:id])
+ elsif params[:cart_product]
+ cart.cart_products.new(cart_product_params)
+ end
+ end
+
+ def cart
+ marketplace.carts.find(params[:cart_id])
+ end
+
+ def marketplace
+ room.furniture_placements.find(params[:marketplace_id]).furniture
+ end
+
+ def cart_product_params
+ params.require(:cart_product).permit(:quantity, :product_id)
+ end
+ end
+end
diff --git a/app/furniture/marketplace/locales/en.yml b/app/furniture/marketplace/locales/en.yml
new file mode 100644
index 000000000..810cab05a
--- /dev/null
+++ b/app/furniture/marketplace/locales/en.yml
@@ -0,0 +1,21 @@
+en:
+ marketplace:
+ products:
+ index:
+ new: Add a Product
+ product:
+ add: Add Product
+ remove: Remove Product
+ cart_products:
+ cart_product:
+ remove: Remove from Cart
+ add: Add to Cart
+ destroy:
+ success: "Removed %{quantity} %{product} from Cart"
+ failure: "Could not remove %{quantity} %{product} from Cart"
+ create:
+ success: "Added %{quantity} %{product} to Cart"
+ failure: "Could not add %{quantity} %{product} to Cart"
+ update:
+ success: "Changed %{quantity} %{product} on Cart"
+ failure: "Could not change %{quantity} %{product} on Cart"
diff --git a/app/furniture/marketplace/marketplace.rb b/app/furniture/marketplace/marketplace.rb
new file mode 100644
index 000000000..772ab444b
--- /dev/null
+++ b/app/furniture/marketplace/marketplace.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Marketplace
+ class Marketplace < FurniturePlacement
+ has_many :products, inverse_of: :marketplace
+ has_many :carts, inverse_of: :marketplace
+
+ def self.model_name
+ @_model_name ||= ActiveModel::Name.new(self, ::Marketplace)
+ end
+
+ def location(child = nil)
+ [space, room, self, child].compact
+ end
+ end
+end
diff --git a/app/furniture/marketplace/marketplace/_marketplace.html.erb b/app/furniture/marketplace/marketplace/_marketplace.html.erb
deleted file mode 100644
index c8c1b0d8e..000000000
--- a/app/furniture/marketplace/marketplace/_marketplace.html.erb
+++ /dev/null
@@ -1,26 +0,0 @@
-<%= turbo_frame_tag marketplace do %>
-
-
-
-
-
- <%= Marketplace::Product.human_attribute_name(:name) %>
- |
-
- <%= Marketplace::Product.human_attribute_name(:description) %>
- |
-
- <%= Marketplace::Product.human_attribute_name(:price) %>
- |
-
- Actions
- <%= render "buttons/new", title: t('marketplace.products.new'), href: [:new, marketplace.space, marketplace.room, marketplace, :product] %>
- |
-
-
-
- <%= render marketplace.products %>
-
-
-
-<%- end %>
\ No newline at end of file
diff --git a/app/furniture/marketplace/marketplaces/_marketplace.html.erb b/app/furniture/marketplace/marketplaces/_marketplace.html.erb
new file mode 100644
index 000000000..b06f74c8e
--- /dev/null
+++ b/app/furniture/marketplace/marketplaces/_marketplace.html.erb
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ <%= Marketplace::Product.human_attribute_name(:name) %>
+ |
+
+ <%= Marketplace::Product.human_attribute_name(:description) %>
+ |
+
+ <%= Marketplace::Product.human_attribute_name(:price) %>
+ |
+ |
+
+
+
+ <%- cart = marketplace.carts.find_or_create_by(id: session[:current_cart] ||= SecureRandom.uuid) %>
+ <%- marketplace.products.each do |product| %>
+ <%= render cart.cart_products.find_or_initialize_by(product: product) %>
+ <%- end %>
+
+
+
+
+<%- if policy(marketplace.products.new).create? %>
+ <%= link_to t('.manage_products'), marketplace.location(:products) %>
+<%- end %>
+
diff --git a/app/furniture/marketplace/marketplaces/show.html.erb b/app/furniture/marketplace/marketplaces/show.html.erb
new file mode 100644
index 000000000..247aa239f
--- /dev/null
+++ b/app/furniture/marketplace/marketplaces/show.html.erb
@@ -0,0 +1,2 @@
+<%- breadcrumb :marketplace, marketplace %>
+<%= render marketplace %>
diff --git a/app/furniture/marketplace/marketplaces_controller.rb b/app/furniture/marketplace/marketplaces_controller.rb
new file mode 100644
index 000000000..a4ef3907f
--- /dev/null
+++ b/app/furniture/marketplace/marketplaces_controller.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class Marketplace
+ class MarketplacesController < FurnitureController
+ def show; end
+
+ helper_method def marketplace
+ Marketplace.find(params[:id])
+ end
+ end
+end
diff --git a/app/furniture/marketplace/product.rb b/app/furniture/marketplace/product.rb
index 39b451708..b4d1830c0 100644
--- a/app/furniture/marketplace/product.rb
+++ b/app/furniture/marketplace/product.rb
@@ -2,8 +2,15 @@
class Marketplace
class Product < ApplicationRecord
- self.table_name = "marketplace_products"
- belongs_to :space
+ self.table_name = 'marketplace_products'
+
+ extend StripsNamespaceFromModelName
+
+ belongs_to :marketplace
+ delegate :space, to: :marketplace
+
+ has_many :cart_products, inverse_of: :product
+ has_many :carts, through: :cart_products
attribute :name, :string
validates :name, presence: true
@@ -11,5 +18,9 @@ class Product < ApplicationRecord
attribute :description, :string
monetize :price_cents
+
+ def location
+ marketplace.location(self)
+ end
end
end
diff --git a/app/furniture/marketplace/product_policy.rb b/app/furniture/marketplace/product_policy.rb
index bd5817624..5eec79bef 100644
--- a/app/furniture/marketplace/product_policy.rb
+++ b/app/furniture/marketplace/product_policy.rb
@@ -2,8 +2,17 @@
class Marketplace
class ProductPolicy < ApplicationPolicy
+ alias product object
def permitted_attributes(_params)
%i[name description price_cents price_currency]
end
+
+ def create?
+ person.member_of?(product.space)
+ end
+
+ def update?
+ create?
+ end
end
end
diff --git a/app/furniture/marketplace/products/_form.html.erb b/app/furniture/marketplace/products/_form.html.erb
new file mode 100644
index 000000000..15fde27be
--- /dev/null
+++ b/app/furniture/marketplace/products/_form.html.erb
@@ -0,0 +1,6 @@
+<%= form_with model: product.location do |f| %>
+ <%= render "text_field", { attribute: :name, form: f} %>
+ <%= render "text_area", { attribute: :description, form: f} %>
+ <%= render "number_field", { attribute: :price_cents, form: f} %>
+ <%= f.submit %>
+<% end %>
diff --git a/app/furniture/marketplace/products/_product.html.erb b/app/furniture/marketplace/products/_product.html.erb
index 15d776a7d..fe7611322 100644
--- a/app/furniture/marketplace/products/_product.html.erb
+++ b/app/furniture/marketplace/products/_product.html.erb
@@ -1,4 +1,4 @@
-
+
<%= product.name %>
@@ -13,6 +13,6 @@
<%= humanized_money_with_symbol(product.price) %>
|
- <%= render "buttons/new", label: "🛒", title: t('marketplace.products.new'), href: "#" %>
+ <%= render "buttons/remove", title: t('.remove'), href: product.location %>
|
-
\ No newline at end of file
+
diff --git a/app/furniture/marketplace/products/index.html.erb b/app/furniture/marketplace/products/index.html.erb
new file mode 100644
index 000000000..f0b49b423
--- /dev/null
+++ b/app/furniture/marketplace/products/index.html.erb
@@ -0,0 +1,25 @@
+<%- breadcrumb :marketplace_products, marketplace%>
+
+
+
+
+
+ <%= Marketplace::Product.human_attribute_name(:name) %>
+ |
+
+ <%= Marketplace::Product.human_attribute_name(:description) %>
+ |
+
+ <%= Marketplace::Product.human_attribute_name(:price) %>
+ |
+
+
+
+ <%= render marketplace.products %>
+
+
+
+<%- new_product = marketplace.products.new %>
+<%- if policy(new_product).create? %>
+ <%= render "buttons/new", label: "#{t('.new')} #{t('icons.new')}", title: t('.new'), href: [:new] + marketplace.location + [:product] %>
+<%- end %>
diff --git a/app/furniture/marketplace/products/new.html.erb b/app/furniture/marketplace/products/new.html.erb
index c263ef1ca..9b7d915a2 100644
--- a/app/furniture/marketplace/products/new.html.erb
+++ b/app/furniture/marketplace/products/new.html.erb
@@ -1,8 +1,3 @@
-<%= turbo_frame_tag marketplace do %>
- <%= form_with model: [marketplace.space, marketplace.room, marketplace.products.new] do |f| %>
- <%= render "text_field", { attribute: :name, form: f} %>
- <%= render "text_area", { attribute: :description, form: f} %>
- <%= render "number_field", { attribute: :price_cents, form: f} %>
- <%= f.submit %>
- <% end %>
-<%- end %>
\ No newline at end of file
+<%- new_product = marketplace.products.new %>
+<%- breadcrumb :new_marketplace_product, new_product %>
+<%= render "form", product: marketplace.products.new %>
diff --git a/app/furniture/marketplace/products_controller.rb b/app/furniture/marketplace/products_controller.rb
index ffd89d5ef..956bb1680 100644
--- a/app/furniture/marketplace/products_controller.rb
+++ b/app/furniture/marketplace/products_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Marketplace
class ProductsController < FurnitureController
def new
@@ -9,16 +11,32 @@ def create
respond_to do |format|
format.turbo_stream
- format.html { redirect_to [space, room] }
+ format.html { redirect_to marketplace.location(:products) }
+ end
+ end
+
+ def destroy
+ product = authorize(marketplace.products.find(params[:id]))
+
+ respond_to do |format|
+ if product.destroy
+ format.turbo_stream { render turbo_stream: turbo_stream.remove(product) }
+ format.html { redirect_to marketplace.location(:products) }
+ else
+ format.html { redirect_to product.location }
+ end
end
end
+ def index
+ end
+
helper_method def marketplace
- Marketplace.find_by(room: room)
+ Marketplace.find(params[:marketplace_id])
end
def product_params
- policy(Marketplace::Product).permit(params.require(:marketplace_product))
+ policy(Product).permit(params.require(:product))
end
end
end
diff --git a/app/views/buttons/_minus.html.erb b/app/views/buttons/_minus.html.erb
new file mode 100644
index 000000000..a876ebe01
--- /dev/null
+++ b/app/views/buttons/_minus.html.erb
@@ -0,0 +1,15 @@
+<%- label = local_assigns.fetch(:label, t('icons.minus')) %>
+<%- title = local_assigns.fetch(:title) %>
+<%- href = local_assigns.fetch(:href) %>
+<%- method = local_assigns.fetch(:method, :put)%>
+<%- disabled = local_assigns.fetch(:disabled, false)%>
+<%- data = { turbo_method: method, turbo: true} %>
+<%- data = data.merge(turbo_confirm: local_assigns[:confirm], confirm: local_assigns[:confirm]) if local_assigns.key?(:confirm) %>
+
+<%- if !disabled %>
+ <%= link_to label, href, title: title, method: method,
+ data: data,
+ class: 'no-underline bg-transparent hover:bg-primary-100 button' %>
+<%- else %>
+ <%=label%>
+<%- end %>
diff --git a/app/views/buttons/_new.html.erb b/app/views/buttons/_new.html.erb
index be8a3e249..70afe93a8 100644
--- a/app/views/buttons/_new.html.erb
+++ b/app/views/buttons/_new.html.erb
@@ -3,4 +3,4 @@
<%- href = local_assigns.fetch(:href) %>
<%= link_to label, href, title: title,
- class: 'no-underline bg-transparent hover:bg-primary-100 button' %>
+ class: 'no-underline hover:bg-primary-400 bg-primary-500 font-bold py-2 px-4 my-1 rounded text-white text-center transition ease-in-out duration-150 ' %>
diff --git a/app/views/buttons/_plus.html.erb b/app/views/buttons/_plus.html.erb
new file mode 100644
index 000000000..84e9ed47b
--- /dev/null
+++ b/app/views/buttons/_plus.html.erb
@@ -0,0 +1,10 @@
+<%- label = local_assigns.fetch(:label, t('icons.plus')) %>
+<%- title = local_assigns.fetch(:title) %>
+<%- href = local_assigns.fetch(:href) %>
+<%- method = local_assigns.fetch(:method, :put)%>
+<%- data = { turbo_method: method, turbo: true } %>
+<%- data = data.merge(turbo_confirm: local_assigns[:confirm], confirm: local_assigns[:confirm]) if local_assigns.key?(:confirm) %>
+
+<%= link_to label, href, title: title, method: method,
+ data: data,
+ class: 'no-underline bg-transparent hover:bg-primary-100 button' %>
diff --git a/app/views/buttons/_remove.html.erb b/app/views/buttons/_remove.html.erb
index 96c12990e..9ce72be1d 100644
--- a/app/views/buttons/_remove.html.erb
+++ b/app/views/buttons/_remove.html.erb
@@ -1,7 +1,7 @@
<%- label = local_assigns.fetch(:label, t('icons.remove')) %>
<%- title = local_assigns.fetch(:title) %>
<%- href = local_assigns.fetch(:href) %>
-<%- data = { turbo_method: :delete } %>
+<%- data = { turbo_method: :delete, turbo: true } %>
<%- data = data.merge(turbo_confirm: local_assigns[:confirm], confirm: local_assigns[:confirm]) if local_assigns.key?(:confirm) %>
<%= link_to label, href, title: title,
diff --git a/app/views/furniture_placements/_form.html.erb b/app/views/furniture_placements/_form.html.erb
index 39cf16c06..a54a1a5ec 100644
--- a/app/views/furniture_placements/_form.html.erb
+++ b/app/views/furniture_placements/_form.html.erb
@@ -17,4 +17,4 @@
<%- end %>
<%- end %>
-<%- end %>
\ No newline at end of file
+<%- end %>
diff --git a/config/initializers/money.rb b/config/initializers/money.rb
index 633a68193..575df2cdb 100644
--- a/config/initializers/money.rb
+++ b/config/initializers/money.rb
@@ -82,6 +82,9 @@
# sign_before_symbol: nil
# }
+ config.default_format = { no_cents_if_whole: false }
+ config.no_cents_if_whole = false
+
# If you would like to use I18n localization (formatting depends on the
# locale):
config.locale_backend = :i18n
diff --git a/config/locales/icon/en.yml b/config/locales/icon/en.yml
index 3a1758717..46fa0f7f9 100644
--- a/config/locales/icon/en.yml
+++ b/config/locales/icon/en.yml
@@ -2,4 +2,6 @@ en:
icons:
edit: '⚙️'
remove: '🗑️'
- new: '➕'
\ No newline at end of file
+ new: '➕'
+ plus: '➕'
+ minus: '➖'
diff --git a/db/migrate/20221013010533_add_marketplace_carts.rb b/db/migrate/20221013010533_add_marketplace_carts.rb
new file mode 100644
index 000000000..2989acf69
--- /dev/null
+++ b/db/migrate/20221013010533_add_marketplace_carts.rb
@@ -0,0 +1,32 @@
+class AddMarketplaceCarts < ActiveRecord::Migration[7.0]
+ def change
+ create_table :marketplace_carts, id: :uuid do |t|
+ t.references :marketplace, type: :uuid, foreign_key: {to_table: :furniture_placements}
+ t.timestamps
+ end
+
+ # We can't change the primary key type so we drop and recreate :'(
+ drop_table :marketplace_products do |t|
+ t.references :marketplace, type: :uuid, foreign_key: {to_table: :furniture_placements}
+ t.string :name
+ t.string :description
+ t.monetize :price
+ t.timestamps
+ end
+
+ create_table :marketplace_products, id: :uuid do |t|
+ t.references :marketplace, type: :uuid, foreign_key: {to_table: :furniture_placements}
+ t.string :name
+ t.string :description
+ t.monetize :price
+ t.timestamps
+ end
+
+ create_table :marketplace_cart_products, id: :uuid do |t|
+ t.belongs_to(:cart, foreign_key: {to_table: :marketplace_carts}, type: :uuid)
+ t.belongs_to(:product, foreign_key: {to_table: :marketplace_products}, type: :uuid)
+ t.integer :quantity
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index adb16c225..b7414b411 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2022_10_07_224846) do
+ActiveRecord::Schema[7.0].define(version: 2022_10_13_010533) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
@@ -134,15 +134,32 @@
t.index ["journal_id"], name: "index_journal_entries_on_journal_id"
end
- create_table "marketplace_products", force: :cascade do |t|
- t.uuid "space_id"
+ create_table "marketplace_cart_products", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.uuid "cart_id"
+ t.uuid "product_id"
+ t.integer "quantity"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["cart_id"], name: "index_marketplace_cart_products_on_cart_id"
+ t.index ["product_id"], name: "index_marketplace_cart_products_on_product_id"
+ end
+
+ create_table "marketplace_carts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.uuid "marketplace_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["marketplace_id"], name: "index_marketplace_carts_on_marketplace_id"
+ end
+
+ create_table "marketplace_products", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+ t.uuid "marketplace_id"
t.string "name"
t.string "description"
t.integer "price_cents", default: 0, null: false
t.string "price_currency", default: "USD", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
- t.index ["space_id"], name: "index_marketplace_products_on_space_id"
+ t.index ["marketplace_id"], name: "index_marketplace_products_on_marketplace_id"
end
create_table "memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
@@ -206,7 +223,10 @@
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "journal_entries", "furniture_placements", column: "journal_id"
- add_foreign_key "marketplace_products", "spaces"
+ add_foreign_key "marketplace_cart_products", "marketplace_carts", column: "cart_id"
+ add_foreign_key "marketplace_cart_products", "marketplace_products", column: "product_id"
+ add_foreign_key "marketplace_carts", "furniture_placements", column: "marketplace_id"
+ add_foreign_key "marketplace_products", "furniture_placements", column: "marketplace_id"
add_foreign_key "memberships", "invitations"
add_foreign_key "spaces", "rooms", column: "entrance_id"
end
diff --git a/spec/factories/furniture/marketplace.rb b/spec/factories/furniture/marketplace.rb
index 4bbad431f..d43315f55 100644
--- a/spec/factories/furniture/marketplace.rb
+++ b/spec/factories/furniture/marketplace.rb
@@ -1,18 +1,21 @@
FactoryBot.define do
- factory :marketplace do
- transient do
- room { build(:room) }
- end
-
- placement do
- association :furniture_placement, {furniture_kind: "marketplace", room: room}
- end
+ factory :marketplace, class: "Marketplace::Marketplace" do
+ room
end
factory :marketplace_product, class: "Marketplace::Product" do
name { Faker::TvShows::DrWho.specie }
- price_cents { Random.rand(1_00..9999_99) }
+ price_cents { Random.rand(1_00..999_999) }
+
+ marketplace
+ end
+
+ factory :marketplace_cart_product, class: "Marketplace::CartProduct" do
+ association(:product, factory: :marketplace_product)
+ association(:cart, factory: :marketplace_cart)
+ end
- association :space
+ factory :marketplace_cart, class: "Marketplace::Cart" do
+ marketplace
end
end
diff --git a/spec/furniture/marketplace/cart_product_spec.rb b/spec/furniture/marketplace/cart_product_spec.rb
new file mode 100644
index 000000000..dca41c82b
--- /dev/null
+++ b/spec/furniture/marketplace/cart_product_spec.rb
@@ -0,0 +1,10 @@
+require "rails_helper"
+
+RSpec.describe Marketplace::CartProduct, type: :model do
+ subject(:cart_product) { build(:marketplace_cart_product) }
+
+ it { is_expected.to belong_to(:cart).inverse_of(:cart_products) }
+
+ it { is_expected.to belong_to(:product).inverse_of(:cart_products) }
+ it { is_expected.to validate_uniqueness_of(:product).scoped_to(:cart_id) }
+end
diff --git a/spec/furniture/marketplace/cart_spec.rb b/spec/furniture/marketplace/cart_spec.rb
new file mode 100644
index 000000000..faf99e70f
--- /dev/null
+++ b/spec/furniture/marketplace/cart_spec.rb
@@ -0,0 +1,9 @@
+require "rails_helper"
+
+RSpec.describe Marketplace::Cart, type: :model do
+ it { is_expected.to have_many(:cart_products) }
+
+ it { is_expected.to have_many(:products).through(:cart_products) }
+
+ it { is_expected.to belong_to(:marketplace).class_name("Marketplace::Marketplace") }
+end
diff --git a/spec/furniture/marketplace/marketplace_spec.rb b/spec/furniture/marketplace/marketplace_spec.rb
new file mode 100644
index 000000000..77482df6e
--- /dev/null
+++ b/spec/furniture/marketplace/marketplace_spec.rb
@@ -0,0 +1,6 @@
+require "rails_helper"
+
+RSpec.describe Marketplace::Marketplace, type: :model do
+ it { is_expected.to have_many(:products).inverse_of(:marketplace) }
+ it { is_expected.to have_many(:carts).inverse_of(:marketplace) }
+end
diff --git a/spec/furniture/marketplace/product_spec.rb b/spec/furniture/marketplace/product_spec.rb
index ae0bbf7d9..14b2cd228 100644
--- a/spec/furniture/marketplace/product_spec.rb
+++ b/spec/furniture/marketplace/product_spec.rb
@@ -1,9 +1,9 @@
-require "rails_helper"
+require 'rails_helper'
RSpec.describe Marketplace::Product, type: :model do
- it { is_expected.to belong_to(:space) }
+ it { is_expected.to belong_to(:marketplace) }
- describe "#name" do
+ describe '#name' do
it { is_expected.to validate_presence_of(:name) }
end
end
diff --git a/spec/furniture/marketplace/products_request_spec.rb b/spec/furniture/marketplace/products_controller_request_spec.rb
similarity index 94%
rename from spec/furniture/marketplace/products_request_spec.rb
rename to spec/furniture/marketplace/products_controller_request_spec.rb
index 4b45db67a..c5deb4619 100644
--- a/spec/furniture/marketplace/products_request_spec.rb
+++ b/spec/furniture/marketplace/products_controller_request_spec.rb
@@ -10,7 +10,8 @@
attributes = attributes_for(:marketplace_product)
expect do
- post polymorphic_path([space, room, marketplace, :products]), params: {marketplace_product: attributes}
+ post polymorphic_path([space, room, marketplace, :products]),
+ params: {product: attributes}
end.to change(marketplace.products, :count).by(1)
created_product = marketplace.products.last