diff --git a/lib/Coocook/Controller/Dish.pm b/lib/Coocook/Controller/Dish.pm index 0caf15e63725c1ad7ff3bebb20325edb5fa74755..8ad4b0409deb2d49b2a25fd023112e1750a0c38d 100644 --- a/lib/Coocook/Controller/Dish.pm +++ b/lib/Coocook/Controller/Dish.pm @@ -88,8 +88,9 @@ sub edit : GET HEAD Chained('base') PathPart('') Args(0) RequiresCapability('vie articles => $ingredients->all_articles, units => $ingredients->all_units, prepare_meals => [ $prepare_meals->all ], - add_ingredient_url => $c->project_uri( '/dish/add', $dish->id ), - delete_url => $c->project_uri( '/dish/delete', $dish->id ), + add_ingredient_url => $c->project_uri( '/dish/add', $dish->id ), + delete_url => $c->project_uri( '/dish/delete', $dish->id ), + create_recipe_url => $c->project_uri( '/recipe/from_dish', $dish->id ), ); for my $ingredient ( @{ $c->stash->{ingredients} } ) { diff --git a/lib/Coocook/Controller/Recipe.pm b/lib/Coocook/Controller/Recipe.pm index 5a04e5ffcd8bc01f117404d57653aff46d8d34a1..6901629442edc2f53e435638dc0d2355e30b060f 100644 --- a/lib/Coocook/Controller/Recipe.pm +++ b/lib/Coocook/Controller/Recipe.pm @@ -170,6 +170,22 @@ sub create : POST Chained('submenu') Args(0) RequiresCapability('edit_project') } +sub from_dish : POST Chained('/project/base') PathPart('recipes/from_dish') Args(1) + RequiresCapability('edit_project') { + my ( $self, $c, $dish_id ) = @_; + + my $dish = $c->project->dishes->find($dish_id); + + if ( $c->project->find_related( recipes => { name => $dish->name } ) ) { + $c->messages->error("Recipe with that name does already exist"); + $c->detach( '/dish/redirect' => [ $dish->id ] ); + } + + my $recipe = $c->model('DB::Recipe')->from_dish($dish); + + $c->response->redirect( $c->project_uri( '/recipe/edit', $recipe->id ) ); +} + sub duplicate : POST Chained('base') Args(0) RequiresCapability('edit_project') { my ( $self, $c ) = @_; diff --git a/lib/Coocook/Schema/Component/ResultSet/Ingredient.pm b/lib/Coocook/Schema/Component/ResultSet/Ingredient.pm new file mode 100644 index 0000000000000000000000000000000000000000..5534d8ae7ba253522be1a49394ecf3eb31824a68 --- /dev/null +++ b/lib/Coocook/Schema/Component/ResultSet/Ingredient.pm @@ -0,0 +1,35 @@ +package Coocook::Schema::Component::ResultSet::Ingredient; + +# ABSTRACT: common methods for ResultSet::DishIngredient and ResultSet::RecipeIngredient + +use strict; +use warnings; + +use feature 'fc'; # Perl v5.16 + +=head1 METHODS + +=head2 copy_from_rs($resultset) + +Copy ingredients from another dish or recipe. +Can copy from dish to recipe or vice versa. + +=cut + +sub copy_from_rs { + my ( $self, $rs ) = @_; + + my @columns = qw( position prepare article_id unit_id value comment ); + + # TODO could even use arrayref inflator for more speed + $self->populate( [ $rs->search( undef, { columns => \@columns } )->hri->all ] ); + + return $self; +} + +sub sorted_by_columns { 'position' } + +sub prepared { shift->search( { -bool => 'prepare' } ) } +sub not_prepared { shift->search( { -not_bool => 'prepare' } ) } + +1; diff --git a/lib/Coocook/Schema/ResultSet/Dish.pm b/lib/Coocook/Schema/ResultSet/Dish.pm index 52c3ad97cf78a870a79dc65076040f0b945bb88a..4d2eb706917e5af9bea52db9b9b5f23cd63e9041 100644 --- a/lib/Coocook/Schema/ResultSet/Dish.pm +++ b/lib/Coocook/Schema/ResultSet/Dish.pm @@ -20,19 +20,17 @@ sub from_recipe { meal_id => $args{meal}, comment => $args{comment}, - name => $args{name} || $recipe->name, - description => $args{description} || $recipe->description, - preparation => $args{preparation} || $recipe->preparation, + map { $_ => $args{comment} || $recipe->get_column($_) } qw( + name + description + preparation + ) } ); $dish->set_tags( [ $recipe->tags->all ] ); - # copy ingredients - for my $ingredient ( $recipe->ingredients->all ) { - $dish->create_related( - ingredients => { map { $_ => $ingredient->$_ } qw } ); - } + $dish->ingredients->copy_from_rs( $recipe->ingredients ); # adjust values of dish ingredients to new servings if ( my $servings = $args{servings} ) { diff --git a/lib/Coocook/Schema/ResultSet/DishIngredient.pm b/lib/Coocook/Schema/ResultSet/DishIngredient.pm index 67fa751b30a04115029b2226e63449af97ab3654..e9d27db01245d80536ca6276a4e7d15e26177282 100644 --- a/lib/Coocook/Schema/ResultSet/DishIngredient.pm +++ b/lib/Coocook/Schema/ResultSet/DishIngredient.pm @@ -5,18 +5,13 @@ use namespace::autoclean; extends 'Coocook::Schema::ResultSet'; -sub sorted_by_columns { 'position' } - -__PACKAGE__->load_components('+Coocook::Schema::Component::ResultSet::SortByName'); +__PACKAGE__->load_components( + '+Coocook::Schema::Component::ResultSet::Ingredient', + '+Coocook::Schema::Component::ResultSet::SortByName', +); __PACKAGE__->meta->make_immutable; -sub prepared { - my $self = shift; - - return $self->search( { -bool => $self->me('prepare') } ); -} - sub unassigned { my $self = shift; diff --git a/lib/Coocook/Schema/ResultSet/Recipe.pm b/lib/Coocook/Schema/ResultSet/Recipe.pm index 619eba1d79ea7ad4079fba525ffe30d9dad714ea..93d192c11da512c9034b8099183c0db858dc49fb 100644 --- a/lib/Coocook/Schema/ResultSet/Recipe.pm +++ b/lib/Coocook/Schema/ResultSet/Recipe.pm @@ -9,6 +9,35 @@ __PACKAGE__->load_components('+Coocook::Schema::Component::ResultSet::SortByName __PACKAGE__->meta->make_immutable; +sub from_dish { + my ( $self, $dish, %args ) = @_; + + return $self->txn_do( + sub { + my $recipe = $self->create( + { + project_id => $dish->meal->project_id, + servings => $dish->servings, + map { $_ => $args{$_} || $dish->get_column($_) } + qw( + name + description + preparation + ) + } + ); + + $recipe->set_tags( [ $dish->tags->all ] ); + + $recipe->ingredients->copy_from_rs( $dish->ingredients ); + + # TODO set from_recipe on dish? #179 + + return $recipe; + } + ); +} + sub public { my $self = shift; diff --git a/lib/Coocook/Schema/ResultSet/RecipeIngredient.pm b/lib/Coocook/Schema/ResultSet/RecipeIngredient.pm index abe1c2596a56be25251120228de993468d6653d8..06098128cfd22242bd22fd3df19680469c79137b 100644 --- a/lib/Coocook/Schema/ResultSet/RecipeIngredient.pm +++ b/lib/Coocook/Schema/ResultSet/RecipeIngredient.pm @@ -5,13 +5,11 @@ use namespace::autoclean; extends 'Coocook::Schema::ResultSet'; -sub sorted_by_columns { 'position' } - -__PACKAGE__->load_components('+Coocook::Schema::Component::ResultSet::SortByName'); +__PACKAGE__->load_components( + '+Coocook::Schema::Component::ResultSet::Ingredient', + '+Coocook::Schema::Component::ResultSet::SortByName', +); __PACKAGE__->meta->make_immutable; -sub prepared { shift->search( { -bool => 'prepare' } ) } -sub not_prepared { shift->search( { -not_bool => 'prepare' } ) } - 1; diff --git a/root/templates/dish/edit.tt b/root/templates/dish/edit.tt index a32d652f540e5cbdfe3c9e98cc61a8c1c8d94352..046af091098ef4fe1f1d9d0c7b7eb3af11a32ec2 100644 --- a/root/templates/dish/edit.tt +++ b/root/templates/dish/edit.tt @@ -13,14 +13,19 @@ js.push('/lib/coocook-web-components/dist/ingredients-editor/ingredients-editor.
-
+
+
+ +
+
-
diff --git a/root/templates/recipe/edit.tt b/root/templates/recipe/edit.tt index 0c3665bc97d91f511d5b4cea3eaa00d4c7c01996..36d7a43da126691eda931a7a57383e84b87a1ea7 100644 --- a/root/templates/recipe/edit.tt +++ b/root/templates/recipe/edit.tt @@ -14,7 +14,9 @@ IF import_url %]
[ [% IF public_url %] - + [% END; IF import_url %] diff --git a/t/schema_Recipe.t b/t/schema_Recipe.t index 035f248dec4f0ea98115ee2fde19c44309943431..2296c655e52eca1c192d8b514e5fbe651f021ab2 100644 --- a/t/schema_Recipe.t +++ b/t/schema_Recipe.t @@ -17,4 +17,54 @@ subtest duplicate => sub { is $clone->ingredients->count => $recipe->ingredients->count, "number of ingredients equal"; }; +subtest from_dish => sub { + my $db = TestDB->new; + + my $dish = $db->resultset('Dish')->find(1); + + ok my $recipe = $db->resultset('Recipe')->from_dish($dish); + + is [ $recipe->ingredients->hri->all ] => bag { + item hash { + field position => 1; + field value => 500.0; # half as in recipe + field unit_id => 1; # grams + field article_id => 1; # flour + etc; + }; + item hash { field position => 2; etc }; + item hash { field position => 3; etc }; + }; +}; + +subtest from_recipe => sub { + my $db = TestDB->new; + + my $recipe = $db->resultset('Recipe')->find(1); + + ok my $dish = $db->resultset('Dish')->from_recipe( + $recipe, + meal => 1, + comment => __FILE__, + servings => 2, # half as recipe + ); + + is $dish->from_recipe_id => $recipe->id; + is $dish->servings => 2; + is $dish->comment => __FILE__; + + is [ $dish->ingredients->hri->all ] => bag { + item hash { + field position => 1; + field value => 0.25; # half as in recipe + field unit_id => 3; # liters + field article_id => 3; # water + etc; + }; + item hash { field position => 2; etc }; + item hash { field position => 3; etc }; + item hash { field position => 4; etc }; + }; +}; + done_testing;