| WebService-Buxfer documentation | Contained in the WebService-Buxfer distribution. |
transactions only)
WebService::Buxfer - Interact with the Buxfer webservice
use strict;
use warnings;
use WebService::Buxfer;
my $bux = WebService::Buxfer->new(
{
userid => 'nheinrichs', # Required
password => 'my password', # Required
preload_accounts => 1, # Default
inject_account_name => 1, # Default
debug => 0, # Default
url => 'https://www.buxfer.com/api', # Default
}
);
my $results = $bux->transactions;
print "Transaction: ".Dumper($_)."\n" for (@$results);
my $new_transactions = [
'coffee 5.45 tags:drinks,coffee', # Raw, Buxfer SMS format
'Pay check +6952.32 status:pending', # Raw, Buxfer SMS format
{ # As a hashref
description => 'Thai food with friends',
amount => -3000,
payer => 'me',
tags => ['sustenance, 'thai food'],
account => 'cash',
date => '2009-01-03',
status => 'default',
participants => [ [andy, 1000], elena ],
},
];
my @responses = $bux->add_transactions($new_transactions);
print "Response: ".($_->buxfer_status)."\n" for (@responses);
Buxfer is an online personal finance site: http://www.buxfer.com
WebService::Buxfer provides access to the Buxfer webservices API.
Build a new WebService::Buxfer instance.
Retrieve transactions (25 at a time.)
Results can be restricted using the following parameters (see Buxfer API documentation for details):
transactions only)NOTE: On any given day the format of the 'date' field in the transactions seems to change (sometimes I get '3 Jan' and sometimes '3 Jan 08'.)
This package makes no attempt to format or inflate dates or any other information returned from the API.
Get Analysis graph URLs and rawData.
Takes the same parameters as transactions.
Returns a hashref of Analysis information.
Retrieve Buxfer accounts.
In array context returns an array of hashrefs containing account details.
In scalar context returns a hashref of account details keyed on the internal Buxfer accountId.
i.e., { $accountId => { name => 'cash', ... }, ... }
Accepts an array of transactions in raw format or as hashrefs and submits
them to Buxfer using the add_transaction API call.
Because the Buxfer API allows for submission of multiple transactions in a
single API call, this method will combine transactions into batches based on
the max_transactions_per_submit parameter prior to submission.
WebService::Buxfer will also wrap tags containing spaces in single quotes. HOWEVER, the quotes themselves will also end up as part of the tag.
This is the fault of Buxfer's parser: if the single quotes are omitted, the system will fail to parse/import the transaction properly.
Parameters:
In array context returns an array of responses.
In scalar context returns a reference to the responses array.
Move some of the logic out of here and into WebService::Buxfer::Response.
Add a pager for flipping through transactions based on 25 results per page and numTransactions in the response.
Automatically in/deflate DateTime objects
Portions of this package borrowed/adapted from the WebService::Solr code.
Thanks to Brian Cassidy and Kirk Beers for that package.
Nathaniel Heinrichs <nheinric@cpan.org>
Copyright (c) 2009 Nathaniel Heinrichs. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| WebService-Buxfer documentation | Contained in the WebService-Buxfer distribution. |
package WebService::Buxfer; use Moose; use URI; use LWP::UserAgent; use HTTP::Request::Common; use WebService::Buxfer::Response; use WebService::Buxfer::Utils; use Carp qw(croak); our $VERSION = '0.01'; use 5.008; ################################################################################ ##### Options has 'preload_accounts' => ( is => 'ro', isa => 'Bool', default => 1 ); has 'inject_account_name' => ( is => 'rw', isa => 'Bool', default => 1 ); has 'data_format' => ( is => 'ro', isa => 'Str', default => 'json' ); has 'debug' => ( is => 'rw', isa => 'Bool', default => 0 ); has 'userid' => ( is => 'ro', isa => 'Str', required => 1); has 'password' => ( is => 'ro', isa => 'Str', required => 1); has 'url' => ( is => 'ro', isa => 'URI', default => sub { URI->new('https://www.buxfer.com/api') }, ); ################################################################################ ##### Internal Accessors has '_ua' => ( is => 'ro', isa => 'Object', default => sub { LWP::UserAgent->new }, ); has '_response' => ( is => 'rw', isa => 'Maybe[Object]',); has '_accounts' => ( is => 'rw', isa => 'Maybe[HashRef]',); has '_token' => ( is => 'rw', isa => 'Maybe[Str]',); has '_uid' => ( is => 'rw', isa => 'Maybe[Str]',); ################################################################################ ##### GET Methods sub transactions { return shift->_do_get('transactions', @_); } sub analysis { my $results = shift->_do_get('analysis', @_); $results->{buxferImageURL} and $results->{buxferImageURL} =~ s/&/&/g; $results->{imageURL} and $results->{imageURL} =~ s/&/&/g; return $results; } sub accounts { my $self = shift; unless ( $self->_accounts ) { # Accounts are more useful when keyed on accountId my %hash; map { $hash{$_->{'id'}} = $_; } $self->_do_get('accounts', @_); $self->_accounts(\%hash); } return wantarray ? values(%{$self->_accounts}) : $self->_accounts; } sub impacts { return shift->_do_get('impacts', @_); } sub tags { return shift->_do_get('tags', @_); } sub budgets { return shift->_do_get('budgets', @_); } sub groups { return shift->_do_get('groups', @_); } sub contacts { return shift->_do_get('contacts', @_); } ################################################################################ ##### POST Methods sub add_transactions { my ($self, $raw_txns, $params) = @_; my @responses = (); my $format = $params->{format} || 'sms'; WebService::Buxfer::Utils->max_transactions_per_submit( $params->{max_transactions_per_submit} || 1000 ); foreach my $text ( @{ &make_transactions($raw_txns) } ) { my $txn = { format => $format, text => $text, }; $self->_debug("Adding transaction(s):\n$text"); $self->_do_post('add_transaction', $txn); push @responses, $self->_response; } return wantarray ? @responses : \@responses; } ################################################################################ ##### Internal Methods sub _login { my ( $self ) = @_; # Return if we already have a token return if $self->_token; my $params = { userid => $self->userid, password => $self->password, }; my $response = WebService::Buxfer::Response->new( $self->_ua->request( GET $self->_build_url('login', $params) ) ); !$response->ok and croak("Login failed: ".$response->buxfer_status); $self->_token($response->content->{response}->{token}); $self->_uid($response->content->{response}->{uid}); $self->_debug("Authorization token is '".$self->_token."'"); $self->preload_accounts and $self->accounts; return $self->_response($response); } sub _do_get { my $self = shift; my ( $buxfer_method, $get_params ) = @_; $self->_call_api('GET', $buxfer_method, $get_params, {}); my $results = $self->_response->content->{response}->{$buxfer_method}; # Some API calls return results with a Buxfer internal accountId field. # For convenience, this method looks up the actual account name for you. $self->inject_account_name && $buxfer_method ne 'accounts' and &inject_accountName($self->accounts, $results); return wantarray ? @{$results} : $results; } sub _do_post { my $self = shift; my ( $buxfer_method, $post_params ) = @_; $self->_call_api('POST', $buxfer_method, {}, $post_params); my $results = $self->_response->content->{response};#->{$buxfer_method}; return wantarray ? @{$results} : $results; } sub _call_api { my ( $self, $method, $buxfer_method, $get_params, $post_params ) = @_; !$buxfer_method and croak("buxfer_method is undef"); $self->_login; $get_params->{token} = $self->_token || 'undef'; $post_params->{token} = $get_params->{token}; no strict 'refs'; my $response = WebService::Buxfer::Response->new( $self->_ua->request( &{"HTTP::Request::Common::".$method}($self->_build_url($buxfer_method, $get_params), $post_params) ) ); $self->_debug( "_call_api, status: '".$response->buxfer_status."'"); !$response->ok and croak("Error calling '$buxfer_method': ".$response->buxfer_status); return $self->_response($response); } sub _build_url { my ( $self, $buxfer_method, $params ) = @_; $params ||= {}; my $url = $self->url->clone; $url->path( $url->path . "/$buxfer_method.".$self->data_format ); $url->query_form( { %$params } ); $self->_debug("_build_url, '$buxfer_method' URL: '$url'"); return $url; } sub _debug { my $self = shift; print ref($self).": ".shift()."\n" if $self->debug; } 1; __END__