NAME
    WebService::Basecamp - Perl interface to the Basecamp API webservice

SYNOPSIS
     use WebService::Basecamp;
 
     my $bc = WebService::Basecamp->new( url  => 'http://mysite.clientsection.com',
                                         user => 'username',
                                         pass => 'password'    );

     my $test = $bc->ping || die $bc->error();

     my $projects = $bc->projects;  # a list of all projects

DESCRIPTION
    Basecamp is a web based project collaboration tool that makes it simple
    to communicate and collaborate on projects. Basecamp is built on the
    Ruby on Rails platform but provides a webservice API to many of the
    application functions. WebService::Basecamp is a Perl interface to the
    Basecamp web service API.

    For more information on Basecamp, visit the Basecamp website.
    http://www.bascamphq.com.

    This module does much of the heavy lifting for you when accessing the
    Basecamp API. Once initialising a WebService::Basecamp object you can
    access the API function via method calls. The module takes care of the
    creation and parsing of the XML (using XML::Simple) that relays the data
    across the web service, however there is an option to access the XML
    directly (see new()).

    The documentation for this module is based on the Basecamp API docs
    available at http://www.basecamphq.com/api. It is recommended you read
    the official docs to become familiar with the data reference.

METHODS
    new(url => $url, user => $username, pass => $password, [ xml => $xml ])
        Call new() to create a new Basecamp object. You must pass the url of
        your Basecamp account, a username and password.

         my $bc = WebService::Basecamp->new( url  => 'http://mysite.clientsection.com', 
                                             user => $username, 
                                             pass => $password );

        By default, all methods return a data reference. If you would prefer
        to receive the raw XML from the webservice you can pass the 'xml'
        parameter. E.g.

         my $bc = WebService::Basecamp->new( url  => 'http://mysite.clientsection.com', 
                                             user => $username, 
                                             pass => $password,
                                             xml  => 1 );

    error()
        Returns any error messages as a string.

    ping()
        Tests the connection with the Basecamp web service. Returns 1 for
        success.

  General Queries
    projects([$key])
        This will return a list of all active, on-hold, and archived
        projects that you have access to. The list is not ordered.

        This method returns a reference to a hash containing an array of
        file category names and id.

         use Data::Dumper;
         my $projects = $bc->projects;
         print Dumper($projects);

         returns: 

         $VAR1 = [
                  {
                    'start-page' => 'all',
                    'show-writeboards' => 'false',
                    'status' => 'active',
                    'name' => 'Create World Peace',
                    'created-on' => '2004-05-31',
                    'last-changed-on' => '2004-09-07T02:49:12Z',
                    'id' => '123456',
                    'announcement' => {},
                    'show-announcement' => 'false',
                    'company' => {
                                   'name' => 'Earth',
                                   'id' => '888'
                                 }
                  },
                  {
                    'start-page' => 'log',
                    'show-writeboards' => 'false',
                    'status' => 'active',
                    'name' => 'Basecamp CPAN Module',
                    'created-on' => '2006-07-26',
                    'last-changed-on' => '2006-07-29T04:08:34Z',
                    'id' => '654321',
                    'announcement' => {},
                    'show-announcement' => 'false',
                    'company' => {
                                   'name' => 'Internal',
                                   'id' => '555'
                                 }
                  }
                ];

        If you pass the optional $key parameter to the method you will
        recieve a keyed hash of the project data. The key must be either
        'name' or 'id', e.g.:

         use Data::Dumper
         my $projects = $bc->projects('name');
         print Dumper($projects);
 
         returns: 

         $VAR1 = [
                  'Create World Peace' => {
                            'start-page' => 'all',
                            'status' => 'active',
                            'show-writeboards' => 'false',
                            'created-on' => '2004-05-31',
                            'last-changed-on' => '2004-09-07T02:49:12Z',
                            'show-announcement' => 'false',
                            'id' => '123456',
                            'announcement' => {},
                            'company' => {
                                           'name' => 'Earth',
                                           'id' => '888'
                                         }
                          },
                  'Basecamp CPAN Module' => {
                              'start-page' => 'log',
                              'status' => 'active',
                              'show-writeboards' => 'false',
                              'created-on' => '2006-07-26',
                              'last-changed-on' => '2006-07-29T04:08:34Z',
                              'show-announcement' => 'false',
                              'id' => '654321',
                              'announcement' => {},
                              'company' => {
                                             'name' => 'Internal',
                                             'id' => '555'
                                           }
                            }
                ];

    file_categories($project_id [,$key])
        This will return an alphabetical list of all file categories in the
        referenced project. Requires the $project_id to be passed as an
        argument.

        By default this method returns a reference to an array of hashes. If
        you would prefer a keyed hash, you can specify the optional key. The
        available key options are 'name' or 'id'.

    message_categories($project_id [,$key])
        This will return an alphabetical list of all message categories in
        the referenced project. Requires the $project_id to be passed as an
        argument.

        By default this method returns a reference to an array of hashes. If
        you would prefer a keyed hash, you can specify the optional key. The
        available key options are 'name' or 'id'.

  Messages and Comments
    comment($comment_id)
        Retrieve a specific comment by its id.

    comments($message_id)
        Return the list of comments associated with the specified message.

    create_comment($message_id, $comment)
        Create a new comment, associating it with a specific message.
        Returns a hash containing all of the comment details.

         my $message_id    = 1234;
         my $comment        = "This looks too easy!";
         my $new_comment = $bc->create_comment($message_id, $comment);

    create_message($project_id, $message)
        Creates a new message, optionally sending notifications to a
        selected list of people. The available fields are;

         category_id        - the id of the message category
         title            - message title
         body            - summary text of main message
         extended_body    - the main body of the message
         textile            - optional boolean value. Set to '1' to use Basecamp's 
        textile
                          formatting for your message. Defaults to '0'.
         private            - optional boolean value. Set to '1' to make this message 
                          visible only to the logged in user. Defaults to '0'.
         notify            - optional list of person ids. Each person in this list will 
                          receive an email notification of the message. 

        Returns a hash containing all of the message details.

         my $project_id    = 1234;
         my $message    = {    category_id => 654321, 
                            title => 'New Message Title', 
                            body => 'This text is a summary of the message', 
                            extended_body => 'This is the main body of the message', 
                            textile => 1,    # optional field
                            private => 0,    # optional field
                            notify => qw(1234 5678) # optional field
                            };
         my $data = $bc->create_message($project_id,$message);

    delete_comment($comment_id)
        Delete the comment with the given id.

    delete_message($message_id)
        Delete the specified message from the project.

    message('$message_id, [$message_id2, $message_id3, ...]')
        This will return information about the referenced message. If the id
        is given as a comma-delimited list, one record will be returned for
        each id. In this way you can query a set of messages in a single
        request. Note that you can only give up to 25 ids per request--more
        than that will return an error.

    message_archive($project_id)
        This will return a summary record for each message in a project. If
        you specify a category_id, only messages in that category will be
        returned. (Note that a summary record includes only a few bits of
        information about a post, not the complete record.)

    message_archive_per_category($project_id, $category_id)
        This will return a summary record for each message in a particular
        category. (Note that a summary record includes only a few bits of
        information about a post, not the complete record.)

    update_comment($comment_id, $comment)
        Update a specific comment. This can be used to edit the content of
        an existing comment. Returns a hash containing all of the comment
        details.

         my $comment_id    = 99999;
         my $comment        = "This looks too easy!!";
         my $new_comment = $bc->update_comment($comment_id, $comment);

    update_message($message_id, $message)
        Updates an existing message, optionally sending notifications to a
        selected list of people. Available fields are as per the
        create_message method.

        Returns a hash containing all of the message details.

  To-Do Lists and Items
    complete_item($item_id)
        Marks the specified item as "complete". If the item is already
        completed, this does nothing.

    create_item($list_id, $item_data)
        This call lets you add an item to an existing list. The item is
        added to the bottom of the list. If a person is responsible for the
        item, give their id as the party_id value. If a company is
        responsible, prefix their company id with a 'c' and use that as the
        party_id value. If the item has a person as the responsible party,
        you can use the notify key to indicate whether an email should be
        sent to that person to tell them about the assignment.

         my $list_id        = 4321;
         my $item_data    = { content    => "Turn the lights out",
                            party_id    => 555,
                            notify        => 1 };
         my $new_item = $bc->create_item($list_id, $item_data);

        Returns a hash containing all of the item details.

    create_list($project_id, $list_data)
        This will create a new, empty list. You can create the list
        explicitly, or by giving it a list template id to base the new list
        off of. The available fields are:

         milestone_id    - optional id of an associated milestone
         private        - optional boolean value. Set to '1' to make this list visible
                          only to the logged in user. Defaults to '0'.
         track            - optional boolean value. Set to '1' to enable time tracking on 
                          items in this list. Defaults to '0';

        Basecamp allows you to create list templates for easy creation of
        common task lists. When creating a new list using this method you
        can provide the id of a predefined list template:

         template_id    - id of predefined template

        or pass the name and description for the list:

         name            - list title
         description    - optional description of list

         my $project_id    = 654321;
         my $list_data    = {    milestone_id    => 5436, 
                            private            => 0, 
                            track            => 1,
                            name            => 'Closing up procedures', 
                            };
         my $data = $bc->create_list($project_id,$list_data);

    delete_item($item_id)
        Deletes the specified item, removing it from its parent list.

    delete_list($list_id)
        This call will delete the entire referenced list and all items
        associated with it. Use it with caution, because a deleted list
        cannot be restored!

    delete_list($list_id)
        This will return the metadata and items for a specific list.

    lists($project_id, [$filter], [$key])
        This will return the metadata for all of the lists in a given
        project. You can further constrain the query to only return those
        lists that are "complete" (have no uncompleted items) or
        "uncomplete" (have uncompleted items remaining).

        To receive only complete lists pass $filter = 'true' To receive only
        incomplete lists, pass $filter = 'false' To receive all lists do not
        pass $filter

        Available keys for this method are 'name' and 'id'. (optional)

    move_item($item_id, $position)
        Changes the position of an item within its parent list. It does not
        currently support reparenting an item. Position 1 is at the top of
        the list. Moving an item beyond the end of the list puts it at the
        bottom of the list.

    move_list($list_id, $position)
        This allows you to reposition a list relative to the other lists in
        the project. A list with position 1 will show up at the top of the
        page. Moving lists around lets you prioritize. Moving a list to a
        position less than 1, or more than the number of lists in a project,
        will force the position to be between 1 and the number of lists
        (inclusive).

    move_list($item_id)
        Marks the specified item as "uncomplete". If the item is already
        uncompleted, this does nothing.

    update_item($item_id, $item_data)
        Modifies an existing item. Available fields are as per the
        create_item method.

    update_list($list_id, $list_data)
        Modifies an the metadata for an existing list. Available fields are
        as per the create_list method, with the exclusion of the
        template_id.

  Milestones
    complete_milestone($milestone_id)
        Marks the specified milestone as complete.

    create_milestone($project_id, $milestone_data)
        Creates a single milestone. If a company is responsible, prefix
        their company id with a 'c' and use that as the party_id value. If
        the milestone has a person as the responsible party, you can use the
        notify key to indicate whether an email should be sent to that
        person to tell them about the milestone. The available fields are:

         title        - Title for the milestone
         deadline    - date the milestone is due to be completed. Must be in the format 
                      of YYYYMMDD
         party_id    - id of a person or company responsible for the milestone. If it is 
                      a company, prefix the id with a 'c', e.g. 'c123' 
         notify        - optional boolean value. Set to '1' to send an email about the     
                      milestone to the responsible party.

         my $project_id = 654321
         my $milestone_data = {    title        => 'Launch Party',
                                deadline    => '20060828',
                                party_id    => 555,
                                notify        => 1 };
         my $new_milestone = $bc->create_milestone($project_id, $milestone_data);

        Returns a hash containing all of the milestone details.

    delete_milestone($milestone_id)
        Deletes the given milestone from the project.

    list_milestones($project_id, [$filter])
        This lets you query the list of milestones for a project. You can
        either return all milestones, or only those that are late,
        completed, or upcoming.

        To receive only complete milestones pass $filter = 'complete' To
        receive only upcoming milesones, pass $filter = 'upcoming' To
        receive only late milesones, pass $filter = 'late' To receive all
        milestones do not pass $filter

    uncomplete_milestone($milestone_id)
        Marks the specified milestone as uncomplete.

    update_milestone($milestone_id, $milestone_data)
        Modifies a single milestone. You can use this to shift the deadline
        of a single milestone, and optionally shift the deadlines of
        subsequent milestones as well. The available fields are as per the
        create_milestone() method with the addition of two extra fields:

         move_upcoming    - optional boolean value. Set to '1' to move subsequent         
                          milestone deadlines whne updating the deadline for this 
                          milestone
         move_weekends    - optional boolean value. If using the 'move_upcoming' 
                          parameter, you can set this value to '1' to make sure that any 
                          subsequent milestone deadlines do not get moved to a Saturday 
                          or Sunday.

         my $milestone_id = 98765
         my $milestone_data = {    title            => 'Launch Party',
                                    deadline        => '20061028',
                                    party_id        => 555,
                                    notify            => 1,
                                    move_upcoming    => 1,
                                    move_weekends    => 1 };
         my $new_milestone = $bc->update_milestone($milestone_id, $milestone_data);

        Returns a hash containing all of the milestone details.

  Time Tracking
    create_time($data)
        With this method you can create a new time entry for a particular
        person and project. The available fields are:

         project_id    - id for the project associated with the task
         person_id    - id of the person who completed the work
         date        - date the work took place. Date format = YYYYMMDD, e.g. 20060801 
         hours        - time worked, in hours

        If the task being time tracked is an existing item from a to do
        list, you can pass the item_id:

         item_id        - id of an existing to do list item

        or you can provide a description of the task

         description    - txt description of the task

         my $project_id    = 654321;
         my $person_id    = 555;
         my $data = {    project_id    => $project_id,
                        person_id    => $person_id,
                        date        => '20060801',
                        hours        => '1.25',
                        description    => 'Meeting with world leaders' };
         my $new_time = $bc->create_time($data);

    delete_time($project_id, $time_id)
        Deletes the identified time entry.

    report_time($person_id, $from, $to, [$filter])
        This method lets you query the time entries in a variety of ways. If
        you do not want to query by $person_id, put a 0 in that position.
        Likewise for $from and $to (to use default from/to values). In no
        case can you query more than 90 days' worth of data. The $filter
        parameter can be blank, or an id number prefixed by a 'p' (to filter
        by a specific project) or 'c' (to filter by a specific company).

         my $report = $bc->report_time(5,'20060101','20060207','c7');
    
         Would return all time entries for the person with id 5, for all projects 
        associated with the company with id 7, between the dates 2006-01-01 and 
        2006-02-07 (inclusive).

        Date values passed for $from and $to must be in the format of
        YYYYMMDD

    update_time($time_id, $data)
        With this method you can modify a specific time entry. The available
        fields are as per the create_time() method.

  Contact Management
    companies()
        Returns a list of all companies visible to the given person. This is
        only accessible to employees of the "firm" (the company assoicated
        with the account). Client employees will get a 403 response if they
        attempt to access this method.

    company($company_id)
        This will return the information for the referenced company.

    people($company_id)
        This will return all of the people in the given company.

    people_per_project($project_id, $company_id)
        This will return all of the people in the given company that can
        access the given project.

    person($person_id)
        This will return information about the referenced person.

TODO
    This module does not currently support all of the Basecamp API
    functions. In particular, the following methods need to be added:

    *   File uploads

    *   Attaching files to messages

    *   batch creation of milestones

    Add more tests

BUGS
    This is alpha software and as such, the features and interface are
    subject to change. So please check the Changes file when upgrading.

SEE ALSO
    <http://www.basecamphq.com/api>, XML::Simple

AUTHOR
    David Baxter <david@sitesuite.com.au>

CREDITS
    Thanks to SiteSuite (http://www.sitesuite.com.au) for funding the
    development of this plugin and for releasing it to the world.

LICENCE AND COPYRIGHT
    Copyright (c) 2006, SiteSuite. All rights reserved.

    This module is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

DISCLAIMER OF WARRANTY
    BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
    PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
    YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
    NECESSARY SERVICING, REPAIR, OR CORRECTION.

    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
    REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
    TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
    CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
    SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
    RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
    FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
    SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    DAMAGES.

