[Jifty-commit] r4488 - in apps/spensive: . etc lib/Spensive lib/Spensive/Action lib/Spensive/Model lib/Spensive/View

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Tue Nov 20 12:11:13 EST 2007


Author: jesse
Date: Tue Nov 20 12:11:12 2007
New Revision: 4488

Modified:
   apps/spensive/   (props changed)
   apps/spensive/etc/config.yml
   apps/spensive/lib/Spensive/Action/EmailDispatch.pm
   apps/spensive/lib/Spensive/Model/Expense.pm
   apps/spensive/lib/Spensive/Model/User.pm
   apps/spensive/lib/Spensive/View.pm
   apps/spensive/lib/Spensive/View/Expenses.pm
   apps/spensive/share/web/static/css/app.css

Log:
 r67465 at pinglin (orig r7375):  jesse | 2007-09-20 18:13:56 -0400
 * working on emailing to expenses, deleteing expense emails


Modified: apps/spensive/etc/config.yml
==============================================================================
--- apps/spensive/etc/config.yml	(original)
+++ apps/spensive/etc/config.yml	Tue Nov 20 12:11:12 2007
@@ -13,7 +13,7 @@
     Password: ''
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
-    Version: 0.0.5
+    Version: 0.0.9
   DevelMode: 0
   L10N: 
     PoDir: share/po

Modified: apps/spensive/lib/Spensive/Action/EmailDispatch.pm
==============================================================================
--- apps/spensive/lib/Spensive/Action/EmailDispatch.pm	(original)
+++ apps/spensive/lib/Spensive/Action/EmailDispatch.pm	Tue Nov 20 12:11:12 2007
@@ -80,16 +80,40 @@
 
     # See if this is a published address
     my $address = $self->argument_value('address');
-    my $pa      = Jifty->app_class('Model', 'User')->new( current_user => Jifty->app_class('CurrentUser')->superuser );
-    $pa->load_by_cols( published_address => $address );
+            my $summary = $email->header("Subject");
 
     my $action;
-    if ( $pa->id ) { 
+
+    if ($address =~ /^expense-(.*?)(\d+)/) {
+        my $key = $1;
+        my $id = $2;
+        my $pa      = Jifty->app_class('Model', 'Expense')->new( current_user => Jifty->app_class('CurrentUser')->superuser );
+        $pa->load_by_cols( published_address => $key );
+    if ( $pa->id && $pa->id == $id) { 
+
+            $action = Jifty->web->new_action(
+                class     => 'CreateEmail',
+                moniker   => "email_dispatch",
+                arguments => {
+                    expense => $pa->id,
+                    message => $self->argument_value('email'),
+                },
+            );
+        }
+
+    } 
+    elsif ($address =~ /^(.*?)(\d+)/) {
+        my $key = $1;
+        my $id = $2;
+    my $pa      = Jifty->app_class('Model', 'User')->new( current_user => Jifty->app_class('CurrentUser')->superuser );
+    $pa->load_by_cols( published_address => $key );
+
+    # if we have a user's expense creating address
+    if ( $pa->id && $pa->id == $id) { 
         # We got a user
             # if a user set up auto_attributes we need to parse
             # for braindump syntax.  Put them first so that if
             # auto_attributes contains [due] a [due] in Subject will clobber
-            my $summary = $email->header("Subject");
 
             $action = Jifty->web->new_action(
                 class     => 'CreateExpense',
@@ -100,12 +124,9 @@
                     incurred_by => $pa->id,
                     email_content => $self->argument_value('email'),
                 },
-                # We clobber the current_user for group tasks so
-                # anyone can create group tasks, which is not usually
-                # the case
-                current_user => $pa
             );
         }
+    }
     if($action) {
         $action->run;
         if($action->result->failure) {

Modified: apps/spensive/lib/Spensive/Model/Expense.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/Expense.pm	(original)
+++ apps/spensive/lib/Spensive/Model/Expense.pm	Tue Nov 20 12:11:12 2007
@@ -4,17 +4,18 @@
 package Spensive::Model::Expense;
 use Jifty::DBI::Schema;
 
+our $PWGEN =   Text::Password::Pronounceable->new(6=>8);
 use Spensive::Record schema {
     
     column title => type is 'text';
     column description => type is 'text', render as 'Textarea';
-    column date_incurred => type is 'datetime', default is defer { Jifty::DateTime->now }, render_as 'Date';;
+    column date_incurred => type is 'datetime', default is defer { Jifty::DateTime->now }, render_as 'Date', filters are qw(Jifty::DBI::Filter::Date);;
     column incurred_by =>  references Spensive::Model::User;
     column tags => type is 'text';
     column local_cost => type is 'float';
     column cost => type is 'float';
     column category => type is 'text', valid_values are qw(airfare hotel travel communication meals entertainment other), since '0.0.5';
-
+    column published_address => type is 'varchar(32)', is immutable, since is '0.0.9';
     column payment_currency => type is 'text', valid_values are qw(USD CAD UKP EUR TWD NZD HKD), default is 'USD';
     #column payment_method => type is 'text', valid_values are qw(personal_credit corporate_credit cash);
     column expense_report=> references Spensive::Model::ExpenseReport;
@@ -26,12 +27,15 @@
     my $self = shift;
     my $args = shift;
 
+    $args->{'published_address'} = $PWGEN->generate;
     $args->{'incurred_by'} = $self->current_user->id;
     $args->{'date_incurred'} ||= Jifty::DateTime->now;
     $self->{'_email_content'} = delete $args->{'email_content'};
     return 1;
 }
 
+sub published_address {my $self = shift; return $self->_value('published_address').$self->id."@".Jifty->config->app('EmailDomain') };
+
 sub after_create {
     my $self = shift;
       my $insert_return_value_ref = shift;
@@ -71,6 +75,16 @@
     return @results;
 }
 
+sub attachments {
+    my $self = shift; 
+    my $collateral = Spensive::Model::EmailAttachmentCollection->new();
+    $collateral->limit(alias => '', column=>'length(main.content)', operator => '>', value => '0', quote_value => 0);
+    my $email_alias = $collateral->join( alias1 => 'main', column1 => 'email', table2 => 'emails', column2 => 'id');
+
+    my $expenses =$collateral->join(alias1 => $email_alias, column1 => 'expense', table2 => 'expenses', column2 => 'id');
+    $collateral->limit(alias => $expenses, column => 'id', value => $self->id);
+    return $collateral;
+}
 
 1;
 

Modified: apps/spensive/lib/Spensive/Model/User.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/User.pm	(original)
+++ apps/spensive/lib/Spensive/Model/User.pm	Tue Nov 20 12:11:12 2007
@@ -14,10 +14,10 @@
 };
 
 
-our $PWGEN =   Text::Password::Pronounceable->new(4=>6);
+our $PWGEN =   Text::Password::Pronounceable->new(6=>8);
 
 
-sub published_address { return shift->_value('published_address')."@".Jifty->config->app('EmailDomain') };
+sub published_address { return shift->_value('published_address').shift->id."@".Jifty->config->app('EmailDomain') };
 
 sub before_create {
     my $self = shift;

Modified: apps/spensive/lib/Spensive/View.pm
==============================================================================
--- apps/spensive/lib/Spensive/View.pm	(original)
+++ apps/spensive/lib/Spensive/View.pm	Tue Nov 20 12:11:12 2007
@@ -1,5 +1,6 @@
 use warnings;
 use strict;
+
 package Spensive::View;
 use Jifty::View::Declare -base;
 
@@ -10,46 +11,57 @@
     h1 { _('Spensive helps you keep track of your business expenses') };
     h2 { _('(It also helps you get reimbursed for them)') };
 
-    h3 { _('Unsubmitted expenses') };
-    form {
+    h3   { _('Unsubmitted expenses') };
         my $search = Spensive::Model::ExpenseCollection->new();
-        $search->limit( column => 'expense_report', value => 'null', operator => 'is',  quote_value => 0);
-        $search->limit( column => 'incurred_by', value  => Jifty->web->current_user->id);
-        set (search_collection =>  $search);
+        $search->limit(
+            column      => 'expense_report',
+            value       => 'null',
+            operator    => 'is',
+            quote_value => 0
+        );
+        $search->limit(
+            column => 'incurred_by',
+            value  => Jifty->web->current_user->id
+        );
+        set( search_collection => $search );
         render_region(
-            name => 'expenses',
-            path => '/expenses/list',
-            defaults =>
-                { page => 1, id => 'xxx' }
+            name     => 'expenses',
+            path     => '/expenses/list',
+            defaults => { page => 1, id => 'xxx' }
 
         );
+    span {
+        { class is 'hint' };
+        hyperlink( label => 'All my expenses...', path => '/expenses/all' );
     };
-    span { {class is 'hint'}; hyperlink(label => 'All my expenses...', path => '/expenses/all') };
 };
 
+sub show_open_expense_reports {
 
-    sub show_open_expense_reports { 
-
-    h3 { _('Open expense reports')};
+    h3   { _('Open expense reports') };
     form {
         my $search = Spensive::Model::ExpenseReportCollection->new();
         $search->limit(
             column => 'submitted_by',
             value  => Jifty->web->current_user->id
         );
-        set (search_collection =>  $search);
+        set( search_collection => $search );
         render_region(
-            name => 'reports',
-            path => '/reports/list',
-            defaults =>
-                { page => 1, id => 'xxx' }
+            name     => 'reports',
+            path     => '/reports/list',
+            defaults => { page => 1, id => 'xxx' }
 
         );
     };
-    span { {class is 'hint'}; hyperlink(label => 'All my expense reports...', path => '/reports/all') };
+    span {
+        { class is 'hint' };
+        hyperlink(
+            label => 'All my expense reports...',
+            path  => '/reports/all'
+        );
+    };
 }
 
-
 require Spensive::View::Expenses;
 alias Spensive::View::Expenses under 'expenses/';
 
@@ -59,67 +71,114 @@
 require Spensive::View::Prefs;
 alias Spensive::View::Prefs under './prefs';
 
-
 use Jifty::Plugin::TabView::View;
 
-
 template 'report/show' => page {
     my $report = get('report');
-    h1 { $report->title };
+    h1 { 'Expense Report: ' . $report->title };
 
     my %category_totals = ();
-    my %category_items = ();
-    foreach my $cat ( $report->categories ) {
-        my $expenses = $report->expenses( category => $cat );
-        div { { class is 'expense-category'};
-        h2 {$cat};
-
-        while ( my $expense = $expenses->next ) {
-            div  { { class is 'expense-entry'};
-            for (qw(date_incurred title description cost)) {
-                span { {class is 'expense-'.$_};  $expense->$_() };
-            }
-            };
-            $category_totals{$cat} += $expense->cost;
-            push @{$category_items{$cat}},$expense;
-        }
+    my %category_items  = ();
+    my %appendices = ();
+    my $expenses        = $report->expenses();
+    my ( $earliest, $latest );
+    my $appendix_counter++;
+    warn $expenses->count;
+
+    map {
+        $earliest = $_->date_incurred
+            if ( !$earliest || $_->date_incurred < $earliest );
+        $latest = $_->date_incurred
+            if ( !$latest || $_->date_incurred > $latest )
 
-        if ($category_items{$cat}->[0]) {
+    } @{ $expenses->items_array_ref };
 
+    div {
+        { id is 'report-date-range' };
+        outs(_('%1 to %2', $earliest, $latest));
 
-        div {
-            { class is 'subtotal' };
-            span { { class is 'label' }; _('Subtotal: '); };
-            outs( $category_totals{$cat});
-
-            };
-        } else {
-        div { {class is 'subtotal-empty'};
-            outs("Nothing to report"); 
+    };
+    table {
+        foreach my $cat ( $report->categories ) {
+            my $expenses = $report->expenses( category => $cat );
+            div {
+                { class is 'expense-category' };
+                row {
+                    th { {colspan is '3' };
+                    h2 {$cat};
+                    }
+                }
+                }
+                my $expense;
+            foreach $expense ( grep { $_->category eq $cat }
+                @{ $expenses->items_array_ref } )
+            {
+                row {
+                    { class is 'expense-entry' };
+                    for (qw(date_incurred title cost)) {
+                        cell {
+                            { class is 'expense-' . $_ };
+                            $expense->$_();
+                        };
+                    };
+                    if ($expense->attachments->count) {
+                        $appendices{$expense->id} = $appendix_counter++;
+                        cell { 'For attachments, see appendix '.$appendices{$expense->id}};
+                    }
+                };
+                row { 
+                    cell {
+                        { class is 'expense-description'; colspan is '3'; };
+                        $expense->description();
+                    };
+                };
+                $category_totals{$cat} += $expense->cost;
+                push @{ $category_items{$cat} }, $expense;
+            }
+
+            if ( $category_items{$cat}->[0] ) {
+
+                row { { class is 'subtotal' };
+                    th { { colspan is '3' };
+                        span { { class is 'label' }; _('Subtotal: '); };
+                        outs( $category_totals{$cat} );
+                    };
+
+                };
+            } else {
+                row {
+                    cell {
+                        {
+                            { class is 'subtotal-empty' };
+                            outs("Nothing to report");
+                        }
+                        }
+                    }
+            }
         }
-    }
-    }
-}
-    div {
-        h2 { 'Totals' };
+        }
+        div {
+        h2 {'Totals'};
 
         { class is 'total' };
         span {
             { class is 'label' };
             _('Total');
         };
-        outs( List::Util::sum (values %category_totals) );
-    };
-
+        outs( List::Util::sum( values %category_totals ) );
+        };
 };
 
-
 template 'report/build' => page {
-           my $self = shift;
+    my $self = shift;
     h1 { get('report')->title };
-           render_region( name => 'reports', path => 'report_tabs', defaults => { report => get('report')->id});
-                  
-        outs_raw(Jifty->web->return(label => 'Done'));      
+    render_region(
+        name     => 'reports',
+        path     => 'report_tabs',
+        defaults => { report => get('report')->id }
+    );
+
+    outs_raw( Jifty->web->return( label => 'Done' ) );
 };
 
 template report_tabs => sub {
@@ -127,103 +186,183 @@
     $self->render_tabs(
         'reports',
         [qw(report)],
-        { label => 'Add expenses', path => '/attach_reports' ,
-        defer => 1
-    },
+        {   label => 'Attach expenses',
+            path  => '/attach_reports',
+            defer => 1
+        },
         {   label => 'Remove expenses',
             path  => '/remove_reports',
             defer => 1,
+        },
+        {   label => 'Add expenses',
+            path  => '/add_report',
+            defer => 1,
         }
     );
 
     #        qw(/attach_reports_tab /remove_reports_tab ) );
 };
 
+
+template 'add_report' => sub {
+    my $report_id = get('report');
+    my $report    = Spensive::Model::ExpenseReport->new();
+    $report->load($report_id);
+
+    h2 { _('Add a new expense'); };
+    render_region(
+        name     => 'expense-new',
+        path     => 'report/new_expense',
+        defaults => { report => $report->id }
+    );
+
+
+};
+
 template 'attach_reports' => sub {
     my $report_id = get('report');
-    my $report = Spensive::Model::ExpenseReport->new();
+    my $report    = Spensive::Model::ExpenseReport->new();
     $report->load($report_id);
     h2 { _('add some stuff') };
-    
+
     my $untied = Spensive::Model::ExpenseCollection->new();
-    $untied->limit( 
-                    column => 'incurred_by',
-                                value  => Jifty->web->current_user->id
+    $untied->limit(
+        column => 'incurred_by',
+        value  => Jifty->web->current_user->id
 
     );
-    $untied->limit( column => 'expense_report', operator => 'is', value => 'null', entryaggregator => 'or');
-    $untied->limit( column => 'expense_report', operator => '=', value => '');
+    $untied->limit(
+        column          => 'expense_report',
+        operator        => 'is',
+        value           => 'null',
+        entryaggregator => 'or'
+    );
+    $untied->limit(
+        column   => 'expense_report',
+        operator => '=',
+        value    => ''
+    );
 
-    h3 { 'Open expenses'};
+    h3 {'Open expenses'};
 
-       while (my $item = $untied->next) {
-        render_region (name => 'expense-'.$item->id, path => 'report/add_expense', defaults => { id => $item->id, report => $report->id});
+    while ( my $item = $untied->next ) {
+        render_region(
+            name     => 'expense-' . $item->id,
+            path     => 'report/add_expense',
+            defaults => { id => $item->id, report => $report->id }
+        );
 
-}
+    }
 
-    h3 { 'A new expense' };
-        render_region (name => 'expense-new', path => 'report/new_expense', defaults => { report => $report->id});
 };
 template 'remove_reports' => sub {
     my $report_id = get('report');
-    my $report = Spensive::Model::ExpenseReport->new();
+    my $report    = Spensive::Model::ExpenseReport->new();
     $report->load($report_id);
     h2 { _('remove some stuff') };
-    
+
     my $untied = Spensive::Model::ExpenseCollection->new();
-    $untied->limit( column => 'incurred_by', value  => Jifty->web->current_user->id );
-    $untied->limit( column => 'expense_report', operator => '=', value => $report->id);
-       while (my $item = $untied->next) {
-        render_region (name => 'expense-'.$item->id,
-                        path => 'report/remove_expense',
-                            defaults => { id => $item->id, report => $report->id});
-}
+    $untied->limit(
+        column => 'incurred_by',
+        value  => Jifty->web->current_user->id
+    );
+    $untied->limit(
+        column   => 'expense_report',
+        operator => '=',
+        value    => $report->id
+    );
+    while ( my $item = $untied->next ) {
+        render_region(
+            name     => 'expense-' . $item->id,
+            path     => 'report/remove_expense',
+            defaults => { id => $item->id, report => $report->id }
+        );
+    }
 };
 
-
-
 template 'report/new_expense' => sub {
     my $report = get('report');
-    my $action = Jifty->web->new_action( class    => 'CreateExpense', arguments => {expense_report => $report});
+    my $action = Jifty->web->new_action(
+        class     => 'CreateExpense',
+        arguments => { expense_report => $report, incurred_by => Jifty->web->current_user->id }
+    );
     form {
-        render_action($action);
-    outs_raw($action->button( label => 'Add', onclick=> [{submit => $action, }, { refresh_self => 1}]));
-    }
+        for (qw(title cost date_incurred description)) {
+            render_param($action => $_);
+        }
+        for (qw(incurred_by expense_report)) {
+            render_param($action => $_, 
+            render_as     => 'Hidden');
+        }
+        outs_raw(
+            $action->button(
+                label   => 'Add',
+                onclick => [ { submit => $action, }, { refresh_self => 1 } ]
+            )
+        );
+        }
 };
 
-
 template 'report/add_expense' => sub {
     my $report = get('report');
     my $item   = Spensive::Model::Expense->new();
     $item->load( get 'id' );
-    my $action = Jifty->web->new_action( class    => 'UpdateExpense', record   => $item,);
+    my $action
+        = Jifty->web->new_action( class => 'UpdateExpense', record => $item,
+        );
     h3 { $item->title, ' - ', $item->cost, " - ", };
     form {
-        render_param($action => 'expense_report', render_as=>'Hidden', default_value => $report);
-    outs_raw($action->button( label => 'Add', onclick=> [{submit => $action, }, { delete => Jifty->web->current_region}] ));
-    }
+        render_param(
+            $action       => 'expense_report',
+            render_as     => 'Hidden',
+            default_value => $report
+        );
+        outs_raw(
+            $action->button(
+                label   => 'Add',
+                onclick => [
+                    { submit => $action, },
+                    { delete => Jifty->web->current_region }
+                ]
+            )
+        );
+        }
 };
 
 template 'report/remove_expense' => sub {
     my $report = get('report');
     my $item   = Spensive::Model::Expense->new();
     $item->load( get 'id' );
-    my $action = Jifty->web->new_action( class    => 'UpdateExpense', record   => $item,);
+    my $action
+        = Jifty->web->new_action( class => 'UpdateExpense', record => $item,
+        );
     h3 { $item->title, ' - ', $item->cost, " - ", };
     form {
-        render_param($action => 'expense_report', render_as=>'Hidden', default_value => undef);
-    outs_raw($action->button( label => 'Remove', onclick=> [{submit => $action, }, { delete => Jifty->web->current_region}] ));
-}
+        render_param(
+            $action       => 'expense_report',
+            render_as     => 'Hidden',
+            default_value => undef
+        );
+        outs_raw(
+            $action->button(
+                label   => 'Remove',
+                onclick => [
+                    { submit => $action, },
+                    { delete => Jifty->web->current_region }
+                ]
+            )
+        );
+        }
 };
 
 template 'attachment/image' => sub {
     my $item = get('attachment');
-     Jifty->handler->apache->content_type($item->content_type);
-    outs_raw($item->content);
+    Jifty->handler->apache->content_type( $item->content_type );
+    outs_raw( $item->content );
 
 };
 
-
-private template app_page_footer => sub { show '/feedback/request_feedback'; };
+private template app_page_footer =>
+    sub { show '/feedback/request_feedback'; };
 
 1;

Modified: apps/spensive/lib/Spensive/View/Expenses.pm
==============================================================================
--- apps/spensive/lib/Spensive/View/Expenses.pm	(original)
+++ apps/spensive/lib/Spensive/View/Expenses.pm	Tue Nov 20 12:11:12 2007
@@ -16,31 +16,62 @@
 private template view_item_controls => sub {
     my $self =shift;
     my $item=shift;
+    div { { class is 'controls'};
     tangent(url => '/expense/'.$item->id, label => 'Details');
 };
+};
 
 
 template show_details => page {
     my $expense = get('expense');
 
-    my $collateral = Spensive::Model::EmailAttachmentCollection->new();
-    my $email_alias = $collateral->join( alias1 => 'main', column1 => 'email', table2 => 'emails', column2 => 'id');
-
-    my $expenses =$collateral->join(alias1 => $email_alias, column1 => 'expense', table2 => 'expenses', column2 => 'id');
-    $collateral->limit(alias => $expenses, column => 'id', value => $expense->id);
-
+    my $collateral = $expense->attachments;
+    my $action = Jifty->web->new_action( class => 'UpdateExpense', record => $expense);
     h1 { $expense->title};
-    h2 { $expense->description};
-    div { {class is 'cost'}; $expense->cost};
+
+    div { { class is 'hint'};
+        outs_raw(_('You can email new receipts to this expense by sending to %1'. a{ {href is 'mailto:'.$expense->published_address;} $expense->published_address}));
+    };
+
+    render_action($action);
+    form_submit($action);
+    h2 { 'Attachments'};
 
     while (my $item = $collateral->next) {
     
+        render_region(
+            name     => 'attach-' . $item->id,
+            path     => '/expenses/one_attachment',
+            defaults => { id => $item->id}
+        );
+
+
+
+    }
+};
+
+template one_attachment => sub {
+    my  $id = get('id');
+    my $item = Spensive::Model::EmailAttachment->new();
+    $item->load($id);
         if ($item->content_type =~ /^image/i) {
-            img { { src is '/attachment/view/'.$item->id} };
+            a { {href is '/attachment/view/'.$item->id; target is '_new'};
+                img { { class is 'inline-image'; src is '/attachment/view/'.$item->id} };
+            };
         } elsif ($item->content_type eq 'text/plain' || $item->content eq 'message/rfc822' ) {
             div { $item->content };
         }
-    }
-};
 
+        my $del = Jifty->web->new_action(class => 'DeleteEmailAttachment', record => $item);
+        outs_raw(
+            $del->button(
+                label   => 'Delete',
+                onclick => [
+         {confirm => "We aren't going to save a backup copy. If you delete this, it's forever! Are you sure?",
+                     submit => $del, 
+                     delete => Jifty->web->current_region }
+                ]
+            )
+        );
+    };
 1;

Modified: apps/spensive/share/web/static/css/app.css
==============================================================================
--- apps/spensive/share/web/static/css/app.css	(original)
+++ apps/spensive/share/web/static/css/app.css	Tue Nov 20 12:11:12 2007
@@ -41,4 +41,10 @@
  font-size: 1em;
  font-family:  arial, sans-serif; 
 width: 17em;
-}
\ No newline at end of file
+
+}
+
+img.inline-image {
+    max-width: 250px;
+
+}


More information about the Jifty-commit mailing list