File Coverage

blib/lib/App/Dochazka/REST/Model/Schedhistory.pm
Criterion Covered Total %
statement 26 52 50.0
branch 0 4 0.0
condition n/a
subroutine 9 16 56.2
pod 7 7 100.0
total 42 79 53.1


line stmt bran cond sub pod time code
1             # *************************************************************************
2             # Copyright (c) 2014-2017, SUSE LLC
3             #
4             # All rights reserved.
5             #
6             # Redistribution and use in source and binary forms, with or without
7             # modification, are permitted provided that the following conditions are met:
8             #
9             # 1. Redistributions of source code must retain the above copyright notice,
10             # this list of conditions and the following disclaimer.
11             #
12             # 2. Redistributions in binary form must reproduce the above copyright
13             # notice, this list of conditions and the following disclaimer in the
14             # documentation and/or other materials provided with the distribution.
15             #
16             # 3. Neither the name of SUSE LLC nor the names of its contributors may be
17             # used to endorse or promote products derived from this software without
18             # specific prior written permission.
19             #
20             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30             # POSSIBILITY OF SUCH DAMAGE.
31             # *************************************************************************
32              
33              
34             use 5.012;
35 41     41   3543 use strict;
  41         135  
36 41     41   221 use warnings;
  41         85  
  41         706  
37 41     41   171 use App::CELL qw( $CELL $log $meta $site );
  41         86  
  41         1100  
38 41     41   200 use App::Dochazka::REST::Model::Shared qw( cud get_history load );
  41         100  
  41         4151  
39 41     41   1141 use Data::Dumper;
  41         111  
  41         2126  
40 41     41   273 use Params::Validate qw( :all );
  41         112  
  41         1714  
41 41     41   279  
  41         99  
  41         5589  
42             # we get 'spawn', 'reset', and accessors from parent
43             use parent 'App::Dochazka::Common::Model::Schedhistory';
44 41     41   283  
  41         89  
  41         269  
45              
46              
47              
48             =head1 NAME
49              
50             App::Dochazka::REST::Model::Schedhistory - schedule history functions
51              
52              
53              
54              
55             =head1 SYNOPSIS
56              
57             use App::Dochazka::REST::Model::Schedhistory;
58              
59             ...
60              
61              
62              
63             =head1 DESCRIPTION
64              
65             A description of the schedhistory data model follows.
66              
67              
68             =head2 Schedhistory in the database
69              
70             =head3 Table
71              
72             Once we know the SID of the schedule we would like to assign to a given
73             employee, it is time to insert a record into the C<schedhistory> table:
74              
75             CREATE TABLE IF NOT EXISTS schedhistory (
76             shid serial PRIMARY KEY,
77             eid integer REFERENCES employees (eid) NOT NULL,
78             sid integer REFERENCES schedules (sid) NOT NULL,
79             effective timestamp NOT NULL,
80             remark text,
81             stamp json
82             );
83              
84             =head3 Stored procedures
85              
86             This table also includes two stored procedures -- C<sid_at_timestamp> and
87             C<current_schedule> -- which will return an employee's schedule as of a given
88             date/time and as of 'now', respectively. For the procedure definitions, see
89             C<dbinit_Config.pm>
90              
91             See also L<When history changes take effect>.
92              
93              
94             =head2 Schedhistory in the Perl API
95              
96             =over
97              
98             =item * constructor (L<spawn>)
99              
100             =item * L<reset> method (recycles an existing object)
101              
102             =item * basic accessors (L<shid>, L<eid>, L<sid>, L<effective>, L<remark>)
103              
104             =item * L<load_by_eid> method (load schedhistory record from EID and optional timestamp)
105              
106             =item * L<load_by_shid> method (wrapper for load_by_id)
107              
108             =item * L<load_by_id> (load schedhistory record by its SHID)
109              
110             =item * L<insert> method (straightforward)
111              
112             =item * L<delete> method (straightforward) -- not tested yet # FIXME
113              
114             =back
115              
116             For basic workflow, see C<t/model/schedule.t>.
117              
118              
119              
120              
121             =head1 EXPORTS
122              
123             This module provides the following exports:
124              
125             =over
126              
127             =item L<get_schedhistory>
128              
129             =back
130              
131             =cut
132              
133             use Exporter qw( import );
134 41     41   65308 our @EXPORT_OK = qw( get_schedhistory );
  41         98  
  41         23805  
135              
136              
137              
138             =head1 METHODS
139              
140              
141             =head2 load_by_eid
142              
143             Class method. Given an EID, and, optionally, a timestamp, attempt to
144             look it up in the database. Generate a status object: if a schedhistory
145             record is found, it will be in the payload and the code will be
146             'DISPATCH_RECORDS_FOUND'.
147              
148             =cut
149              
150             my $self = shift;
151             my ( $conn, $eid, $ts ) = validate_pos( @_,
152 0     0 1   { isa => 'DBIx::Connector' },
153 0           { type => SCALAR }, # EID
154             { type => SCALAR|UNDEF, optional => 1 }, # optional timestamp
155             );
156              
157             if ( $ts ) {
158             return load(
159 0 0         conn => $conn,
160 0           class => __PACKAGE__,
161             sql => $site->SQL_SCHEDHISTORY_SELECT_ARBITRARY,
162             keys => [ $eid, $ts ],
163             );
164             }
165              
166             return load(
167             conn => $conn,
168 0           class => __PACKAGE__,
169             sql => $site->SQL_SCHEDHISTORY_SELECT_CURRENT,
170             keys => [ $eid ],
171             );
172             }
173            
174              
175              
176             =head2 load_by_id
177              
178             Given a shid, load a single schedhistory record.
179              
180             =cut
181              
182             my $self = shift;
183             my ( $conn, $shid ) = validate_pos( @_,
184             { isa => 'DBIx::Connector' },
185 0     0 1   { type => SCALAR }
186 0           );
187              
188             return load(
189             conn => $conn,
190             class => __PACKAGE__,
191 0           sql => $site->SQL_SCHEDHISTORY_SELECT_BY_SHID,
192             keys => [ $shid ],
193             );
194             }
195              
196              
197             =head2 load_by_shid
198              
199             Wrapper for load_by_id
200              
201             =cut
202              
203             my $self = shift;
204             my ( $conn, $shid ) = validate_pos( @_,
205             { isa => 'DBIx::Connector' },
206             { type => SCALAR }
207 0     0 1   );
208 0            
209             return $self->load_by_id( $conn, $shid );
210             }
211              
212              
213 0           =head2 insert
214              
215             Instance method. Attempts to INSERT a record into the 'Schedhistory' table.
216             Field values are taken from the object. Returns a status object.
217              
218             =cut
219              
220             my $self = shift;
221             my ( $context ) = validate_pos( @_, { type => HASHREF } );
222              
223             my $status = cud(
224             conn => $context->{'dbix_conn'},
225 0     0 1   eid => $context->{'current'}->{'eid'},
226 0           object => $self,
227             sql => $site->SQL_SCHEDHISTORY_INSERT,
228             attrs => [ 'eid', 'sid', 'effective', 'remark' ],
229             );
230 0            
231             return $status;
232             }
233              
234              
235             =head2 update
236 0            
237             Instance method. Updates the record. Returns status object.
238              
239             =cut
240              
241             my $self = shift;
242             my ( $context ) = validate_pos( @_, { type => HASHREF } );
243              
244             my $status = cud(
245             conn => $context->{'dbix_conn'},
246             eid => $context->{'current'}->{'eid'},
247 0     0 1   object => $self,
248 0           sql => $site->SQL_SCHEDHISTORY_UPDATE,
249             attrs => [ 'sid', 'effective', 'remark', 'shid' ],
250             );
251              
252 0           return $status;
253             }
254              
255              
256             =head2 delete
257              
258 0           Instance method. Deletes the record. Returns status object.
259              
260             =cut
261              
262             my $self = shift;
263             my ( $context ) = validate_pos( @_, { type => HASHREF } );
264              
265             my $status = cud(
266             conn => $context->{'dbix_conn'},
267             eid => $context->{'current'}->{'eid'},
268             object => $self,
269 0     0 1   sql => $site->SQL_SCHEDHISTORY_DELETE,
270 0           attrs => [ 'shid' ],
271             );
272             $self->reset( 'shid' => $self->{shid} ) if $status->ok;
273              
274 0           return $status;
275             }
276              
277              
278             =head2 get_schedhistory
279 0 0          
280             Takes a PARAMHASH which can have one or more of the properties 'eid', 'nick',
281 0           and 'tsrange'.
282              
283             At least one of { 'eid', 'nick' } must be specified. If both are specified,
284             the employee is determined according to 'eid'.
285              
286             The function returns the history of schedule changes for that employee
287             over the given tsrange, or the entire history if no tsrange is supplied.
288              
289             The return value will always be an L<App::CELL::Status|status> object.
290              
291             Upon success, the payload will be a reference to an array of C<schedhistory>
292             objects. If nothing is found, the array will be empty. If there is a DBI error,
293             the payload will be undefined.
294              
295             =cut
296              
297             my $context = shift;
298             return get_history( 'sched', $context->{'dbix_conn'}, @_ );
299             }
300              
301              
302              
303             =head1 EXAMPLES
304              
305 0     0 1   In this section, some examples are presented to give an idea of how this
306 0           module is used.
307              
308              
309             =head2 Sam Wallace joins the firm
310              
311             Let's say Sam's initial schedule is 09:00-17:00, Monday to Friday. To
312             reflect that, the C<schedintvls> table might contain the following intervals
313             for C<< sid = 9 >>
314              
315             '[2014-06-02 09:00, 2014-06-02 17:00)'
316             '[2014-06-03 09:00, 2014-06-03 17:00)'
317             '[2014-06-04 09:00, 2014-06-04 17:00)'
318             '[2014-06-05 09:00, 2014-06-05 17:00)'
319             '[2014-06-06 09:00, 2014-06-06 17:00)'
320              
321             and the C<schedhistory> table would contain a record like this:
322              
323             shid 848 (automatically assigned by PostgreSQL)
324             eid 39 (Sam's Dochazka EID)
325             sid 9
326             effective '2014-06-04 00:00'
327              
328             (This is a straightfoward example.)
329              
330              
331             =head2 Sam goes on night shift
332              
333             A few months later, Sam gets assigned to the night shift. A new
334             C<schedhistory> record is added:
335              
336             shid 1215 (automatically assigned by PostgreSQL)
337             eid 39 (Sam's Dochazka EID)
338             sid 17 (link to Sam's new weekly work schedule)
339             effective '2014-11-17 12:00'
340              
341             And the schedule intervals for C<< sid = 17 >> could be:
342              
343             '[2014-06-02 23:00, 2014-06-03 07:00)'
344             '[2014-06-03 23:00, 2014-06-04 07:00)'
345             '[2014-06-04 23:00, 2014-06-05 07:00)'
346             '[2014-06-05 23:00, 2014-06-06 07:00)'
347             '[2014-06-06 23:00, 2014-06-07 07:00)'
348            
349             (Remember: the date part in this case designates the day of the week)
350              
351              
352              
353              
354             =head1 AUTHOR
355              
356             Nathan Cutler, C<< <presnypreklad@gmail.com> >>
357              
358             =cut
359              
360             1;
361              
362              
363