summaryrefslogblamecommitdiffstats
path: root/lib/WWW/YNAB/Budget.pm
blob: 1cffd883c8f5e132e966de389d7b525d13706b62 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
                          
 

          
          
                               





                                                          
















                                                                       





                      



            




                 



                        




                         



                   




                    



                  




                   



                        




                         



                











                                               



              











                                             









                        












                                                     



              











                                             



                    











                                                   



                              











                                                            
















                                                                  





                                   
























                                                                                





                                    



















                                                                        





                                 



















                                                                    





                                 













                                                                    






















                                                                               
















































                                                                                                    





                                       













                                                                          















                                                                                    





                                                 













                                                                                    



                                  
package WWW::YNAB::Budget;


use 5.010;
use Moose;
# ABSTRACT: Budget model object

use Carp;
use Moose::Util::TypeConstraints qw(find_type_constraint);

with 'WWW::YNAB::ModelHelpers';

=head1 SYNOPSIS

  use WWW::YNAB;

  my $ynab = WWW::YNAB->new(...);
  my $budget = $ynab->budget('12345678-1234-1234-1234-1234567890ab');

=head1 OVERVIEW

See L<https://api.youneedabudget.com/v1#/Budgets> for more information.

=cut

=method id

=cut

has id => (
    is       => 'ro',
    isa      => 'Str',
    required => 1,
);

=method name

=cut

has name => (
    is  => 'ro',
    isa => 'Str',
);

=method last_modified_on

=cut

has last_modified_on => (
    is  => 'ro',
    isa => 'Str',
);

=method first_month

=cut

has first_month => (
    is  => 'ro',
    isa => 'Str',
);

=method last_month

=cut

has last_month => (
    is  => 'ro',
    isa => 'Str',
);

=method server_knowledge

=cut

has server_knowledge => (
    is  => 'ro',
    isa => 'Int',
);

=method accounts

=cut

has _accounts => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::Account]',
    init_arg => 'accounts',
    lazy     => 1,
    builder  => '_build_accounts',
    handles  => {
        accounts => 'elements',
    }
);

=method payees

=cut

has _payees => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::Payee]',
    init_arg => 'payees',
    lazy     => 1,
    builder  => '_build_payees',
    handles  => {
        payees => 'elements',
    }
);

=method categories

=cut

=method category_groups

Alias for C<categories>.

=cut

has _category_groups => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::CategoryGroup]',
    init_arg => 'category_groups',
    lazy     => 1,
    builder  => '_build_categories',
    handles  => {
        categories      => 'elements',
        category_groups => 'elements',
    }
);

=method months

=cut

has _months => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::Month]',
    init_arg => 'months',
    lazy     => 1,
    builder  => '_build_months',
    handles  => {
        months => 'elements',
    }
);

=method transactions

=cut

has _transactions => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::Transaction]',
    init_arg => 'transactions',
    lazy     => 1,
    builder  => '_build_transactions',
    handles  => {
        transactions => 'elements',
    }
);

=method scheduled_transactions

=cut

has _scheduled_transactions => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => 'ArrayRef[WWW::YNAB::ScheduledTransaction]',
    init_arg => 'scheduled_transactions',
    lazy     => 1,
    builder  => '_build_scheduled_transactions',
    handles  => {
        scheduled_transactions => 'elements',
    }
);

has _ua => (
    is       => 'ro',
    isa      => 'WWW::YNAB::UA',
    required => 1,
);

sub _build_accounts {
    my $self = shift;

    my $data = $self->_ua->get("/budgets/${\$self->id}/accounts");
    [
        map {
            $self->model_from_data('WWW::YNAB::Account', $_)
        } @{ $data->{data}{accounts} }
    ]
}

=method account($id)

Returns the account with id C<$id>.

=cut

sub account {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/accounts/$id");
    my $account = $data->{data}{account};
    $self->model_from_data('WWW::YNAB::Account', $account);
}

sub _build_categories {
    my $self = shift;

    my $data = $self->_ua->get("/budgets/${\$self->id}/categories");
    [
        map {
            my %category_group = %$_;
            my @categories = map {
                $self->model_from_data('WWW::YNAB::Category', $_)
            } @{ $category_group{categories} };
            $category_group{categories} = \@categories;
            $self->model_from_data('WWW::YNAB::CategoryGroup', \%category_group)
        } @{ $data->{data}{category_groups} }
    ]
}

=method category($id)

Returns the category with id C<$id>.

=cut

sub category {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/categories/$id");
    my $category = $data->{data}{category};
    $self->model_from_data('WWW::YNAB::Category', $category);
}

sub _build_payees {
    my $self = shift;

    my $data = $self->_ua->get("/budgets/${\$self->id}/payees");
    [
        map {
            $self->model_from_data('WWW::YNAB::Payee', $_)
        } @{ $data->{data}{payees} }
    ]
}

=method payee($id)

Returns the payee with id C<$id>.

=cut

sub payee {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/payees/$id");
    my $payee = $data->{data}{payee};
    $self->model_from_data('WWW::YNAB::Payee', $payee);
}

sub _build_months {
    my $self = shift;

    my $data = $self->_ua->get("/budgets/${\$self->id}/months");
    [
        map {
            $self->model_from_data('WWW::YNAB::Month', $_)
        } @{ $data->{data}{months} }
    ]
}

=method month($id)

Returns the month with id C<$id>.

=cut

sub month {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/months/$id");
    my $month = $data->{data}{month};
    my %month = %$month;
    my @categories = map {
        $self->model_from_data('WWW::YNAB::Category', $_)
    } @{ $month{categories} };
    $month{categories} = \@categories;
    $self->model_from_data('WWW::YNAB::Month', \%month);
}

=method find_transactions(%query)

Finds transactions based on query parameters. Valid options are (all optional):

=over 4

=item account

=item category

=item payee

=item type

=item since_date

=back

Note that only one of C<account>, C<category>, C<payee>, or C<type> may be
specified.

=cut

sub find_transactions {
    my $self = shift;
    my %query = @_;

    if ((grep { defined } @query{qw(account category payee type)}) > 1) {
        croak "You can only query transactions by at most one of account, category, payee, or type";
    }

    my $path;
    if ($query{account}) {
        $path = "/budgets/${\$self->id}/accounts/$query{account}/transactions";
    }
    elsif ($query{category}) {
        $path = "/budgets/${\$self->id}/categories/$query{category}/transactions";
    }
    elsif ($query{payee}) {
        $path = "/budgets/${\$self->id}/payees/$query{payee}/transactions";
    }
    else {
        $path = "/budgets/${\$self->id}/transactions";
    }

    my $params;
    if ($query{type}) {
        $params ||= {};
        $params->{type} = $query{type};
    }
    if ($query{since_date}) {
        $params ||= {};
        $params->{since_date} = $query{since_date};
    }

    my $data = $self->_ua->get($path, $params);
    map {
        my %transaction = %$_;
        my @subtransactions = map {
            $self->model_from_data('WWW::YNAB::SubTransaction', $_)
        } @{ $transaction{subtransactions} };
        $transaction{subtransactions} = \@subtransactions;
        $self->model_from_data('WWW::YNAB::Transaction', \%transaction)
    } @{ $data->{data}{transactions} };
}

sub _build_transactions {
    my $self = shift;

    $self->find_transactions
}

=method transaction($id)

Returns the transaction with id C<$id>.

=cut

sub transaction {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/transactions/$id");
    my $transaction = $data->{data}{transaction};
    my %transaction = %$transaction;
    my @subtransactions = map {
        $self->model_from_data('WWW::YNAB::SubTransaction', $_)
    } @{ $transaction{subtransactions} };
    $transaction{subtransactions} = \@subtransactions;
    $self->model_from_data('WWW::YNAB::Transaction', \%transaction);
}

sub _build_scheduled_transactions {
    my $self = shift;

    my $data = $self->_ua->get("/budgets/${\$self->id}/scheduled_transactions");
    [
        map {
            my %transaction = %$_;
            my @subtransactions = map {
                $self->model_from_data('WWW::YNAB::ScheduledSubTransaction', $_)
            } @{ $transaction{subtransactions} };
            $transaction{subtransactions} = \@subtransactions;
            $self->model_from_data('WWW::YNAB::ScheduledTransaction', \%transaction)
        } @{ $data->{data}{scheduled_transactions} }
    ]
}

=method scheduled_transaction($id)

Returns the scheduled transaction with id C<$id>.

=cut

sub scheduled_transaction {
    my $self = shift;
    my ($id) = @_;

    my $data = $self->_ua->get("/budgets/${\$self->id}/scheduled_transactions/$id");
    my $transaction = $data->{data}{scheduled_transaction};
    my %transaction = %$transaction;
    my @subtransactions = map {
        $self->model_from_data('WWW::YNAB::ScheduledSubTransaction', $_)
    } @{ $transaction{subtransactions} };
    $transaction{subtransactions} = \@subtransactions;
    $self->model_from_data('WWW::YNAB::ScheduledTransaction', \%transaction);
}

__PACKAGE__->meta->make_immutable;
no Moose;

1;