App-Dochazka-CLI

 view release on metacpan or  search on metacpan

lib/App/Dochazka/CLI/Commands/Interval.pm  view on Meta::CPAN

    print "Entering " . __PACKAGE__ . "::interval_promptdate\n" if $debug_mode;
    my ( $ts, $th ) = @_;

    # parse test
    return parse_test( $ts, $th ) if $ts eq 'PARSE_TEST';

    print Dumper( $th ) if $debug_mode;

    # determine employee
    my $status = determine_employee( $th->{'EMPLOYEE_SPEC'} );
    return $status unless $status->ok;
    my $emp = $status->payload;

    return _interval_fillup_delete_print( $th, $emp, "[ $prompt_date 00:00, $prompt_date 24:00 )" );
}

sub _interval_fillup_delete_print {
    my ( $th, $emp, $tsr ) = @_;

    if ( $th->{'FILLUP'} ) {
        my %ARGS;
        $ARGS{eid} = $emp->eid;
        $ARGS{tsrange} = $tsr;
        $ARGS{dry_run} = exists( $th->{'DRY_RUN'} ) ? 1 : 0;
        $ARGS{clobber} = 0;
        return _fillup( %ARGS );
    } elsif ( $th->{'DELETE'} ) {
        return _delete_intervals_tsrange( $emp->eid, $tsr );
    } elsif ( $th->{'SUMMARY'} ) {
        return _interval_summary( $emp->eid, $tsr );
    } elsif ( $th->{'REPORT'} ) {
        return _interval_report( $emp, $tsr );
    } else {
        return _print_intervals_tsrange( $emp, $tsr );
    }
}


=head2 Helper functions

Functions called from command handlers


=head3 _interval_new

Takes code, tsrange and, optionally, long_desc. Converts the code into an AID,
sets up and sends the "POST interval/new" REST request, and returns the
resulting status object.

=cut

sub _interval_new {
    my ( $code, $tsrange, $long_desc ) = validate_pos( @_,
        { type => SCALAR },
        { type => SCALAR },
        { type => SCALAR|UNDEF, optional => 1 },
    );

    # get aid from code
    my $status = send_req( 'GET', "activity/code/$code" );
    if ( $status->not_ok ) {
        if ( $status->code eq "DISPATCH_SEARCH_EMPTY" and
             $status->text =~ m/Search over activity with key -\>code equals .+\<- returned nothing/
        ) {
            return $CELL->status_err( 'DOCHAZKA_CLI_WRONG_ACTIVITY', args => [ $code ] );
        }
        return rest_error( $status, "Determine AID from code" ) unless $status->ok;
    }
    my $aid = $status->payload->{'aid'};

    # assemble entity
    my $entity_perl = {
        'aid' => $aid,
        'intvl' => $tsrange,
    };
    $entity_perl->{'long_desc'} = $long_desc if $long_desc;
    my $entity = encode_json $entity_perl;

    # send the request
    $status = send_req( 'POST', "interval/new", $entity );
    if ( $status->not_ok ) {
        # if ... possible future checks for common errors
        # elsif ... other common errors
        return rest_error( $status, "Insert new attendance interval" ) unless $status->ok;
    }

    return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION',
        payload => _print_interval( $status->payload ) );
}


=head3 _tsrange_from_dates_and_times

Given two dates and two times, returns a full-fledged tsrange.
If the first date is undef or empty, use the prompt date.
If the second date is undef or empty, use the first date.

=cut

sub _tsrange_from_dates_and_times {
    my ( $d0, $d1, $t0, $t1 ) = @_;

    # normalize dates and times
    BREAK_OUT: {
        my $s = 1;
        my $flagged;

        # normalize_date will replace an undefined or empty date with the prompt date
        if ( $s = normalize_date( $d0 ) ) {
            $d0 = $s;
        } else {
            $flagged = $d0;
        }

        # for the second date, we have to check for undefined/empty-ness ourselves
        $d1 = $d0 unless defined( $d1 ) and length( $d1 ) > 0;

        if ( $s = normalize_date( $d1 ) ) {
            $d1 = $s;
        } else {
            $flagged = $d1;
        }

        if ( $s = normalize_time( $t0 ) ) {
            $t0 = $s;
        } else {
            $flagged = $t0;
        }

        if ( $s = normalize_time( $t1 ) ) {
            $t1 = $s;
        } else {
            $flagged = $t1;
        }

        last BREAK_OUT unless $flagged;
        $flagged = 'undefined' if not defined $flagged;
        return $CELL->status_err( 'DOCHAZKA_CLI_INVALID_DATE_OR_TIME', args => [ $flagged ] );
    }

    return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', payload => "[ $d0 $t0, $d1 $t1 )" );
}

=head3 _print_interval

Given an interval object (blessed or unblessed), construct a string
suitable for on-screen display.

=cut

sub _print_interval {
    my ( $int ) = @_;
    
    # get the activity code from the 'aid' property
    my $status = send_req( 'GET', "activity/aid/" . $int->{'aid'} );
    return rest_error( $status, "Determine activity code from AID" ) unless $status->ok;
    my $code = $status->payload->{'code'};

    # convert the interval into a readable form
    my $intvl = $int->{'intvl'};
    my $iid = $int->{'iid'};

    my $out = '';
    $out .= "Interval IID $iid\n";
    $out .= "$intvl $code";
    $out .= " " . $int->{'long_desc'} if defined( $int->{'long_desc'} );
    $out .= "\n";

    return $out;
}

=head3 _print_intervals_tsrange

Given an employee object and a tsrange, print all matching intervals

=cut

sub _print_intervals_tsrange {
    my ( $emp, $tsr ) = @_;
    my $eid = $emp->eid;
    my $nick = $emp->nick;

    my $status = send_req( 'GET', "interval/eid/$eid/$tsr" );
    if ( $status->not_ok and $status->code eq 'DISPATCH_NOTHING_IN_TSRANGE' ) {
        return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', payload => $status->text );
    }
    return rest_error( $status, "Get intervals for employee $nick (EID $eid) in range $tsr" ) 
        unless $status->ok;

    my $pl = '';
    $pl .= "Attendance intervals of $nick (EID $eid)\n";
    $pl .= "in the range $tsr\n\n";

    my $t = Text::Table->new( 'IID', 'Begin', 'End', 'Code', 'Description' );
    my $partial_intervals_present = 0;
    for my $props ( @{ $status->payload } ) {
        my $int = App::Dochazka::Common::Model::Interval->spawn( $props );
        my $iid;
        if ( $int->partial ) {
            $partial_intervals_present = 1;
            $iid = $int->iid . '**';
        } else {
            $iid = $int->iid;
        }
        $t->add( 
            $iid,
            _begin_and_end_from_intvl( $int->intvl ),
            $int->code,
            truncate_to( $int->long_desc ),
        );
    }
    $pl .= $t;
    $pl .= "\nPartial intervals signified by **\n" if $partial_intervals_present;

    return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', payload => $pl );
}


=head3 _begin_and_end_from_intvl

=cut

sub _begin_and_end_from_intvl {
    my $intvl = shift;

    my ( $d0, $t0, $d1, $t1 ) = $intvl =~ 
        m/(\d{4,4}-\d{2,2}-\d{2,2}).*(\d{2,2}:\d{2,2}):\d{2,2}.*(\d{4,4}-\d{2,2}-\d{2,2}).*(\d{2,2}:\d{2,2}):\d{2,2}/;

    return ( "$d0 $t0", "$d1 $t1" );
}

=head3 _delete_intervals_tsrange

Given an EID and a tsrange, delete all matching intervals

=cut

sub _delete_intervals_tsrange {
    my ( $eid, $tsr ) = @_;
    my $status = send_req( 'DELETE', "interval/eid/$eid/$tsr" );
    return $status unless $status->ok;
    my $count = $status->{'count'};
    return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', 
        payload => "$count intervals deleted in range $tsr" );



( run in 0.797 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )