mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-18 21:56:55 -04:00
Add transplant feature for plantings (#4133)
* Add ability to transplant a planting * Fix view tests * Transplantable gardens * Add spec --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Daniel O'Connor <daniel.oconnor@gmail.com>
This commit is contained in:
committed by
GitHub
parent
ac1463e2cf
commit
a98990ccd2
@@ -91,6 +91,32 @@ class PlantingsController < DataController
|
||||
respond_with @planting, location: @planting.garden
|
||||
end
|
||||
|
||||
def transplant
|
||||
# The `load_and_authorize_resource` in DataController will handle finding the
|
||||
# planting and authorizing the action.
|
||||
# We still need to authorize the new garden
|
||||
new_garden = Garden.find(params[:garden_id])
|
||||
authorize! :update, new_garden
|
||||
|
||||
# Mark original planting as finished
|
||||
@planting.update(finished: true, finished_at: Time.zone.now)
|
||||
|
||||
# Create a new planting
|
||||
new_planting = @planting.dup
|
||||
new_planting.garden = new_garden
|
||||
new_planting.slug = nil # let friendly_id generate a new slug
|
||||
new_planting.finished = false
|
||||
new_planting.finished_at = nil
|
||||
|
||||
if new_planting.save
|
||||
redirect_to edit_planting_path(new_planting), notice: 'Planting was successfully transplanted.'
|
||||
else
|
||||
# if the save fails, we should probably roll back the finishing of the original planting
|
||||
@planting.update(finished: false, finished_at: nil)
|
||||
redirect_to @planting, alert: "There was an error transplanting the planting: #{new_planting.errors.full_messages.to_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_crop_medians
|
||||
|
||||
@@ -43,6 +43,14 @@ module PlantingsHelper
|
||||
(planting.first_harvest_predicted_at - Time.zone.today).to_i
|
||||
end
|
||||
|
||||
# Returns a list of gardens the planting can be transplanted to
|
||||
# based on the planting's owner.
|
||||
def transplantable_gardens_by_owner(planting)
|
||||
garden_ids = planting.owner.gardens.select(:id).to_a + GardenCollaborator.where(member_id: planting.owner.id).select(:garden_id).to_a
|
||||
|
||||
Garden.active.where.not(id: planting.garden_id).where(id: garden_ids)
|
||||
end
|
||||
|
||||
def days_from_now_to_last_harvest(planting)
|
||||
return unless planting.planted_at.present? && planting.last_harvest_predicted_at.present?
|
||||
|
||||
|
||||
@@ -111,6 +111,10 @@ class Ability
|
||||
can :update, Planting do |planting|
|
||||
planting.garden.garden_collaborators.where(member_id: member.id).any?
|
||||
end
|
||||
can :transplant, Planting, garden: { owner_id: member.id }
|
||||
can :transplant, Planting do |planting|
|
||||
planting.garden.garden_collaborators.where(member_id: member.id).any?
|
||||
end
|
||||
can :destroy, Planting do |planting|
|
||||
planting.garden.garden_collaborators.where(member_id: member.id).any?
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ class Garden < ApplicationRecord
|
||||
include Geocodable
|
||||
include PhotoCapable
|
||||
include Ownable
|
||||
|
||||
friendly_id :garden_slug, use: %i(slugged finders)
|
||||
|
||||
has_many :plantings, dependent: :destroy
|
||||
@@ -44,6 +45,7 @@ class Garden < ApplicationRecord
|
||||
.where.not(gardens: { latitude: nil })
|
||||
.where.not(gardens: { longitude: nil })
|
||||
}
|
||||
|
||||
AREA_UNITS_VALUES = {
|
||||
"square metres" => "square metre",
|
||||
"square feet" => "square foot",
|
||||
|
||||
@@ -9,5 +9,13 @@
|
||||
= planting_finish_button(planting, classes: 'dropdown-item')
|
||||
= planting_harvest_button(planting, classes: 'dropdown-item')
|
||||
= planting_save_seeds_button(planting, classes: 'dropdown-item')
|
||||
- if can?(:transplant, planting) && planting.active && transplantable_gardens_by_owner(planting).any?
|
||||
.dropdown-divider
|
||||
.px-2
|
||||
= form_tag transplant_planting_path(planting), method: :post do
|
||||
.form-group
|
||||
= label_tag :garden_id, 'Transplant to:'
|
||||
= select_tag :garden_id, options_from_collection_for_select(transplantable_gardens_by_owner(planting), :id, :name), class: 'form-control form-control-sm'
|
||||
= submit_tag 'Transplant', class: 'btn btn-sm btn-primary mt-2'
|
||||
.dropdown-divider
|
||||
= delete_button(planting, classes: 'dropdown-item text-danger')
|
||||
|
||||
@@ -40,6 +40,9 @@ Rails.application.routes.draw do
|
||||
collection do
|
||||
get 'crop/:crop' => 'plantings#index', as: 'plantings_by_crop'
|
||||
end
|
||||
member do
|
||||
post :transplant
|
||||
end
|
||||
end
|
||||
|
||||
resources :seeds, concerns: :has_photos, param: :slug do
|
||||
|
||||
@@ -65,9 +65,9 @@ ActiveRecord::Schema[7.2].define(version: 2025_08_24_085224) do
|
||||
t.string "name", null: false
|
||||
t.integer "crop_id", null: false
|
||||
t.integer "creator_id", null: false
|
||||
t.string "language", null: false
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.string "language"
|
||||
end
|
||||
|
||||
create_table "authentications", id: :serial, force: :cascade do |t|
|
||||
|
||||
@@ -233,6 +233,29 @@ describe "Planting a crop", :js, :search do
|
||||
expect(page).to have_content "maize"
|
||||
end
|
||||
|
||||
describe "Transplanting a planting" do
|
||||
it "allows transplanting to another garden" do
|
||||
other_garden = FactoryBot.create(:garden, owner: member, name: 'Backyard')
|
||||
visit planting_path(planting)
|
||||
click_link 'Actions'
|
||||
select other_garden.name, from: 'Transplant to:'
|
||||
click_on "Transplant"
|
||||
expect(page).to have_content "Planting was successfully transplanted"
|
||||
|
||||
new_planting = Planting.last
|
||||
planting.reload
|
||||
|
||||
# The old planting is finished.
|
||||
expect(planting.finished).to be true
|
||||
expect(planting.finished_at).not_to be_nil
|
||||
|
||||
# The new planting is a continuation of the old one.
|
||||
expect(new_planting.garden).to eq(other_garden)
|
||||
expect(new_planting.crop).to eq(planting.crop)
|
||||
expect(new_planting.owner).to eq(planting.owner)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Marking a planting as finished without a date" do
|
||||
before do
|
||||
fill_autocomplete "crop", with: "mai"
|
||||
|
||||
Reference in New Issue
Block a user