Skip to content

Commit

Permalink
✨🥔 Marketplace: Products have TaxRates
Browse files Browse the repository at this point in the history
- #1137

There's a bit of low-hanging 🌸, but I don't want to block on them. In
particular:

- It would be nice if we had a well-styled `Component` or partial for
  the `collection_check_boxes` form helper, since right now the
  `input[type="checkbox"]` and the `label` for each option are stacked
  on top of each other. Nasteh!
- There's probably a way to show the tax rate amount with a humanized
  percentage when selecting options, but I didn't want to figure it out
  • Loading branch information
zspencer committed Mar 9, 2023
1 parent 61ea173 commit 0f46fc2
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 9 deletions.
3 changes: 2 additions & 1 deletion app/furniture/marketplace/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class Product < Record
has_many :ordered_products, inverse_of: :product, dependent: :destroy
has_many :orders, through: :ordered_products, inverse_of: :products

has_many :tax_rates, inverse_of: :products
has_many :product_tax_rates, inverse_of: :product
has_many :tax_rates, through: :product_tax_rates, inverse_of: :products

attribute :name, :string
validates :name, presence: true
Expand Down
2 changes: 1 addition & 1 deletion app/furniture/marketplace/product_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Marketplace
class ProductPolicy < Policy
alias_method :product, :object
def permitted_attributes(_params = nil)
%i[name description price_cents price_currency price]
%i[name description price_cents price_currency price] + [tax_rate_ids: []]
end

def update?
Expand Down
8 changes: 8 additions & 0 deletions app/furniture/marketplace/product_tax_rate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Marketplace
class ProductTaxRate < Record
self.table_name = :marketplace_product_tax_rates

belongs_to :product, inverse_of: :product_tax_rates
belongs_to :tax_rate, inverse_of: :product_tax_rates
end
end
1 change: 1 addition & 0 deletions app/furniture/marketplace/products/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<%= render "text_field", { attribute: :name, form: f} %>
<%= render "text_area", { attribute: :description, form: f} %>
<%= render "money_field", { attribute: :price, form: f, min: 0, step: 0.01} %>
<%= render "collection_check_boxes", { attribute: :tax_rate_ids, collection: marketplace.tax_rates, value_method: :id, text_method: :label, form: f} %>
<%= f.submit %>
<% end %>
5 changes: 5 additions & 0 deletions app/furniture/marketplace/products/_product.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<td class="hidden px-3 py-4 text-sm text-gray-500 lg:table-cell">
<%= product.description %>
</td>

<td class="hidden px-3 py-4 text-sm text-gray-500 sm:table-cell">
<%= render product.tax_rates %>
</td>

<td class="hidden px-3 py-4 text-sm text-gray-500 sm:table-cell">
<%= humanized_money_with_symbol(product.price) %>
</td>
Expand Down
5 changes: 5 additions & 0 deletions app/furniture/marketplace/products/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">
<%= Marketplace::Product.human_attribute_name(:description) %>
</th>

<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:table-cell">
<%= Marketplace::Product.human_attribute_name(:tax_rates) %>
</th>

<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:table-cell">
<%= Marketplace::Product.human_attribute_name(:price) %>
</th>
Expand Down
3 changes: 2 additions & 1 deletion app/furniture/marketplace/tax_rate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class TaxRate < Record
self.location_parent = :marketplace

belongs_to :marketplace, inverse_of: :tax_rates
has_many :tax_rates, inverse_of: :tax_rates
has_many :product_tax_rates, inverse_of: :tax_rate
has_many :products, through: :product_tax_rates, inverse_of: :tax_rates
end
end
4 changes: 4 additions & 0 deletions app/views/application/_collection_check_boxes.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
<%= form.label attribute %>
<%= form.collection_check_boxes attribute, collection, value_method, text_method %>
</div>
11 changes: 11 additions & 0 deletions db/migrate/20230307031329_create_marketplace_product_tax_rates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateMarketplaceProductTaxRates < ActiveRecord::Migration[7.0]
def change
remove_reference :marketplace_products, :tax_rate

create_table :marketplace_product_tax_rates, id: :uuid do |t|
t.references :tax_rate, type: :uuid, foreign_key: {to_table: :marketplace_tax_rates}
t.references :product, type: :uuid, foreign_key: {to_table: :marketplace_products}
t.timestamps
end
end
end
18 changes: 13 additions & 5 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
"expired",
"ignored",
"revoked",
"sent"
"sent",
], force: :cascade

create_enum :membership_status, [
"active",
"revoked"
"revoked",
], force: :cascade

create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
Expand Down Expand Up @@ -140,6 +140,15 @@
t.index ["shopper_id"], name: "index_marketplace_orders_on_shopper_id"
end

create_table "marketplace_product_tax_rates", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "tax_rate_id"
t.uuid "product_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["product_id"], name: "index_marketplace_product_tax_rates_on_product_id"
t.index ["tax_rate_id"], name: "index_marketplace_product_tax_rates_on_tax_rate_id"
end

create_table "marketplace_products", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "marketplace_id"
t.string "name"
Expand All @@ -148,9 +157,7 @@
t.string "price_currency", default: "USD", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.uuid "tax_rate_id"
t.index ["marketplace_id"], name: "index_marketplace_products_on_marketplace_id"
t.index ["tax_rate_id"], name: "index_marketplace_products_on_tax_rate_id"
end

create_table "marketplace_shoppers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
Expand Down Expand Up @@ -231,8 +238,9 @@
add_foreign_key "marketplace_cart_products", "marketplace_orders", column: "cart_id"
add_foreign_key "marketplace_cart_products", "marketplace_products", column: "product_id"
add_foreign_key "marketplace_orders", "marketplace_shoppers", column: "shopper_id"
add_foreign_key "marketplace_product_tax_rates", "marketplace_products", column: "product_id"
add_foreign_key "marketplace_product_tax_rates", "marketplace_tax_rates", column: "tax_rate_id"
add_foreign_key "marketplace_products", "furniture_placements", column: "marketplace_id"
add_foreign_key "marketplace_products", "marketplace_tax_rates", column: "tax_rate_id"
add_foreign_key "marketplace_shoppers", "people"
add_foreign_key "marketplace_tax_rates", "furniture_placements", column: "marketplace_id"
add_foreign_key "memberships", "invitations"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

describe "#create" do
it "Creates a Product in the Marketplace" do
attributes = attributes_for(:marketplace_product)
tax_rate = create(:marketplace_tax_rate, marketplace: marketplace)
attributes = attributes_for(:marketplace_product, tax_rate_ids: [tax_rate.id])

sign_in(space, member)

Expand All @@ -22,6 +23,7 @@
expect(created_product.description).to eql(attributes[:description])
expect(created_product.price_cents).to eql(attributes[:price_cents])
expect(created_product.price_currency).to eql(Money.default_currency.to_s)
expect(created_product.tax_rates).to include(tax_rate)
end
end

Expand Down

0 comments on commit 0f46fc2

Please sign in to comment.