[freeside-commits] branch master updated. 7e5098563f4fec41ccff6c0907fc1558a5a61597

Ivan ivan at 420.am
Tue Jun 11 00:34:25 PDT 2013


The branch, master has been updated
       via  7e5098563f4fec41ccff6c0907fc1558a5a61597 (commit)
       via  a094dcf3aa925ae4c7d22f3f6c93c2ecdd513d41 (commit)
       via  91893b441b4281d0384dbb783e67383d0ea5ead2 (commit)
       via  b7a2175dd9b386441f4ab66869d73083e5e8beb1 (commit)
      from  e497261817ee2cf3acb5ee3dda3c5906f1c13a4f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7e5098563f4fec41ccff6c0907fc1558a5a61597
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Jun 11 00:34:19 2013 -0700

    multi-currency, RT#21565

diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index f3122aa..18ad9e3 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -58,6 +58,7 @@ use FS::cust_main_exemption;
 use FS::cust_tax_adjustment;
 use FS::cust_tax_location;
 use FS::agent;
+use FS::agent_currency;
 use FS::cust_main_invoice;
 use FS::cust_tag;
 use FS::prepay_credit;
@@ -1771,8 +1772,17 @@ sub check {
     if $error =~ /^Illegal or empty \(numeric\) refnum: /;
   return $error if $error;
 
-  return "Unknown agent"
-    unless qsearchs( 'agent', { 'agentnum' => $self->agentnum } );
+  my $agent = qsearchs( 'agent', { 'agentnum' => $self->agentnum } )
+    or return "Unknown agent";
+
+  if ( $self->currency ) {
+    my $agent_currency = qsearchs( 'agent_currency', {
+      'agentnum' => $agent->agentnum,
+      'currency' => $self->currency,
+    })
+      or return "Agent ". $agent->agent.
+                " not permitted to offer ".  $self->currency. " invoicing";
+  }
 
   return "Unknown refnum"
     unless qsearchs( 'part_referral', { 'refnum' => $self->refnum } );

commit a094dcf3aa925ae4c7d22f3f6c93c2ecdd513d41
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Jun 11 00:24:09 2013 -0700

    multi-currency, RT#21565

diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index ef9bc22..89f1615 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -1,331 +1,330 @@
-<% include( 'elements/edit.html',
-              'post_url'              => popurl(1).'process/part_pkg.cgi',
-              'name'                  => "Package definition",
-              'table'                 => 'part_pkg',
-
-              'agent_virt'            => 1,
-              'agent_null_right'      => $edit_global,
-              'agent_clone_extra_sql' => $agent_clone_extra_sql,
-              #'viewall_dir'           => 'browse',
-              'viewall_url'           => $p.'browse/part_pkg.cgi',
-              'html_init'             => include('/elements/init_overlib.html').
-                                         $javascript,
-              'html_bottom'           => $html_bottom,
-              'body_etc'              =>
-                'onLoad="agent_changed(document.edit_topform.agentnum)"',
-
-              'begin_callback'        => $begin_callback,
-              'end_callback'          => $end_callback,
-              'new_hashref_callback'  => $new_hashref_callback,
-              'new_object_callback'   => $new_object_callback,
-              'new_callback'          => $new_callback,
-              'clone_callback'        => $clone_callback,
-              'edit_callback'         => $edit_callback,
-              'error_callback'        => $error_callback,
-              'field_callback'        => $field_callback,
-
-              'onsubmit'              => 'confirm_submit',
-
-              'labels' => { 
-                            'pkgpart'          => 'Package Definition',
-                            'pkg'              => 'Package',
-                            %locale_field_labels,
-                            'comment'          => 'Comment (customer-hidden)',
-                            'classnum'         => 'Package class',
-                            'addon_classnum'   => 'Restrict additional orders to package class',
-                            'promo_code'       => 'Promotional code',
-                            'freq'             => 'Recurring fee frequency',
-                            'setuptax'         => 'Setup fee tax exempt',
-                            'recurtax'         => 'Recurring fee tax exempt',
-                            'taxclass'         => 'Tax class',
-                            'taxproduct_select'=> 'Tax products',
-                            'plan'             => 'Price plan',
-                            'disabled'         => 'Disable new orders',
-                            'disable_line_item_date_ranges' => 'Disable line item date ranges',
-                            'setup_cost'       => 'Setup cost',
-                            'recur_cost'       => 'Recur cost',
-                            'pay_weight'       => 'Payment weight',
-                            'credit_weight'    => 'Credit weight',
-                            'agentnum'         => 'Agent',
-                            'setup_fee'        => 'Setup fee',
-                            'setup_show_zero'  => 'Show zero setup',
-                            'recur_fee'        => 'Recurring fee',
-                            'recur_show_zero'  => 'Show zero recurring',
-                            ( map { ( "setup_fee_$_" => "Setup fee $_",
-                                      "recur_fee_$_" => "Recurring fee $_",
-                                    );
-                                  }
-                                $conf->config('currencies')
-                            ),
-                            'discountnum'      => 'Offer discounts for longer terms',
-                            'bill_dst_pkgpart' => 'Include line item(s) from package',
-                            'svc_dst_pkgpart'  => 'Include services of package',
-                            'supp_dst_pkgpart' => 'Include complete package',
-                            'report_option'    => 'Report classes',
-                            'fcc_ds0s'         => 'Voice-grade equivalents',
-                            'fcc_voip_class'   => 'Category',
-                          },
-
-              'fields' => [
-                            { field=>'clone',  type=>'hidden',
-                              curr_value_callback =>
-                                sub { shift->param('clone') },
-                            },
-                            { field=>'pkgnum', type=>'hidden',
-                              curr_value_callback =>
-                                sub { shift->param('pkgnum') },
-                            },
-
-                            { field=>'custom',  type=>'hidden' },
-                            { field=>'family_pkgpart', type=>'hidden' },
-                            { field=>'successor', type=>'hidden' },
-
-                            { type => 'columnstart' },
-                            
-                              { field     => 'pkg',
-                                type      => 'text',
-                                size      => 40, #32
-                                maxlength => 50,
-                              },
-                              #@locale_fields,
-                              {field=>'comment',  type=>'text', size=>40 }, #32
-                              { field         => 'agentnum',
-                                type          => 'select-agent',
-                                disable_empty => ! $acl_edit_global,
-                                empty_label   => '(global)',
-                                onchange      => 'agent_changed',
-                              },
-                              {field=>'classnum', type=>'select-pkg_class' },
-                              ( $conf->exists('pkg-addon_classnum')
-                                  ? ( { field=>'addon_classnum',
-                                        type =>'select-pkg_class',
-                                      }
-                                    )
-                                   : ()
-                              ),
-                              {field=>'disabled', type=>$disabled_type, value=>'Y'},
-                              {field=>'disable_line_item_date_ranges', type=>$disabled_type, value=>'Y'},
-
-                              { type     => 'tablebreak-tr-title',
-                                value    => 'Pricing', #better name?
-                              },
-                              { field    => 'plan',
-                                type     => 'selectlayers-select',
-                                options  => [ keys %plan_labels ],
-                                labels   => \%plan_labels,
-                                onchange => 'aux_planchanged(what);',
-                              },
-                              { field    => 'setup_fee',
-                                type     => 'money',
-                                onchange => 'setup_changed',
-                              },
-                              { field    => 'setup_show_zero',
-                                type     => 'checkbox',
-                                value    => 'Y',
-                                disabled => sub { $setup_show_zero_disabled },
-                              },
-                              ( map { +{ field => "setup_fee_$_",
-                                         type  => 'text',
-                                         prefix=> currency_symbol($_, SYM_HTML),
-                                         size  => 8,
-                                       }
-                                    }
-                                  sort $conf->config('currencies')
-                              ),
-                              { field    => 'freq',
-                                type     => 'part_pkg_freq',
-                                onchange => 'freq_changed',
-                              },
-                              { field    => 'recur_fee',
-                                type     => 'money',
-                                disabled => sub { $recur_disabled },
-                                onchange => 'recur_changed',
-                              },
-                              { field    => 'recur_show_zero',
-                                type     => 'checkbox',
-                                value    => 'Y',
-                                disabled => sub { $recur_show_zero_disabled },
-                              },
-                              ( map { +{ field => "recur_fee_$_",
-                                         type  => 'text',
-                                         prefix=> currency_symbol($_, SYM_HTML),
-                                         size  => 8,
-                                       }
-                                    }
-                                  sort $conf->config('currencies')
-                              ),
-
-                              #price plan
-                              #setup fee
-                              #recurring frequency
-                              #recurring fee (auto-disable)
-
-                            { type => 'columnnext' },
-
-                              {type=>'justtitle', value=>'Taxation' },
-                              {field=>'setuptax', type=>'checkbox', value=>'Y'},
-                              {field=>'recurtax', type=>'checkbox', value=>'Y'},
-                              {field=>'taxclass', type=>'select-taxclass' },
-                              { field => 'taxproductnums',
-                                type  => 'hidden',
-                                value => join(',', @taxproductnums),
-                              },
-                              { field => 'taxproduct_select',
-                                type  => 'selectlayers',
-                                options => [ '(default)', @taxproductnums ],
-                                curr_value => '(default)',
-                                labels  => { ( '(default)' => '(default)' ),
-                                             map {($_=>$usage_class{$_})}
-                                             @taxproductnums
-                                           },
-                                layer_fields => \%taxproduct_fields,
-                                layer_values_callback => $taxproduct_values,
-                                layers_only  =>   !$taxproducts,
-                                cell_style   => ( !$taxproducts
-                                                  ? 'display:none'
-                                                  : ''
-                                                ),
-                              },
-
-                              { type  => 'tablebreak-tr-title',
-                                value => 'Promotions', #better name?
-                              },
-                              { field=>'promo_code', type=>'text', size=>15 },
-
-                              { type  => 'tablebreak-tr-title',
-                                value => 'Cost tracking', #better name?
-                              },
-                              { field=>'setup_cost', type=>'money', },
-                              { field=>'recur_cost', type=>'money', },
-
-                            { type => 'columnnext' },
-
-                              { field    => 'agent_type',
-                                type     => 'select-agent_types',
-                                disabled => ! $acl_edit_global,
-                                curr_value_callback => sub {
-                                  my($cgi, $object, $field) = @_;
-                                  #in the other callbacks..?  hmm.
-                                  \@agent_type;
-                                },
-                              },
-
-                              { type  => 'tablebreak-tr-title',
-                                value => 'Line-item revenue recogition', #better name?
-                              },
-                              { field=>'pay_weight',    type=>'text', size=>6 },
-                              { field=>'credit_weight', type=>'text', size=>6 },
-
-                              ( $conf->exists('cust_pkg-show_fcc_voice_grade_equivalent')
-                                ? ( 
-                                    { type  => 'tablebreak-tr-title',
-                                      value => 'FCC Form 477 information',
-                                    },
-                                    { field=>'fcc_voip_class',
-                                      type=>'select-voip_class',
-                                    },
-                                    { field=>'fcc_ds0s', type=>'text', size=>6 },
-                                  )
-                                 : ()
-                              ),
-
-
-                            { type => 'columnend' },
-
-                            { 'type'  => $report_option ? 'tablebreak-tr-title'
-                                                        : 'hidden',
-                              'value' => 'Optional report classes',
-                              'field' => 'census_title',
-                            },
-                            { 'field'    => 'report_option',
-                              'type'     => $report_option ? 'select-table'
-                                                           : 'hidden',
-                              'table'    => 'part_pkg_report_option',
-                              'name_col' => 'name',
-                              'hashref'  => { 'disabled' => '' },
-                              'multiple' => 1,
-                            },
-
-                            { 'type'    => 'tablebreak-tr-title',
-                              'value'   => 'Term discounts',
-                            },
-                            { 'field'      => 'discountnum',
-                              'type'       => 'select-table',
-                              'table'      => 'discount',
-                              'name_col'   => 'name',
-                              'hashref'    => { %$discountnum_hashref },
-                              #'extra_sql'  => 'AND (months IS NOT NULL OR months != 0)',
-                              'empty_label'=> 'Select discount',
-                              'm2_label'   => 'Offer discounts for longer terms',
-                              'm2m_method' => 'part_pkg_discount',
-                              'm2m_dstcol' => 'discountnum',
-                              'm2_error_callback' => $discount_error_callback,
-                            },
-
-                            { 'type'    => 'tablebreak-tr-title',
-                              'value'   => 'Supplemental packages',
-                              'colspan' => '4',
-                            },
-                            { 'field'       => 'supp_dst_pkgpart',
-                              'type'        => 'select-part_pkg',
-                              'm2_label'    => 'Include complete package',
-                              'm2m_method'  => 'supp_part_pkg_link',
-                              'm2m_dstcol'  => 'dst_pkgpart',
-                              'm2_error_callback' =>
-                                &{$m2_error_callback_maker}('supp'),
-                            },
-
-                            { 'type'    => 'tablebreak-tr-title',
-                              'value'   => 'Pricing add-ons',
-                              'colspan' => 4,
-                            },
-                            { 'field'      => 'bill_dst_pkgpart',
-                              'type'       => 'select-part_pkg',
-                              'extra_sql'  => sub { $pkgpart
-                                                     ? "AND pkgpart != $pkgpart"
-                                                     : ''
-                                                  },
-                              'm2_label'   => 'Include line item(s) from package',
-                              'm2m_method' => 'bill_part_pkg_link',
-                              'm2m_dstcol' => 'dst_pkgpart',
-                              'm2_error_callback' =>
-                                &{$m2_error_callback_maker}('bill'),
-                              'm2_fields' => [ { 'field' => 'hidden',
-                                                 'type'  => 'checkbox',
-                                                 'value' => 'Y',
-                                                 'curr_value' => '',
-                                                 'label' => 'Bundle',
-                                               },
-                                             ],
-                            },
-
-                            { type  => 'tablebreak-tr-title',
-                              value => 'Services',
-                            },
-                            { type => 'pkg_svc', },
-
-                            { 'field'      => 'svc_dst_pkgpart',
-                              'label'      => 'Also include services from package: ',
-                              'type'       => 'select-part_pkg',
-                              'extra_sql'  => sub { $pkgpart
-                                                     ? "AND pkgpart != $pkgpart"
-                                                     : ''
-                                                  },
-                              'm2_label'   => 'Include services of package: ',
-                              'm2m_method' => 'svc_part_pkg_link',
-                              'm2m_dstcol' => 'dst_pkgpart',
-                              'm2_error_callback' =>
-                                &{$m2_error_callback_maker}('svc'),
-                            },
-
-                            { type  => 'tablebreak-tr-title',
-                              value => 'Price plan options',
-                            },
-
-                          ],
-
-           )
-%>
+<& elements/edit.html,
+     'post_url'              => popurl(1).'process/part_pkg.cgi',
+     'name'                  => "Package definition",
+     'table'                 => 'part_pkg',
+
+     'agent_virt'            => 1,
+     'agent_null_right'      => $edit_global,
+     'agent_clone_extra_sql' => $agent_clone_extra_sql,
+     #'viewall_dir'           => 'browse',
+     'viewall_url'           => $p.'browse/part_pkg.cgi',
+     'html_init'             => include('/elements/init_overlib.html').
+                                $javascript,
+     'html_bottom'           => $html_bottom,
+     'body_etc'              =>
+       'onLoad="agent_changed(document.edit_topform.agentnum);
+                aux_planchanged(document.edit_topform.plan)"',
+
+     'begin_callback'        => $begin_callback,
+     'end_callback'          => $end_callback,
+     'new_hashref_callback'  => $new_hashref_callback,
+     'new_object_callback'   => $new_object_callback,
+     'new_callback'          => $new_callback,
+     'clone_callback'        => $clone_callback,
+     'edit_callback'         => $edit_callback,
+     'error_callback'        => $error_callback,
+     'field_callback'        => $field_callback,
+
+     'onsubmit'              => 'confirm_submit',
+
+     'labels' => { 
+                   'pkgpart'          => 'Package Definition',
+                   'pkg'              => 'Package',
+                   %locale_field_labels,
+                   'comment'          => 'Comment (customer-hidden)',
+                   'classnum'         => 'Package class',
+                   'addon_classnum'   => 'Restrict additional orders to package class',
+                   'promo_code'       => 'Promotional code',
+                   'freq'             => 'Recurring fee frequency',
+                   'setuptax'         => 'Setup fee tax exempt',
+                   'recurtax'         => 'Recurring fee tax exempt',
+                   'taxclass'         => 'Tax class',
+                   'taxproduct_select'=> 'Tax products',
+                   'plan'             => 'Price plan',
+                   'disabled'         => 'Disable new orders',
+                   'disable_line_item_date_ranges' => 'Disable line item date ranges',
+                   'setup_cost'       => 'Setup cost',
+                   'recur_cost'       => 'Recur cost',
+                   'pay_weight'       => 'Payment weight',
+                   'credit_weight'    => 'Credit weight',
+                   'agentnum'         => 'Agent',
+                   'setup_fee'        => 'Setup fee',
+                   'setup_show_zero'  => 'Show zero setup',
+                   'recur_fee'        => 'Recurring fee',
+                   'recur_show_zero'  => 'Show zero recurring',
+                   ( map { ( "setup_fee_$_" => "Setup fee $_",
+                             "recur_fee_$_" => "Recurring fee $_",
+                           );
+                         }
+                       $conf->config('currencies')
+                   ),
+                   'discountnum'      => 'Offer discounts for longer terms',
+                   'bill_dst_pkgpart' => 'Include line item(s) from package',
+                   'svc_dst_pkgpart'  => 'Include services of package',
+                   'supp_dst_pkgpart' => 'Include complete package',
+                   'report_option'    => 'Report classes',
+                   'fcc_ds0s'         => 'Voice-grade equivalents',
+                   'fcc_voip_class'   => 'Category',
+                 },
+
+     'fields' => [
+                   { field=>'clone',  type=>'hidden',
+                     curr_value_callback =>
+                       sub { shift->param('clone') },
+                   },
+                   { field=>'pkgnum', type=>'hidden',
+                     curr_value_callback =>
+                       sub { shift->param('pkgnum') },
+                   },
+
+                   { field=>'custom',  type=>'hidden' },
+                   { field=>'family_pkgpart', type=>'hidden' },
+                   { field=>'successor', type=>'hidden' },
+
+                   { type => 'columnstart' },
+                   
+                     { field     => 'pkg',
+                       type      => 'text',
+                       size      => 40, #32
+                       maxlength => 50,
+                     },
+                     #@locale_fields,
+                     {field=>'comment',  type=>'text', size=>40 }, #32
+                     { field         => 'agentnum',
+                       type          => 'select-agent',
+                       disable_empty => ! $acl_edit_global,
+                       empty_label   => '(global)',
+                       onchange      => 'agent_changed',
+                     },
+                     {field=>'classnum', type=>'select-pkg_class' },
+                     ( $conf->exists('pkg-addon_classnum')
+                         ? ( { field=>'addon_classnum',
+                               type =>'select-pkg_class',
+                             }
+                           )
+                          : ()
+                     ),
+                     {field=>'disabled', type=>$disabled_type, value=>'Y'},
+                     {field=>'disable_line_item_date_ranges', type=>$disabled_type, value=>'Y'},
+
+                     { type     => 'tablebreak-tr-title',
+                       value    => 'Pricing', #better name?
+                     },
+                     { field    => 'plan',
+                       type     => 'selectlayers-select',
+                       options  => [ keys %plan_labels ],
+                       labels   => \%plan_labels,
+                       onchange => 'aux_planchanged(what);',
+                     },
+                     { field    => 'setup_fee',
+                       type     => 'money',
+                       onchange => 'setup_changed',
+                     },
+                     { field    => 'setup_show_zero',
+                       type     => 'checkbox',
+                       value    => 'Y',
+                       disabled => sub { $setup_show_zero_disabled },
+                     },
+                     ( map { +{ field => "setup_fee_$_",
+                                type  => 'text',
+                                prefix=> currency_symbol($_, SYM_HTML),
+                                size  => 8,
+                              }
+                           }
+                         sort $conf->config('currencies')
+                     ),
+                     { field    => 'freq',
+                       type     => 'part_pkg_freq',
+                       onchange => 'freq_changed',
+                     },
+                     { field    => 'recur_fee',
+                       type     => 'money',
+                       disabled => sub { $recur_disabled },
+                       onchange => 'recur_changed',
+                     },
+                     { field    => 'recur_show_zero',
+                       type     => 'checkbox',
+                       value    => 'Y',
+                       disabled => sub { $recur_show_zero_disabled },
+                     },
+                     ( map { +{ field => "recur_fee_$_",
+                                type  => 'text',
+                                prefix=> currency_symbol($_, SYM_HTML),
+                                size  => 8,
+                              }
+                           }
+                         sort $conf->config('currencies')
+                     ),
+
+                     #price plan
+                     #setup fee
+                     #recurring frequency
+                     #recurring fee (auto-disable)
+
+                   { type => 'columnnext' },
+
+                     {type=>'justtitle', value=>'Taxation' },
+                     {field=>'setuptax', type=>'checkbox', value=>'Y'},
+                     {field=>'recurtax', type=>'checkbox', value=>'Y'},
+                     {field=>'taxclass', type=>'select-taxclass' },
+                     { field => 'taxproductnums',
+                       type  => 'hidden',
+                       value => join(',', @taxproductnums),
+                     },
+                     { field => 'taxproduct_select',
+                       type  => 'selectlayers',
+                       options => [ '(default)', @taxproductnums ],
+                       curr_value => '(default)',
+                       labels  => { ( '(default)' => '(default)' ),
+                                    map {($_=>$usage_class{$_})}
+                                    @taxproductnums
+                                  },
+                       layer_fields => \%taxproduct_fields,
+                       layer_values_callback => $taxproduct_values,
+                       layers_only  =>   !$taxproducts,
+                       cell_style   => ( !$taxproducts
+                                         ? 'display:none'
+                                         : ''
+                                       ),
+                     },
+
+                     { type  => 'tablebreak-tr-title',
+                       value => 'Promotions', #better name?
+                     },
+                     { field=>'promo_code', type=>'text', size=>15 },
+
+                     { type  => 'tablebreak-tr-title',
+                       value => 'Cost tracking', #better name?
+                     },
+                     { field=>'setup_cost', type=>'money', },
+                     { field=>'recur_cost', type=>'money', },
+
+                   { type => 'columnnext' },
+
+                     { field    => 'agent_type',
+                       type     => 'select-agent_types',
+                       disabled => ! $acl_edit_global,
+                       curr_value_callback => sub {
+                         my($cgi, $object, $field) = @_;
+                         #in the other callbacks..?  hmm.
+                         \@agent_type;
+                       },
+                     },
+
+                     { type  => 'tablebreak-tr-title',
+                       value => 'Line-item revenue recogition', #better name?
+                     },
+                     { field=>'pay_weight',    type=>'text', size=>6 },
+                     { field=>'credit_weight', type=>'text', size=>6 },
+
+                     ( $conf->exists('cust_pkg-show_fcc_voice_grade_equivalent')
+                       ? ( 
+                           { type  => 'tablebreak-tr-title',
+                             value => 'FCC Form 477 information',
+                           },
+                           { field=>'fcc_voip_class',
+                             type=>'select-voip_class',
+                           },
+                           { field=>'fcc_ds0s', type=>'text', size=>6 },
+                         )
+                        : ()
+                     ),
+
+
+                   { type => 'columnend' },
+
+                   { 'type'  => $report_option ? 'tablebreak-tr-title'
+                                               : 'hidden',
+                     'value' => 'Optional report classes',
+                     'field' => 'census_title',
+                   },
+                   { 'field'    => 'report_option',
+                     'type'     => $report_option ? 'select-table'
+                                                  : 'hidden',
+                     'table'    => 'part_pkg_report_option',
+                     'name_col' => 'name',
+                     'hashref'  => { 'disabled' => '' },
+                     'multiple' => 1,
+                   },
+
+                   { 'type'    => 'tablebreak-tr-title',
+                     'value'   => 'Term discounts',
+                   },
+                   { 'field'      => 'discountnum',
+                     'type'       => 'select-table',
+                     'table'      => 'discount',
+                     'name_col'   => 'name',
+                     'hashref'    => { %$discountnum_hashref },
+                     #'extra_sql'  => 'AND (months IS NOT NULL OR months != 0)',
+                     'empty_label'=> 'Select discount',
+                     'm2_label'   => 'Offer discounts for longer terms',
+                     'm2m_method' => 'part_pkg_discount',
+                     'm2m_dstcol' => 'discountnum',
+                     'm2_error_callback' => $discount_error_callback,
+                   },
+
+                   { 'type'    => 'tablebreak-tr-title',
+                     'value'   => 'Supplemental packages',
+                     'colspan' => '4',
+                   },
+                   { 'field'       => 'supp_dst_pkgpart',
+                     'type'        => 'select-part_pkg',
+                     'm2_label'    => 'Include complete package',
+                     'm2m_method'  => 'supp_part_pkg_link',
+                     'm2m_dstcol'  => 'dst_pkgpart',
+                     'm2_error_callback' =>
+                       &{$m2_error_callback_maker}('supp'),
+                   },
+
+                   { 'type'    => 'tablebreak-tr-title',
+                     'value'   => 'Pricing add-ons',
+                     'colspan' => 4,
+                   },
+                   { 'field'      => 'bill_dst_pkgpart',
+                     'type'       => 'select-part_pkg',
+                     'extra_sql'  => sub { $pkgpart
+                                            ? "AND pkgpart != $pkgpart"
+                                            : ''
+                                         },
+                     'm2_label'   => 'Include line item(s) from package',
+                     'm2m_method' => 'bill_part_pkg_link',
+                     'm2m_dstcol' => 'dst_pkgpart',
+                     'm2_error_callback' =>
+                       &{$m2_error_callback_maker}('bill'),
+                     'm2_fields' => [ { 'field' => 'hidden',
+                                        'type'  => 'checkbox',
+                                        'value' => 'Y',
+                                        'curr_value' => '',
+                                        'label' => 'Bundle',
+                                      },
+                                    ],
+                   },
+
+                   { type  => 'tablebreak-tr-title',
+                     value => 'Services',
+                   },
+                   { type => 'pkg_svc', },
+
+                   { 'field'      => 'svc_dst_pkgpart',
+                     'label'      => 'Also include services from package: ',
+                     'type'       => 'select-part_pkg',
+                     'extra_sql'  => sub { $pkgpart
+                                            ? "AND pkgpart != $pkgpart"
+                                            : ''
+                                         },
+                     'm2_label'   => 'Include services of package: ',
+                     'm2m_method' => 'svc_part_pkg_link',
+                     'm2m_dstcol' => 'dst_pkgpart',
+                     'm2_error_callback' =>
+                       &{$m2_error_callback_maker}('svc'),
+                   },
+
+                   { type  => 'tablebreak-tr-title',
+                     value => 'Price plan options',
+                   },
+
+                 ],
+&>
 <%init>
 
 my $curuser = $FS::CurrentUser::CurrentUser;
@@ -757,16 +756,28 @@ my $javascript = <<'END';
 
     function aux_planchanged(what) { //?
 
-      alert('called!');
       var plan = what.options[what.selectedIndex].value;
-      var table = document.getElementById('TableNumber7') // XXX NOT ROBUST
 
+      var term_table = document.getElementById('TableNumber7') // XXX NOT ROBUST
       if ( plan == 'flat' || plan == 'prorate' || plan == 'subscription' ) {
-        //table.disabled = false;
-        table.style.visibility = '';
+        //term_table.disabled = false;
+        term_table.style.visibility = '';
       } else {
-        //table.disabled = true;
-        table.style.visibility = 'hidden';
+        //term_table.disabled = true;
+        term_table.style.visibility = 'hidden';
+      }
+
+      var currency_regex = /^(setup|recur)_fee_[A-Z]{3}$/;
+
+      var form = what.form
+      for ( var i=0; i < form.length; i++ ) {
+        if ( currency_regex.test(form[i].name) ) {
+          if ( plan == 'currency_fixed' ) {
+            form[i].disabled = false;
+          } else {
+            form[i].disabled = true;
+          }
+        }
       }
 
     }
@@ -940,6 +951,7 @@ my $html_bottom = sub {
     labels         => \%plan_labels,
     curr_value     => $object->plan,
     layer_callback => $layer_callback,
+    onchange       => 'aux_planchanged(what);',
   );
 
   my $return =

commit 91893b441b4281d0384dbb783e67383d0ea5ead2
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Mon Jun 10 23:20:23 2013 -0700

    multi-currency, RT#21565

diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index b2ff45b..7d9172a 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -211,7 +211,7 @@ if ( $conf->config('currencies') ) {
   @currency_sub = (
     map {
       my $what = $_;
-      sub { my $currency = $_[0]->get($what.'_billed_currency');
+      sub { my $currency = $_[0]->get($what.'_billed_currency') or return '';
             $currency. ' '. currency_symbol($currency, SYM_HTML).
               $_[0]->get($what.'_billed_amount');
           };

commit b7a2175dd9b386441f4ab66869d73083e5e8beb1
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Mon Jun 10 23:15:03 2013 -0700

    multi-currency, RT#21565

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index f1cc09c..da3ddab 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -768,24 +768,26 @@ sub tables_hashref {
 
     'cust_bill_pkg' => {
       'columns' => [
-        'billpkgnum',        'serial',     '',      '', '', '', 
-        'invnum',               'int',     '',      '', '', '', 
-        'pkgnum',               'int',     '',      '', '', '', 
-        'pkgpart_override',     'int', 'NULL',      '', '', '', 
-        'setup',               @money_type,             '', '', 
-        'recur',               @money_type,             '', '', 
-        #XXX a currency for a line item?  or just one for the entire invoice
-        #'currency',            'char', 'NULL',       3, '', '',
-        'sdate',               @date_type,              '', '', 
-        'edate',               @date_type,              '', '', 
-        'itemdesc',         'varchar', 'NULL', $char_d, '', '', 
-        'itemcomment',      'varchar', 'NULL', $char_d, '', '', 
-        'section',          'varchar', 'NULL', $char_d, '', '', 
-        'freq',             'varchar', 'NULL', $char_d, '', '',
-        'quantity',             'int', 'NULL',      '', '', '',
-        'unitsetup',           @money_typen,            '', '', 
-        'unitrecur',           @money_typen,            '', '', 
-        'hidden',              'char', 'NULL',       1, '', '',
+        'billpkgnum',          'serial',     '',      '', '', '', 
+        'invnum',                 'int',     '',      '', '', '', 
+        'pkgnum',                 'int',     '',      '', '', '', 
+        'pkgpart_override',       'int', 'NULL',      '', '', '', 
+        'setup',                 @money_type,             '', '', 
+        'unitsetup',             @money_typen,            '', '', 
+        'setup_billed_currency', 'char', 'NULL',       3, '', '',
+        'setup_billed_amount',   @money_typen,            '', '',
+        'recur',                 @money_type,             '', '', 
+        'unitrecur',             @money_typen,            '', '', 
+        'recur_billed_currency', 'char', 'NULL',       3, '', '',
+        'recur_billed_amount',   @money_typen,            '', '',
+        'sdate',                 @date_type,              '', '', 
+        'edate',                 @date_type,              '', '', 
+        'itemdesc',           'varchar', 'NULL', $char_d, '', '', 
+        'itemcomment',        'varchar', 'NULL', $char_d, '', '', 
+        'section',            'varchar', 'NULL', $char_d, '', '', 
+        'freq',               'varchar', 'NULL', $char_d, '', '',
+        'quantity',               'int', 'NULL',      '', '', '',
+        'hidden',                'char', 'NULL',       1, '', '',
       ],
       'primary_key' => 'billpkgnum',
       'unique' => [],
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index 0c8c0bb..572fe79 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -434,7 +434,13 @@ sub check {
       || $self->ut_snumber('pkgnum')
       || $self->ut_number('invnum')
       || $self->ut_money('setup')
+      || $self->ut_moneyn('unitsetup')
+      || $self->ut_currencyn('setup_billed_currency')
+      || $self->ut_moneyn('setup_billed_amount')
       || $self->ut_money('recur')
+      || $self->ut_moneyn('unitrecur')
+      || $self->ut_currencyn('recur_billed_currency')
+      || $self->ut_moneyn('recur_billed_amount')
       || $self->ut_numbern('sdate')
       || $self->ut_numbern('edate')
       || $self->ut_textn('itemdesc')
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 3fbee15..f3122aa 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -1757,7 +1757,7 @@ sub check {
     || $self->ut_flag('invoice_noemail')
     || $self->ut_flag('message_noemail')
     || $self->ut_enum('locale', [ '', FS::Locales->locales ])
-    || $self->ut_currency('currency')
+    || $self->ut_currencyn('currency')
   ;
 
   my $company = $self->company;
diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm
index 814802b..220f66a 100644
--- a/FS/FS/cust_main/Billing.pm
+++ b/FS/FS/cust_main/Billing.pm
@@ -951,6 +951,8 @@ sub _make_lines {
   my $unitsetup = 0;
   my @setup_discounts = ();
   my %setup_param = ( 'discounts' => \@setup_discounts );
+  my $setup_billed_currency = '';
+  my $setup_billed_amount = 0;
   if (     ! $options{recurring_only}
        and ! $options{cancel}
        and ( $options{'resetup'}
@@ -977,7 +979,13 @@ sub _make_lines {
         return "$@ running calc_setup for $cust_pkg\n"
           if $@;
 
-        $unitsetup = $cust_pkg->part_pkg->unit_setup || $setup; #XXX uuh
+        $unitsetup = $cust_pkg->base_setup()
+                       || $setup; #XXX uuh
+
+        if ( $setup_param{'billed_currency'} ) {
+          $setup_billed_currency = delete $setup_param{'billed_currency'};
+          $setup_billed_amount   = delete $setup_param{'billed_amount'};
+        }
     }
 
     $cust_pkg->setfield('setup', $time)
@@ -997,6 +1005,8 @@ sub _make_lines {
   my $recur = 0;
   my $unitrecur = 0;
   my @recur_discounts = ();
+  my $recur_billed_currency = '';
+  my $recur_billed_amount = 0;
   my $sdate;
   if (     ! $cust_pkg->start_date
        and ( ! $cust_pkg->susp || $cust_pkg->option('suspend_bill',1)
@@ -1058,6 +1068,11 @@ sub _make_lines {
     #base_cancel???
     $unitrecur = $cust_pkg->base_recur( \$sdate ) || $recur; #XXX uuh, better
 
+    if ( $param{'billed_currency'} ) {
+      $recur_billed_currency = delete $param{'billed_currency'};
+      $recur_billed_amount   = delete $param{'billed_amount'};
+    }
+
     if ( $increment_next_bill ) {
 
       my $next_bill;
@@ -1173,16 +1188,20 @@ sub _make_lines {
       push @details, @cust_pkg_detail;
 
       my $cust_bill_pkg = new FS::cust_bill_pkg {
-        'pkgnum'    => $cust_pkg->pkgnum,
-        'setup'     => $setup,
-        'unitsetup' => $unitsetup,
-        'recur'     => $recur,
-        'unitrecur' => $unitrecur,
-        'quantity'  => $cust_pkg->quantity,
-        'details'   => \@details,
-        'discounts' => [ @setup_discounts, @recur_discounts ],
-        'hidden'    => $part_pkg->hidden,
-        'freq'      => $part_pkg->freq,
+        'pkgnum'                => $cust_pkg->pkgnum,
+        'setup'                 => $setup,
+        'unitsetup'             => $unitsetup,
+        'setup_billed_currency' => $setup_billed_currency,
+        'setup_billed_amount'   => $setup_billed_amount,
+        'recur'                 => $recur,
+        'unitrecur'             => $unitrecur,
+        'recur_billed_currency' => $recur_billed_currency,
+        'recur_billed_amount'   => $recur_billed_amount,
+        'quantity'              => $cust_pkg->quantity,
+        'details'               => \@details,
+        'discounts'             => [ @setup_discounts, @recur_discounts ],
+        'hidden'                => $part_pkg->hidden,
+        'freq'                  => $part_pkg->freq,
       };
 
       if ( $part_pkg->option('prorate_defer_bill',1) 
@@ -1194,7 +1213,7 @@ sub _make_lines {
         $cust_bill_pkg->sdate( $hash{last_bill} );
         $cust_bill_pkg->edate( $sdate - 86399   ); #60s*60m*24h-1
         $cust_bill_pkg->edate( $time ) if $options{cancel};
-      } else { #if ( $part_pkg->recur_temporality eq 'upcoming' ) {
+      } else { #if ( $part_pkg->recur_temporality eq 'upcoming' )
         $cust_bill_pkg->sdate( $sdate );
         $cust_bill_pkg->edate( $cust_pkg->bill );
         #$cust_bill_pkg->edate( $time ) if $options{cancel};
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index 8357386..3d24ea5 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -2191,6 +2191,18 @@ sub calc_recur {
   $self->part_pkg->calc_recur($self, @_);
 }
 
+=item base_setup
+
+Calls the I<base_setup> of the FS::part_pkg object associated with this billing
+item.
+
+=cut
+
+sub base_setup {
+  my $self = shift;
+  $self->part_pkg->base_setup($self, @_);
+}
+
 =item base_recur
 
 Calls the I<base_recur> of the FS::part_pkg object associated with this billing
@@ -2345,9 +2357,11 @@ sub num_cust_event {
 
 =item part_pkg_currency_option OPTIONNAME
 
-Returns the option value for the given name and the currency of this customer
-(see L<FS::part_pkg_currency>).  If this customer has no currency, returns
-the regular option value for the given name (see L<FS::part_pkg_option>).
+Returns a two item list consisting of the currency of this customer, if any,
+and a value for the provided option.  If the customer has a currency, the value
+is the option value the given name and the currency (see
+L<FS::part_pkg_currency>).  Otherwise, if the customer has no currency, is the
+regular option value for the given name (see L<FS::part_pkg_option>).
 
 =cut
 
@@ -2355,9 +2369,9 @@ sub part_pkg_currency_option {
   my( $self, $optionname ) = @_;
   my $part_pkg = $self->part_pkg;
   if ( my $currency = $self->cust_main->currency ) {
-    $part_pkg->part_pkg_currency_option($currency, $optionname);
+    ($currency, $part_pkg->part_pkg_currency_option($currency, $optionname) );
   } else {
-    $part_pkg->option($optionname);
+    ('', $part_pkg->option($optionname) );
   }
 }
 
diff --git a/FS/FS/part_pkg/currency_fixed.pm b/FS/FS/part_pkg/currency_fixed.pm
index bee6c5b..ce71452 100644
--- a/FS/FS/part_pkg/currency_fixed.pm
+++ b/FS/FS/part_pkg/currency_fixed.pm
@@ -5,7 +5,8 @@ use base qw( FS::part_pkg::recur_Common );
 
 use strict;
 use vars qw( %info );
-#use FS::Record qw(qsearch qsearchs);
+use FS::Record qw(qsearchs); # qsearch qsearchs);
+use FS::currency_exchange;
 
 %info = (
   'name' => 'Per-currency pricing from package definitions',
@@ -26,7 +27,7 @@ use vars qw( %info );
   },
   'fieldorder' => [qw( recur_method cutoff_day ),
                    FS::part_pkg::prorate_Mixin::fieldorder,
-                  )],
+                  ],
   'weight' => '59',
 );
 
@@ -37,19 +38,44 @@ sub price_info {
     $str;
 }
 
-#some false laziness w/recur_Common, could have been better about it.. pry when
-# we do discounting
+sub base_setup {
+  my($self, $cust_pkg, $sdate, $details, $param ) = @_;
+
+  $self->calc_currency_option('setup_fee', $cust_pkg, $sdate, $details, $param);
+}
+
 sub calc_setup {
   my($self, $cust_pkg, $sdate, $details, $param) = @_;
 
   return 0 if $self->prorate_setup($cust_pkg, $sdate);
 
-  sprintf('%.2f', $cust_pkg->part_pkg_currency_option('setup_fee') );
+  $self->base_setup($cust_pkg, $sdate, $details, $param);
+}
+
+use FS::Conf;
+sub calc_currency_option {
+  my($self, $optionname, $cust_pkg, $sdate, $details, $param) = @_;
+
+  my($currency, $amount) = $cust_pkg->part_pkg_currency_option($optionname);
+  return sprintf('%.2f', $amount ) unless $currency;
+
+  $param->{'billed_currency'} = $currency;
+  $param->{'billed_amount'}   = $amount;
+
+  my $currency_exchange = qsearchs('currency_exchange', {
+    'from_currency' => $currency,
+    'to_currency'   => ( FS::Conf->new->config('currency') || 'USD' ),
+  }) or die "No exchange rate from $currency\n";
+
+  #XXX do we want the rounding here to work differently?
+  #my $recognized_amount =
+  sprintf('%.2f', $amount * $currency_exchange->rate);
 }
 
 sub base_recur {
-  my( $self, $cust_pkg ) = @_;
-  sprintf('%.2f', $cust_pkg->part_pkg_currency_option('recur_fee') );
+  my( $self, $cust_pkg, $sdate, $details, $param ) = @_;
+  $param ||= {};
+  $self->calc_currency_option('recur_fee', $cust_pkg, $sdate, $details, $param);
 }
 
 sub can_discount { 0; } #can't discount yet (percentage would work, but amount?)
diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm
index 22eb698..9737a94 100644
--- a/FS/FS/part_pkg/flat.pm
+++ b/FS/FS/part_pkg/flat.pm
@@ -122,7 +122,7 @@ sub calc_setup {
 
   my $quantity = $cust_pkg->quantity || 1;
 
-  my $charge = $quantity * $self->unit_setup($cust_pkg, $sdate, $details);
+  my $charge = $quantity * $self->base_setup($cust_pkg, $sdate, $details);
 
   my $discount = 0;
   if ( $charge > 0 ) {
@@ -134,7 +134,7 @@ sub calc_setup {
   sprintf('%.2f', $charge - $discount);
 }
 
-sub unit_setup {
+sub base_setup {
   my($self, $cust_pkg, $sdate, $details ) = @_;
 
   $self->option('setup_fee') || 0;
diff --git a/FS/FS/part_pkg/recur_Common.pm b/FS/FS/part_pkg/recur_Common.pm
index 03d5c2c..ebf8869 100644
--- a/FS/FS/part_pkg/recur_Common.pm
+++ b/FS/FS/part_pkg/recur_Common.pm
@@ -61,7 +61,7 @@ sub calc_recur_Common {
     my $recur_method = $self->option('recur_method', 1) || 'anniversary';
     my @cutoff_day = $self->cutoff_day($cust_pkg);
 
-    $charges = $self->base_recur($cust_pkg);
+    $charges = $self->base_recur($cust_pkg, $sdate, $details, $param);
     $charges += $param->{'override_charges'} if $param->{'override_charges'};
 
     if ( $recur_method eq 'prorate' ) {
diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html
index 5a66f0a..da5f0f2 100644
--- a/httemplate/edit/cust_main/billing.html
+++ b/httemplate/edit/cust_main/billing.html
@@ -615,6 +615,23 @@ function toggle(obj) {
       <INPUT TYPE="hidden" NAME="cdr_termination_percentage" VALUE="<% $cust_main->cdr_termination_percentage %>">
 % }
 
+%my @currencies = $conf->config('currencies');
+%if ( scalar(@currencies) ) {
+%  unshift @currencies, ''; #default
+%  my %currency_labels = map { $_ => "$_: ". code2currency($_) } @currencies;
+%  $currency_labels{''} =
+%    'Default: '. code2currency( $conf->config('currency') || 'USD' );
+
+    <& /elements/tr-select.html, 
+         'label'         => emt('Invoicing currency'),
+         'field'         => 'currency',
+         'options'       => \@currencies,
+         'labels'        => \%currency_labels,
+         'curr_value'    => $cust_main->currency,
+    &>
+% }
+
+
 %my @available_locales = $conf->config('available-locales');
 %if ( scalar(@available_locales) ) {
 %  push @available_locales, ''
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index 1830511..b2ff45b 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -10,6 +10,7 @@
                    emt('Description'),
                    @post_desc_header,
                    @peritem_desc,
+                   @currency_desc,
                    emt('Invoice'),
                    emt('Date'),
                    emt('Paid'),
@@ -32,6 +33,7 @@
                    #strikethrough or "N/A ($amount)" or something these when
                    # they're not applicable to pkg_tax search
                    @peritem_sub,
+                   @currency_sub,
                    'invnum',
                    sub { time2str('%b %d %Y', shift->_date ) },
                    sub { sprintf($money_char.'%.2f', shift->get('pay_amount')) },
@@ -44,6 +46,7 @@
                    '',
                    @post_desc_null,
                    @peritem,
+                   @currency,
                    'invnum',
                    '_date',
                    #'pay_amount',
@@ -55,6 +58,7 @@
                    '',
                    @post_desc_null,
                    @peritem_null,
+                   @currency_null,
                    $ilink,
                    $ilink,
                    $pay_link,
@@ -68,6 +72,7 @@
                             'rl'.
                             $post_desc_align.
                             $peritem_align.
+                            $currency_align.
                             'rcrr'.
                             FS::UI::Web::cust_aligns(),
                  'color' => [ 
@@ -76,6 +81,7 @@
                               '',
                               @post_desc_null,
                               @peritem_null,
+                              @currency_null,
                               '',
                               '',
                               '',
@@ -88,6 +94,7 @@
                               '',
                               @post_desc_null,
                               @peritem_null,
+                              @currency_null,
                               '',
                               '',
                               '',
@@ -196,6 +203,23 @@ my @total_desc = ( $money_char.'%.2f total' ); # sprintf strings
 my @peritem = ( 'setup', 'recur' );
 my @peritem_desc = ( 'Setup charge', 'Recurring charge' );
 
+my @currency_desc = ();
+my @currency_sub = ();
+my @currency = ();
+if ( $conf->config('currencies') ) {
+  @currency_desc = ( 'Setup billed', 'Recurring billed' );
+  @currency_sub = (
+    map {
+      my $what = $_;
+      sub { my $currency = $_[0]->get($what.'_billed_currency');
+            $currency. ' '. currency_symbol($currency, SYM_HTML).
+              $_[0]->get($what.'_billed_amount');
+          };
+    } qw( setup recur )
+  );
+  @currency = ( 'setup_billed_amount', 'recur_billed_amount' ); #for sorting
+}
+
 my @pkgnum_header = ();
 my @pkgnum = ();
 my @pkgnum_null;
@@ -672,6 +696,10 @@ my @peritem_sub = map {
 my @peritem_null = map { '' } @peritem; # placeholders
 my $peritem_align = 'r' x scalar(@peritem);
 
+ at currency_desc = map {emt($_)} @currency_desc;
+my @currency_null = map { '' } @currency; # placeholders
+my $currency_align = 'r' x scalar(@currency);
+
 my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ];
 my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
 
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index b863a73..e286305 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -304,6 +304,13 @@
   </TR>
 % }
 
+% if ( $cust_main->currency ) {
+  <TR>
+    <TD ALIGN="right"><% mt('Invoicing currency') |h %></TD>
+    <TD BGCOLOR="#ffffff"><% $cust_main->currency. ': '. code2currency($cust_main->currency) %></TD>
+  </TR>
+% }
+
 % if ( $cust_main->locale ) {
 % my %locale_info = FS::Locales->locale_info($cust_main->locale);
   <TR>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Schema.pm                        |   38 +-
 FS/FS/cust_bill_pkg.pm                 |    6 +
 FS/FS/cust_main.pm                     |   16 +-
 FS/FS/cust_main/Billing.pm             |   43 ++-
 FS/FS/cust_pkg.pm                      |   24 +-
 FS/FS/part_pkg/currency_fixed.pm       |   40 ++-
 FS/FS/part_pkg/flat.pm                 |    4 +-
 FS/FS/part_pkg/recur_Common.pm         |    2 +-
 httemplate/edit/cust_main/billing.html |   17 +
 httemplate/edit/part_pkg.cgi           |  680 ++++++++++++++++----------------
 httemplate/search/cust_bill_pkg.cgi    |   28 ++
 httemplate/view/cust_main/billing.html |    7 +
 12 files changed, 523 insertions(+), 382 deletions(-)




More information about the freeside-commits mailing list