Skip to content

Commit

Permalink
Marketplace: Create and Update TaxRate (#1186)
Browse files Browse the repository at this point in the history
- #1137

This throws together the basic `CRUD` operations for `TaxRate`. Going to
do a bit of tidying and add some tests, then record a video of the use
case.

I may decide I want to add in the setting of the `TaxRate` on the
`Product`, but maybe I'll wait and add that independently...

* `Marketplace`: Test Create and Update `TaxRate`

* 🧹 `Marketplace`: `TaxRate#tax_rate` is a  float! Like a 🚢

I think mayyybeeeeeeee it's better to support decimals.

* 🧹🛠️ `Marketplace`: Model `Product`<=>`TaxRate` relationship

This also addresses Ana's comments re: Tidying
  • Loading branch information
zspencer authored Mar 7, 2023
1 parent 4ab9f12 commit e846e87
Show file tree
Hide file tree
Showing 18 changed files with 185 additions and 6 deletions.
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ApplicationController < ActionController::Base
before_action :ensure_on_byo_domain

include Pundit::Authorization
after_action :verify_authorized
after_action :verify_authorized, except: [:index] # rubocop:disable Rails/LexicallyScopedActionFilter
after_action :verify_policy_scoped
before_action :prepend_theme_views

Expand Down
10 changes: 10 additions & 0 deletions app/furniture/marketplace/breadcrumbs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@
parent :marketplace_product, product
link "Edit", product.location(:edit)
end

crumb :new_tax_rate do |tax_rate|
parent :edit_marketplace, tax_rate.marketplace
link "Add a Tax Rate", marketplace.location(:new, child: :tax_rate)
end

crumb :edit_tax_rate do |tax_rate|
parent :edit_marketplace, tax_rate.marketplace
link "Edit Tax Rate '#{tax_rate.label}'", marketplace.location(:new, child: :tax_rate)
end
2 changes: 2 additions & 0 deletions app/furniture/marketplace/marketplace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Marketplace < FurniturePlacement
has_many :carts, inverse_of: :marketplace, dependent: :destroy
has_many :orders, inverse_of: :marketplace

has_many :tax_rates, inverse_of: :marketplace

# The Secret Stripe API key belonging to the owner of the Marketplace
def stripe_api_key
space.utility_hookups.find_by!(utility_slug: :stripe).utility.api_token
Expand Down
7 changes: 7 additions & 0 deletions app/furniture/marketplace/marketplaces/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@
<%= button_to t('marketplace.product.index'),
marketplace.location(child: :products), method: :get, data: { turbo: false } %>
<%- end %>

<h3>Tax Rates</h3>
<%= render policy_scope(marketplace.tax_rates) %>

<%- if policy(marketplace.tax_rates.new).create? %>
<%= link_to("Add Tax Rate", marketplace.location(:new, child: :tax_rate)) %>
<%- end %>
2 changes: 2 additions & 0 deletions app/furniture/marketplace/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +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

attribute :name, :string
validates :name, presence: true

Expand Down
2 changes: 2 additions & 0 deletions app/furniture/marketplace/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ def self.append_routes(router)
router.resource :checkout, only: [:show, :create]
end

router.resources :tax_rates

router.resources :orders, only: [:show]
router.resources :products
router.resource :stripe_account
Expand Down
9 changes: 9 additions & 0 deletions app/furniture/marketplace/tax_rate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Marketplace
class TaxRate < Record
self.table_name = "marketplace_tax_rates"
self.location_parent = :marketplace

belongs_to :marketplace, inverse_of: :tax_rates
has_many :tax_rates, inverse_of: :tax_rates
end
end
21 changes: 21 additions & 0 deletions app/furniture/marketplace/tax_rate_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Marketplace
class TaxRatePolicy < ApplicationPolicy
alias_method :tax_rate, :object

def create?
person.member_of?(tax_rate.marketplace.space)
end

alias_method :update?, :create?

def permitted_attributes(_)
[:label, :tax_rate]
end

class Scope < ApplicationScope
def resolve
scope.all
end
end
end
end
6 changes: 6 additions & 0 deletions app/furniture/marketplace/tax_rates/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= form_with(model: tax_rate.location) do |tax_rate_form| %>
<%= render "text_field", attribute: :label, form: tax_rate_form %>
<%= render "number_field", attribute: :tax_rate, form: tax_rate_form, required: true, step: 0.1, min: 0, max: 100 %>

<%= tax_rate_form.submit %>
<%- end %>
3 changes: 3 additions & 0 deletions app/furniture/marketplace/tax_rates/_tax_rate.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= link_to tax_rate.location(:edit) do %>
<%= tax_rate.label %>: <%= number_to_percentage(tax_rate.tax_rate, precision: 1) %>
<%- end %>
2 changes: 2 additions & 0 deletions app/furniture/marketplace/tax_rates/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%- breadcrumb :edit_tax_rate, tax_rate %>
<%= render "form", tax_rate: tax_rate %>
2 changes: 2 additions & 0 deletions app/furniture/marketplace/tax_rates/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%- breadcrumb :new_tax_rate, tax_rate %>
<%= render "form", tax_rate: tax_rate %>
39 changes: 39 additions & 0 deletions app/furniture/marketplace/tax_rates_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
class Marketplace
class TaxRatesController < Controller
def new
tax_rate
end

def create
if tax_rate.save
redirect_to marketplace.location(:edit)
else
render :new
end
end

def update
if tax_rate.update(tax_rate_params)
redirect_to marketplace.location(:edit)
else
render :edit
end
end

def tax_rate_params
policy(TaxRate).permit(params.require(:tax_rate))
end

helper_method def tax_rate
@tax_rate ||= if params[:id]
policy_scope(marketplace.tax_rates).find(params[:id])
elsif params[:tax_rate]
marketplace.tax_rates.new(tax_rate_params)
else
marketplace.tax_rates.new
end.tap do |tax_rate|
authorize(tax_rate)
end
end
end
end
7 changes: 5 additions & 2 deletions app/views/application/_number_field.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<% required ||= required | false %>
<% required = local_assigns[:required] || false %>
<% min = local_assigns[:min] %>
<% max = local_assigns[:max] %>
<% step = local_assigns[:step] %>
<div>
<%= form.label attribute %>
<%= form.number_field attribute, required: required %>
<%= form.number_field attribute, required: required, min: min, max: max, step: step %>
<%= render partial: "error", locals: { model: form.object, attribute: attribute } %>
</div>
14 changes: 14 additions & 0 deletions db/migrate/20230305005417_create_marketplace_tax_rates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateMarketplaceTaxRates < ActiveRecord::Migration[7.0]
def change
create_table :marketplace_tax_rates, id: :uuid do |t|
t.float :tax_rate
t.string :label
t.references :marketplace, type: :uuid, foreign_key: {to_table: :furniture_placements}
t.timestamps
end

change_table :marketplace_products do |t|
t.references :tax_rate, type: :uuid, foreign_key: {to_table: :marketplace_tax_rates}
end
end
end
19 changes: 16 additions & 3 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_03_04_003325) do
ActiveRecord::Schema[7.0].define(version: 2023_03_05_005417) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
Expand All @@ -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 @@ -148,7 +148,9 @@
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 All @@ -158,6 +160,15 @@
t.index ["person_id"], name: "index_marketplace_shoppers_on_person_id", unique: true
end

create_table "marketplace_tax_rates", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.float "tax_rate"
t.string "label"
t.uuid "marketplace_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["marketplace_id"], name: "index_marketplace_tax_rates_on_marketplace_id"
end

create_table "memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "member_id"
t.uuid "space_id"
Expand Down Expand Up @@ -222,7 +233,9 @@
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_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"
add_foreign_key "spaces", "rooms", column: "entrance_id"
end
5 changes: 5 additions & 0 deletions spec/factories/furniture/marketplace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,9 @@

factory :marketplace_shopper, class: "Marketplace::Shopper" do
end

factory :marketplace_tax_rate, class: "Marketplace::TaxRate" do
label { "#{Faker::TvShows::RuPaul.queen} Tax" }
tax_rate { (1..45).to_a.sample }
end
end
39 changes: 39 additions & 0 deletions spec/furniture/marketplace/tax_rates_controller_request_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require "rails_helper"

RSpec.describe Marketplace::TaxRatesController, type: :request do
subject(:result) do
perform_request
test_response
end

before { sign_in(space, person) }

let(:space) { marketplace.space }
let(:marketplace) { create(:marketplace) }
let(:person) { create(:membership, space: space).member }

describe "#new" do
let(:perform_request) { get polymorphic_path(marketplace.location(:new, child: :tax_rate)) }

it { is_expected.to be_ok }
end

describe "#create" do
let(:perform_request) do
post polymorphic_path(marketplace.location(child: :tax_rates)), params: {tax_rate: attributes_for(:marketplace_tax_rate)}
end

it { is_expected.to redirect_to(marketplace.location(:edit)) }
end

describe "#update" do
let(:tax_rate) { create(:marketplace_tax_rate, marketplace: marketplace) }
let(:perform_request) do
put polymorphic_path(tax_rate.location), params: {tax_rate: {label: "Hey", tax_rate: 23}}
end

it { is_expected.to redirect_to(marketplace.location(:edit)) }
specify { expect { result }.to change { tax_rate.reload.label }.to("Hey") }
specify { expect { result }.to change { tax_rate.reload.tax_rate }.to(23) }
end
end

0 comments on commit e846e87

Please sign in to comment.