[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