5 package App::LazyShoppingList::API::v1;
6 use App::LazyShoppingList::API;
13 use experimental 'signatures';
15 set charset => 'UTF-8';
16 set serializer => 'JSON';
18 # get the URI for the list of shopping lists
20 return { lists => uri_for('/list') };
23 # get the list of shopping lists
25 my $dbh = get_database;
28 my %r = ( lists_version => get_lists_version($dbh), lists => [] );
30 $dbh->resultset('ShoppingList')
32 { order_by => { -asc => 'name' } } )->all
36 { uri => uri_for( "/list/" . $list->id ), name => $list->name };
43 # create shopping list
45 my $req = request_data;
47 my $name = $req->{name};
49 return exception 400, "Missing list name";
52 my $dbh = get_database;
54 my $list = $dbh->resultset('ShoppingList')->create({
56 $list->discard_changes;
58 my $lists_ver = increment_lists_version($dbh);
63 uri => uri_for( '/list/' . $list->id ),
64 version => $list->version,
65 lists_version => $lists_ver
69 # get shopping list items
70 get '/list/:list_id' => sub {
71 my $list_id = route_parameters->get('list_id');
72 length($list_id) and $list_id =~ /^\d{1,18}$/ or return invalid_input;
74 my $dbh = get_database;
77 my %r = ( items => [] );
80 $r{lists_version} = get_lists_version($dbh);
82 my $list = $dbh->resultset('ShoppingList')->find($list_id);
86 return exception 404, "No list with that ID found";
89 $r{version} = $list->version;
91 my @items = $dbh->resultset('ShoppingListItem')->search(
92 { shopping_list => $list->id },
93 { order_by => { -asc => 'id' } }
95 for my $item (@items) {
98 uri_for( sprintf( "/list/%s/%s", $list->id, $item->id ) ),
99 description => $item->description,
100 done => JSON->boolean( $item->done ),
101 version => $item->version,
110 # create shopping list item
111 post '/list/:id' => sub {
112 my $list_id = route_parameters->get('id');
113 length($list_id) and $list_id =~ /^\d{1,18}$/
114 or return invalid_input('bad list ID');
116 my $req = request_data;
118 my $descr = $req->{description};
119 my $done = JSON->boolean( $req->{done} // 0 );
121 my $dbh = get_database;
125 lists_version => get_lists_version($dbh),
128 my $list = $dbh->resultset('ShoppingList')->find($list_id);
132 exception 404, "No such list";
135 my $item = $dbh->resultset('ShoppingListItem')->create(
136 { shopping_list => $list->id,
137 description => $descr,
141 $item->discard_changes;
143 $list->update( { version => $list->version + 1 } );
145 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
146 $r{version} = $item->version;
147 $r{list_version} = $list->version;
154 # modify shopping list item
155 put '/list/:list_id/:item_id' => sub {
156 my $list_id = route_parameters->get('list_id');
157 length($list_id) and $list_id =~ /^\d{1,18}$/
158 or return invalid_input('bad list ID');
160 my $item_id = route_parameters->get('item_id');
161 length($item_id) and $item_id =~ /^\d{1,18}$/
162 or return invalid_input('bad item ID');
164 my $req = request_data;
166 my $descr = $req->{description};
167 my $done = JSON->boolean( $req->{done} // 0 );
168 my $version = $req->{version};
170 length($version) and $version =~ /^\d{1,18}$/
171 or return invalid_input('bad version');
173 my $dbh = get_database;
177 lists_version => get_lists_version($dbh),
180 my $list = $dbh->resultset('ShoppingList')->find($list_id);
183 return exception 404, "No such list";
186 my $item = $dbh->resultset('ShoppingListItem')->find({shopping_list => $list->id, id => $item_id});
189 return exception 404, "No such item";
192 # in case no real changes are needed will return the current state
193 if ( defined($descr) and $descr ne ( $item->description // '' )
194 or defined($done) and $done != $item->done )
196 unless ($version == $item->version) {
198 return exception 409, exception =>
199 sprintf( 'Outdated version (current is %d)', $item->version );
203 defined($descr) ? (description => $descr) : (),
204 defined($done) ? (done => $done) : (),
205 version => $version + 1,
208 $list->update( { version => $list->version + 1 } );
211 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
212 $r{version} = $item->version;
213 $r{list_version} = $list->version;