diff options
85 files changed, 3577 insertions, 1198 deletions
| @@ -157,5 +157,11 @@ Perl backend version (c) copyright 2005 Nathan Schmidt  Scott Edwards <supadupa@gmail.com> contributed magic for XMLHTTP error  handling, and other patches. +Contains XMenu <http://webfx.eae.net/dhtml/xmenu/xmenu.html> +by Erik Arvidsson, licensed under the terms of the GNU GPL. + +Contains public domain artwork from openclipart.org by mimooh and other +authors. +  Everything else is my (Ivan Kohler <ivan@420.am>) fault. diff --git a/Changes.1.7.0 b/Changes.1.7.0 new file mode 100644 index 000000000..8dcc36e08 --- /dev/null +++ b/Changes.1.7.0 @@ -0,0 +1,39 @@ +- tax report overhaul +- package classes +- UI overhaul.  No more Apache::ASP support, HTML::Mason only +- lots of CDR/telephony work +- inventory classes and inventory (better description from directleap/specs.txt) +- vonage click2call bs :) +- zip code report +- sales/credit/receipt summary report now has options for agent, 12mo cumulative totals +- gross sales report/graph broken down by agent and package class +- config switch to base tax off shipping address if present (warning: tax reports can take a long time with this switch on) +- plesk provisioning + +-------- some of the above, nicely: + +- Charge taxes based on shipping address if present.  Note that tax  +  reports can take a bit longer than they used to. + +- Per-agent A/R Aging +  - Bookeeping/Collections | Accounts Receivable Aging Summary + +- Per-agent Sales/Credit/Receipt Summary and "pre-selection" of agent  +  and time period as you requested. +  - Bookeeping/Collections | Sales, Credits and Receipts Summary + +- Package classes +  - go to Sysadmin | View/Edit package classes and create some classes +  - go to Sysadmin | View/Edit package definitions, edit the existing +    package defs and put them into classes + +- The sales report you requested, broken down by agent and  +  package class.  This works fine right now, but it will show more +  information once you enter some package classes. +  - Bookeeping/Collections | Sales report (by agent, package class ... + +-------- + +and... +- ACLs +- Agent virtualization diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm new file mode 100644 index 000000000..01d63e35d --- /dev/null +++ b/FS/FS/AccessRight.pm @@ -0,0 +1,77 @@ +package FS::AccessRight; + +use strict; +user vars qw(@rights %rights); +use Tie::IxHash; + +=head1 NAME + +FS::AccessRight - Access control rights. + +=head1 SYNOPSIS + +  use FS::AccessRight; + +=head1 DESCRIPTION + +Access control rights - Permission to perform specific actions that can be +assigned to users and/or groups. + +=cut + +@rights = ( +  'Reports' => [ +    '_desc' => 'Access to high-level reporting', +  ], +  'Configuration' => [ +    '_desc' => 'Access to configuration', + +    'Settings' => {}, + +    'agent' => [ +      '_desc' => 'Master access to reseller configuration', +      'agent_type'  => {}, +      'agent'       => {}, +    ], + +    'export_svc_pkg' => [ +      '_desc' => 'Access to export, service and package configuration', +      'part_export' => {}, +      'part_svc'    => {}, +      'part_pkg'    => {}, +      'pkg_class'   => {}, +    ], + +    'billing' => [ +      '_desc' => 'Access to billing configuration', +      'payment_gateway'  => {}, +      'part_bill_event'  => {}, +      'prepay_credit'    => {}, +      'rate'             => {}, +      'cust_main_county' => {}, +    ], + +    'dialup' => [ +      '_desc' => 'Access to dialup configuraiton', +      'svc_acct_pop' => {}, +    ], + +    'broadband' => [ +      '_desc' => 'Access to broadband configuration', +      'router'     => {}, +      'addr_block' => {}, +    ], + +    'misc' => [ +      'part_referral'      => {}, +      'part_virtual_field' => {}, +      'msgcat'             => {}, +      'inventory_class'    => {}, +    ], + +  }, + +); + +#turn it into a more hash-like structure, but ordered via IxHash + diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm index f1f2a3dca..d598f5218 100644 --- a/FS/FS/CGI.pm +++ b/FS/FS/CGI.pm @@ -62,9 +62,9 @@ sub header {        </HEAD>        <BODY BGCOLOR="#e8e8e8"$etc>            <FONT SIZE=6> -            $title +            <CENTER>$title</CENTER>            </FONT> -          <BR><BR> +          <BR><!--<BR>-->  END    $x .=  $menubar. "<BR><BR>" if $menubar;    $x; @@ -115,6 +115,7 @@ sub menubar { #$menubar=menubar('Main Menu', '../', 'Item', 'url', ... );    my($item,$url,@html);    while (@_) {      ($item,$url)=splice(@_,0,2); +    next if $item =~ /^\s*Main\s+Menu\s*$/i;      push @html, qq!<A HREF="$url">$item</A>!;    }    join(' | ',@html); diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 9125758d0..e81185666 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -244,6 +244,8 @@ sub tables_hashref {    my $username_len = 32; #usernamemax config file +    # name type nullability length default local +    return {      'agent' => { @@ -445,6 +447,9 @@ sub tables_hashref {        'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ],                     [ 'daytime' ], [ 'night' ], [ 'fax' ], [ 'refnum' ],                     [ 'county' ], [ 'state' ], [ 'country' ], [ 'zip' ], +                   [ 'ship_last' ], [ 'ship_company' ], +                   [ 'payby' ], [ 'paydate' ], +                   ],      }, @@ -1444,16 +1449,94 @@ sub tables_hashref {      'inventory_class' => {        'columns' => [ -        'classnum',  'serial',       '', '', '', '', -        'classname', 'varchar', $char_d, '', '', '', +        'classnum',  'serial',       '',      '', '', '', +        'classname', 'varchar',      '', $char_d, '', '',        ],        'primary_key' => 'classnum',        'unique' => [],        'index'  => [],      }, +    'access_user' => { +      'columns' => [ +        'usernum',   'serial',  '',      '', '', '', +        'username',  'varchar', '', $char_d, '', '', +        '_password', 'varchar', '', $char_d, '', '', +        'last',      'varchar', '', $char_d, '', '',  +        'first',     'varchar', '', $char_d, '', '',  +      ], +      'primary_key' => 'usernum', +      'unique' => [ [ 'username' ] ], +      'index'  => [], +    }, + +    'access_user_pref' => { +      'columns' => [ +        'prefnum',    'serial',       '', '', '', '', +        'usernum',     'int',       '', '', '', '', +        'prefname', 'varchar', '', $char_d, '', '',  +        'prefvalue', 'text', 'NULL', '', '', '',  +      ], +      'primary_key' => 'prefnum', +      'unique' => [], +      'index'  => [ [ 'usernum' ] ], +    }, + +    'access_group' => { +      'columns' => [ +        'groupnum',   'serial', '',      '', '', '', +        'groupname', 'varchar', '', $char_d, '', '', +      ], +      'primary_key' => 'groupnum', +      'unique' => [ [ 'groupname' ] ], +      'index'  => [], +    }, + +    'access_usergroup' => { +      'columns' => [ +        'usergroupnum', 'serial', '', '', '', '', +        'usernum',         'int', '', '', '', '', +        'groupnum',        'int', '', '', '', '', +      ], +      'primary_key' => 'usergroupnum', +      'unique' => [ [ 'usernum', 'groupnum' ] ], +      'index'  => [ [ 'usernum' ] ], +    }, + +    'access_groupagent' => { +      'columns' => [ +        'groupagentnum', 'serial', '', '', '', '', +        'groupnum',         'int', '', '', '', '', +        'agentnum',         'int', '', '', '', '', +      ], +      'primary_key' => 'groupagentnum', +      'unique' => [ [ 'groupnum', 'agentnum' ] ], +      'index'  => [ [ 'groupnum' ] ], +    }, + +    'access_right' => { +      'columns' => [ +        'rightnum',   'serial', '',      '', '', '', +        'righttype', 'varchar', '', $char_d, '', '', +        'rightobjnum',   'int', '',      '', '', '', +        'rightname', 'varchar', '',      '', '', '', +      ], +      'primary_key' => 'rightnum', +      'unique' => [ [ 'righttype', 'rightobjnum', 'rightname' ] ], +      'index'  => [], +    }, +    }; +    #'new_table' => { +    #  'columns' => [ +    #    'num', 'serial',       '', '', '', '', +    #  ], +    #  'primary_key' => 'num', +    #  'unique' => [], +    #  'index'  => [], +    #}, +  }  =back diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm index dc45e0188..10ddbf33f 100644 --- a/FS/FS/UI/Web.pm +++ b/FS/FS/UI/Web.pm @@ -184,6 +184,10 @@ sub process {      $self->job_status(@args); +  } else { + +    die "unknown sub $sub"; +    }  } @@ -228,11 +232,19 @@ sub start_job {    my $error = $job->insert( '_JOB', encode_base64(nfreeze(\%param)) );    if ( $error ) { + +    warn "job not inserted: $error\n" +      if $DEBUG; +      $error;  #this doesn't seem to be handled well,               # will trigger "illegal jobnum" below?               # (should never be an error inserting the job, though, only thing               #  would be Pg f%*kage)    } else { + +    warn "job inserted successfully with jobnum ". $job->jobnum. "\n" +      if $DEBUG; +      $job->jobnum;    } @@ -253,7 +265,7 @@ sub job_status {    my @return;    if ( $job && $job->status ne 'failed' ) {      @return = ( 'progress', $job->statustext ); -  } elsif ( !$job ) { #handle job gone case : job sucessful +  } elsif ( !$job ) { #handle job gone case : job successful                        # so close popup, redirect parent window...      @return = ( 'complete' );    } else { diff --git a/FS/FS/access_group.pm b/FS/FS/access_group.pm new file mode 100644 index 000000000..9d870e57f --- /dev/null +++ b/FS/FS/access_group.pm @@ -0,0 +1,121 @@ +package FS::access_group; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::access_group - Object methods for access_group records + +=head1 SYNOPSIS + +  use FS::access_group; + +  $record = new FS::access_group \%hash; +  $record = new FS::access_group { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_group object represents an example.  FS::access_group inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item groupnum - primary key + +=item groupname -  + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_group'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('groupnum') +    || $self->ut_text('groupname') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/access_groupagent.pm b/FS/FS/access_groupagent.pm new file mode 100644 index 000000000..6b5def1a3 --- /dev/null +++ b/FS/FS/access_groupagent.pm @@ -0,0 +1,124 @@ +package FS::access_groupagent; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::access_groupagent - Object methods for access_groupagent records + +=head1 SYNOPSIS + +  use FS::access_groupagent; + +  $record = new FS::access_groupagent \%hash; +  $record = new FS::access_groupagent { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_groupagent object represents an example.  FS::access_groupagent inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item groupagentnum - primary key + +=item groupnum -  + +=item agentnum -  + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_groupagent'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('groupagentnum') +    || $self->ut_number('groupnum') +    || $self->ut_number('agentnum') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/access_right.pm b/FS/FS/access_right.pm new file mode 100644 index 000000000..67200f245 --- /dev/null +++ b/FS/FS/access_right.pm @@ -0,0 +1,127 @@ +package FS::access_right; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::access_right - Object methods for access_right records + +=head1 SYNOPSIS + +  use FS::access_right; + +  $record = new FS::access_right \%hash; +  $record = new FS::access_right { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_right object represents an example.  FS::access_right inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item rightnum - primary key + +=item righttype -  + +=item rightobjnum -  + +=item rightname -  + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_right'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('rightnum') +    || $self->ut_text('righttype') +    || $self->ut_text('rightobjnum') +    || $self->ut_text('rightname') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm new file mode 100644 index 000000000..ca311d3b8 --- /dev/null +++ b/FS/FS/access_user.pm @@ -0,0 +1,167 @@ +package FS::access_user; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); +use FS::m2m_Common; +use FS::access_usergroup; + +@ISA = qw( FS::m2m_Common FS::Record ); + +=head1 NAME + +FS::access_user - Object methods for access_user records + +=head1 SYNOPSIS + +  use FS::access_user; + +  $record = new FS::access_user \%hash; +  $record = new FS::access_user { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_user object represents an example.  FS::access_user inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item usernum - primary key + +=item username -  + +=item _password -  + +=item last - + +=item first - + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_user'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('usernum') +    || $self->ut_text('username') +    || $self->ut_text('_password') +    || $self->ut_text('last') +    || $self->ut_text('first') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=item name + +Returns a name string for this user: "Last, First". + +=cut + +sub name { +  my $self = shift; +  $self->get('last'). ', '. $self->first; +} + +=item access_usergroup + +=cut + +sub access_usergroup { +  my $self = shift; +  qsearch( 'access_usergroup', { 'usernum' => $self->usernum } ); +} + +#=item access_groups +# +#=cut +# +#sub access_groups { +# +#} +# +#=item access_groupnames +# +#=cut +# +#sub access_groupnames { +# +#} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/access_user_pref.pm b/FS/FS/access_user_pref.pm new file mode 100644 index 000000000..ff957f2a1 --- /dev/null +++ b/FS/FS/access_user_pref.pm @@ -0,0 +1,127 @@ +package FS::access_user_pref; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::access_user_pref - Object methods for access_user_pref records + +=head1 SYNOPSIS + +  use FS::access_user_pref; + +  $record = new FS::access_user_pref \%hash; +  $record = new FS::access_user_pref { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_user_pref object represents an example.  FS::access_user_pref inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item prefnum - primary key + +=item usernum -  + +=item prefname -  + +=item prefvalue -  + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_user_pref'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('prefnum') +    || $self->ut_number('usernum') +    || $self->ut_text('prefname') +    || $self->ut_textn('prefvalue') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/access_usergroup.pm b/FS/FS/access_usergroup.pm new file mode 100644 index 000000000..4d8836c15 --- /dev/null +++ b/FS/FS/access_usergroup.pm @@ -0,0 +1,144 @@ +package FS::access_usergroup; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); +use FS::access_user; +use FS::access_group; + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::access_usergroup - Object methods for access_usergroup records + +=head1 SYNOPSIS + +  use FS::access_usergroup; + +  $record = new FS::access_usergroup \%hash; +  $record = new FS::access_usergroup { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::access_usergroup object represents an example.  FS::access_usergroup inherits from +FS::Record.  The following fields are currently supported: + +=over 4 + +=item usergroupnum - primary key + +=item usernum -  + +=item groupnum -  + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example.  To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to.  You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'access_usergroup'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('usergroupnum') +    || $self->ut_number('usernum') +    || $self->ut_number('groupnum') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=item access_user + +=cut + +sub access_user { +  my $self = shift; +  qsearchs( 'access_user', { 'usernum' => $self->usernum } ); +} + +=item access_group + +=cut + +sub access_group { +  my $self = shift; +  qsearchs( 'access_group', { 'groupnum' => $self->groupnum } ); +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/agent_type.pm b/FS/FS/agent_type.pm index 968b3b72e..b28c57285 100644 --- a/FS/FS/agent_type.pm +++ b/FS/FS/agent_type.pm @@ -3,10 +3,11 @@ package FS::agent_type;  use strict;  use vars qw( @ISA );  use FS::Record qw( qsearch ); +use FS::m2m_Common;  use FS::agent;  use FS::type_pkgs; -@ISA = qw( FS::Record ); +@ISA = qw( FS::m2m_Common FS::Record );  =head1 NAME diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index cce028b2c..bcae4d646 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -2463,6 +2463,7 @@ use Data::Dumper;  use MIME::Base64;  sub process_re_X {    my( $method, $job ) = ( shift, shift ); +  warn "process_re_X $method for job $job\n" if $DEBUG;    my $param = thaw(decode_base64(shift));    warn Dumper($param) if $DEBUG; @@ -2478,6 +2479,10 @@ sub process_re_X {  sub re_X {    my($method, $job, %param ) = @_;  #              [ 'begin', 'end', 'agentnum', 'open', 'days', 'newest_percust' ], +  if ( $DEBUG ) { +    warn "re_X $method for job $job with param:\n". +         join( '', map { "  $_ => ". $param{$_}. "\n" } keys %param ); +  }    #some false laziness w/search/cust_bill.html    my $distinct = ''; diff --git a/FS/FS/m2m_Common.pm b/FS/FS/m2m_Common.pm new file mode 100644 index 000000000..fd8700a2d --- /dev/null +++ b/FS/FS/m2m_Common.pm @@ -0,0 +1,110 @@ +package FS::m2m_Common; + +use strict; +use vars qw( @ISA $DEBUG ); +use FS::Schema qw( dbdef ); +use FS::Record qw( qsearch qsearchs ); #dbh ); + +@ISA = qw( FS::Record ); + +$DEBUG = 0; + +=head1 NAME + +FS::m2m_Common - Base class for classes in a many-to-many relationship + +=head1 SYNOPSIS + +use FS::m2m_Common; + +@ISA = qw( FS::m2m_Common ); + +=head1 DESCRIPTION + +FS::m2m_Common is intended as a base class for classes which have a +many-to-many relationship with another table (via a linking table). + +Note: It is currently assumed that the link table contains two fields +named the same as the primary keys of ths base and target tables. + +=head1 METHODS + +=over 4 + +=item process_m2m + +=cut + +sub process_m2m { +  my( $self, %opt ) = @_; + +  my $self_pkey = $self->dbdef_table->primary_key; + +  my $link_table = $self->_load_table($opt{'link_table'}); + +  my $target_table = $self->_load_table($opt{'target_table'}); +  my $target_pkey = dbdef->table($target_table)->primary_key; + +  foreach my $target_obj ( qsearch($target_table, {} ) ) { + +    my $targetnum = $target_obj->$target_pkey(); + +    my $link_obj = qsearchs( $link_table, { +        $self_pkey   => $self->$self_pkey(), +        $target_pkey => $targetnum, +    }); + +    if ( $link_obj && ! $opt{'params'}->{"$target_pkey$targetnum"} ) { + +      my $d_link_obj = $link_obj; #need to save $link_obj for below. +      my $error = $d_link_obj->delete; +      die $error if $error; + +    } elsif ( $opt{'params'}->{"$target_pkey$targetnum"} && ! $link_obj ) { + +      #ok to clobber it now (but bad form nonetheless?) +      #$link_obj = new "FS::$link_table" ( { +      $link_obj = "FS::$link_table"->new( { +        $self_pkey   => $self->$self_pkey(), +        $target_pkey => $targetnum, +      }); +      my $error = $link_obj->insert; +      die $error if $error; +    } + +  } + +  ''; +} + +sub _load_table { +  my( $self, $table ) = @_; +  eval "use FS::$table"; +  die $@ if $@; +  $table; +} + +#=item target_table +# +#=cut +# +#sub target_table { +#  my $self = shift; +#  my $target_table = $self->_target_table; +#  eval "use FS::$target_table"; +#  die $@ if $@; +#  $target_table; +#} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/part_pkg/billoneday.pm b/FS/FS/part_pkg/billoneday.pm deleted file mode 100644 index 8740547a3..000000000 --- a/FS/FS/part_pkg/billoneday.pm +++ /dev/null @@ -1,48 +0,0 @@ -package FS::part_pkg::billoneday; - -use strict; -use vars qw(@ISA %info); -use Time::Local qw(timelocal); -#use FS::Record qw(qsearch qsearchs); -use FS::part_pkg::flat; - -@ISA = qw(FS::part_pkg::flat); - -%info = ( -  'name' => 'charge a full month  every (selectable) billing day', -  'fields' => { -    'setup_fee' => { 'name' => 'Setup fee for this package', -                     'default' => 0, -                   }, -    'recur_fee' => { 'name' => 'Recurring fee for this package', -                     'default' => 0, -			   }, -    'cutoff_day' => { 'name' => 'billing day', -                      'default' => 1, -                    }, - -  }, -  'fieldorder' => [ 'setup_fee', 'recur_fee','cutoff_day'], -  #'setup' => 'what.setup_fee.value', -  #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; $sdate = timelocal(0,0,0,$self->option('cutoff_day'),$mon,$year); \' + what.recur_fee.value', -  'freq' => 'm', -  'weight' => 30, -); - -sub calc_recur { -  my($self, $cust_pkg, $sdate ) = @_; - -  my $mnow = $$sdate; -  my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($mnow) )[0,1,2,3,4,5]; -  my $mstart = timelocal(0,0,0,$self->option('cutoff_day'),$mon,$year); -  my $mend = timelocal(0,0,0,$self->option('cutoff_day'), $mon == 11 ? 0 : $mon+1, $year+($mon==11)); - -  if($mday > $self->option('cutoff_date') and $mstart != $mnow ) { -    $$sdate = timelocal(0,0,0,$self->option('cutoff_day'), $mon == 11 ? 0 : $mon+1,  $year+($mon==11)); -  } -  else{ -    $$sdate = timelocal(0,0,0,$self->option('cutoff_day'), $mon, $year); -  } -  $self->option('recur_fee'); -} -1; diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm index 4425df040..9f8b68918 100644 --- a/FS/FS/payby.pm +++ b/FS/FS/payby.pm @@ -115,7 +115,8 @@ sub cust_payby2longname {  =head1 BUGS -This should eventually be an actual database table. +This should eventually be an actual database table, and all tables that +currently have a char payby field should have a foreign key into here instead.  =head1 SEE ALSO diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm index 191d85604..bdaf79b2f 100644 --- a/FS/FS/svc_domain.pm +++ b/FS/FS/svc_domain.pm @@ -230,7 +230,11 @@ sub delete {      my $error = $domain_record->delete;      if ( $error ) {        $dbh->rollback if $oldAutoCommit; -      return $error; +      return "can't delete DNS entry: ". +             join(' ', map $domain_record->$_(), +                           qw( reczone recaf rectype recdata ) +                 ). +             ":$error";      }    } diff --git a/FS/MANIFEST b/FS/MANIFEST index c309251ff..bd810a8db 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -339,3 +339,4 @@ FS/access_groupagent.pm  t/access_groupagent.t  FS/access_right.pm  t/access_right.t +FS/m2m_Common.pm diff --git a/FS/bin/freeside-addoutsourceuser b/FS/bin/freeside-addoutsourceuser index cad07f1fd..02a435141 100644 --- a/FS/bin/freeside-addoutsourceuser +++ b/FS/bin/freeside-addoutsourceuser @@ -3,6 +3,7 @@  username=$1  domain=$2  password=$3 +realdomain=$4  freeside-adduser -h /usr/local/etc/freeside/htpasswd \                   -s conf.DBI:Pg:dbname=$domain/secrets \ @@ -10,6 +11,5 @@ freeside-adduser -h /usr/local/etc/freeside/htpasswd \                   $username $password 2>/dev/null  [ -e /usr/local/etc/freeside/dbdef.DBI:Pg:dbname=$domain ] \ - || ( freeside-setup -s $username 2>/dev/null; \ -      /home/ivan/freeside/bin/populate-msgcat $username 2>/dev/null ) + || ( freeside-setup -d $realdomain $username 2>/dev/null ) diff --git a/FS/t/AccessRight.t b/FS/t/AccessRight.t new file mode 100644 index 000000000..a96684224 --- /dev/null +++ b/FS/t/AccessRight.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::AccessRight; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_group.t b/FS/t/access_group.t new file mode 100644 index 000000000..be141099b --- /dev/null +++ b/FS/t/access_group.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_group; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_groupagent.t b/FS/t/access_groupagent.t new file mode 100644 index 000000000..aff1f2524 --- /dev/null +++ b/FS/t/access_groupagent.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_groupagent; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_right.t b/FS/t/access_right.t new file mode 100644 index 000000000..66cd362e8 --- /dev/null +++ b/FS/t/access_right.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_right; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_user.t b/FS/t/access_user.t new file mode 100644 index 000000000..cab679d8d --- /dev/null +++ b/FS/t/access_user.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_user; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_user_pref.t b/FS/t/access_user_pref.t new file mode 100644 index 000000000..282209830 --- /dev/null +++ b/FS/t/access_user_pref.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_user_pref; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/access_usergroup.t b/FS/t/access_usergroup.t new file mode 100644 index 000000000..383a7cf9c --- /dev/null +++ b/FS/t/access_usergroup.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::access_usergroup; +$loaded=1; +print "ok 1\n"; diff --git a/htetc/handler.pl b/htetc/handler.pl index e8cd3333b..cbe2dd35d 100644 --- a/htetc/handler.pl +++ b/htetc/handler.pl @@ -179,6 +179,8 @@ sub handler        use FS::inventory_class;        use FS::inventory_item;        use FS::pkg_class; +      use FS::access_user; +      use FS::access_group;        if ( %%%RT_ENABLED%%% ) {          eval ' diff --git a/httemplate/autohandler b/httemplate/autohandler index a3f7eb008..ad0ab8ba6 100644 --- a/httemplate/autohandler +++ b/httemplate/autohandler @@ -9,7 +9,15 @@ if ( UNIVERSAL::can(dbh, 'sprintProfile') ) {    if ( lc($r->content_type) eq 'text/html' ) { -    $profile = '<PRE>'. encode_entities(dbh->sprintProfile()). +    # barely worth it, just in case someone tries to use profiling on a +    # non-RT install +    eval "use Text::Wrapper;"; +    die $@ if $@; + +    my $wrapper = new Text::Wrapper( columns => 80 ); + +    $profile = '<PRE>'. +               encode_entities( $wrapper->wrap( dbh->sprintProfile() ) ).                 #"\n\n". &sprintAutoProfile(). '</PRE>';                 "\n\n".                        '</PRE>';    }  diff --git a/httemplate/browse/access_group.html b/httemplate/browse/access_group.html new file mode 100644 index 000000000..6ba89ea81 --- /dev/null +++ b/httemplate/browse/access_group.html @@ -0,0 +1,33 @@ +<% + +my $html_init =  +  "Internal access groups control access to the back-office interface.<BR><BR>". +  qq!<A HREF="${p}edit/access_group.html"><I>Add an internal access group</I></A><BR><BR>!; + +my $count_query = 'SELECT COUNT(*) FROM access_group'; + +my $link = [ $p.'edit/access_group.html?', 'groupnum' ]; + +%><%= include( 'elements/browse.html', +                 'title'       => 'Internal Access Groups', +                 'menubar'     => [ # 'Main menu' => $p, +                                    'Internal users' => $p.'browse/access_user.html', +                                  ], +                 'html_init'   => $html_init, +                 'name'        => 'internal access groups', +                 'query'       => { 'table'     => 'access_group', +                                    'hashref'   => {}, +                                    'extra_sql' => 'ORDER BY groupname', #?? +                                  }, +                 'count_query' => $count_query, +                 'header'      => [ '#', +                                    'Group name', +                                  ], +                 'fields'      => [ 'groupnum', +                                    'groupname', +                                  ], +                 'links'       => [ $link, +                                    $link, +                                  ], +             ) +%> diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html new file mode 100644 index 000000000..38d5430b1 --- /dev/null +++ b/httemplate/browse/access_user.html @@ -0,0 +1,63 @@ +<% + +my $html_init =  +  "Internal users have access to the back-office interface.  Typically, this is your employees and contractors, but in a VISP setup, you can also add accounts for your reseller's employees.  It is <B>highly recommended</B> to add a <B>separate account for each person</B> rather than using role accounts.<BR><BR>". +  qq!<A HREF="${p}edit/access_user.html"><I>Add an internal user</I></A><BR><BR>!; + +#false laziness w/agent_type.cgi +my $groups_sub = sub { +  my $access_user = shift; + +  [ map { +          my $access_usergroup = $_; +          my $access_group = $access_usergroup->access_group; +          [ +            { +              'data'  => $access_group->groupname, +              'align' => 'left', +              'link'  => +                $p. 'edit/access_group.html?'. $access_usergroup->groupnum, +            }, +          ]; +        } +    grep { $_->access_group # and ! $_->access_group->disabled +         } +    $access_user->access_usergroup, + +  ]; + +}; + +my $count_query = 'SELECT COUNT(*) FROM access_user'; + +my $link = [ $p.'edit/access_user.html?', 'usernum' ]; + +%><%= include( 'elements/browse.html', +                 'title'       => 'Internal Users', +                 'menubar'     => [ #'Main menu' => $p, +                                    'Internal access groups' => $p.'browse/access_group.html', +                                  ], +                 'html_init'   => $html_init, +                 'name'        => 'internal users', +                 'query'       => { 'table'     => 'access_user', +                                    'hashref'   => {}, +                                    'extra_sql' => 'ORDER BY last, first', +                                  }, +                 'count_query' => $count_query, +                 'header'      => [ '#', +                                    'Username', +                                    'Full name', +                                    'Groups' +                                  ], +                 'fields'      => [ 'usernum', +                                    'username', +                                    'name', # sub { shift->name }, +                                    $groups_sub, +                                  ], +                 'links'       => [ $link, +                                    $link, +                                    $link, +                                    '' +                                  ], +             ) +%> diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi index 2e1bdad42..a5ffb1048 100755 --- a/httemplate/browse/agent_type.cgi +++ b/httemplate/browse/agent_type.cgi @@ -1,60 +1,62 @@ -<!-- mason kludge --> -<%= include("/elements/header.html","Agent Type Listing", menubar( -  'Main Menu' => $p, -  'Agents'    => $p. 'browse/agent.cgi', -)) %> -Agent types define groups of packages that you can then assign to particular -agents.<BR><BR> -<A HREF="<%= $p %>edit/agent_type.cgi"><I>Add a new agent type</I></A><BR><BR> +<% -<%= table() %> -<TR> -  <TH COLSPAN=2>Agent Type</TH> -  <TH COLSPAN=2>Packages</TH> -</TR> +my $html_init =  +  'Agent types define groups of packages that you can then assign to'. +  ' particular agents.<BR><BR>'. +  qq!<A HREF="${p}edit/agent_type.cgi"><I>Add a new agent type</I></A><BR><BR>!; -<%  -foreach my $agent_type ( sort {  -  $a->getfield('typenum') <=> $b->getfield('typenum') -} qsearch('agent_type',{}) ) { -  my $hashref = $agent_type->hashref; -  #more efficient to do this with SQL... -  my @type_pkgs = grep { $_->part_pkg and ! $_->part_pkg->disabled } -                       qsearch('type_pkgs',{'typenum'=> $hashref->{typenum} }); -  my $rowspan = scalar(@type_pkgs); -  $rowspan = int($rowspan/2+0.5) ; -  print <<END; -      <TR> -        <TD ROWSPAN=$rowspan><A HREF="${p}edit/agent_type.cgi?$hashref->{typenum}"> -          $hashref->{typenum} -        </A></TD> -        <TD ROWSPAN=$rowspan><A HREF="${p}edit/agent_type.cgi?$hashref->{typenum}">$hashref->{atype}</A></TD> -END +my $count_query = 'SELECT COUNT(*) FROM agent_type'; -  my($type_pkgs); -  my($tdcount) = -1 ; -  foreach $type_pkgs ( @type_pkgs ) { -    my($pkgpart)=$type_pkgs->getfield('pkgpart'); -    my($part_pkg) = qsearchs('part_pkg',{'pkgpart'=> $pkgpart }); -    print qq!<TR>! if ($tdcount == 0) ; -    $tdcount = 0 if ($tdcount == -1) ; -    print qq!<TD><A HREF="${p}edit/part_pkg.cgi?$pkgpart">!, -          $part_pkg->getfield('pkg'),"</A></TD>"; -    $tdcount ++ ; -    if ($tdcount == 2) -    { -	print qq!</TR>\n! ; -	$tdcount = 0 ; -    } -  } +#false laziness w/access_user.html +my $packages_sub = sub { +  my $agent_type = shift; -  print "</TR>"; -} +  [ map  { +           my $type_pkgs = $_; +           my $part_pkg = $type_pkgs->part_pkg; +           [ +             { +               'data'  => $part_pkg->pkg. ' - '. $part_pkg->comment, +               'align' => 'left', +               'link'  => $p. 'edit/part_pkg.cgi?'. $type_pkgs->pkgpart, +             }, +           ]; +         } +    #sort { +    #     } +    grep { +           $_->part_pkg and ! $_->part_pkg->disabled +         } +    $agent_type->type_pkgs #XXX the method should order itself by something +  ]; -print <<END; -    </TABLE> -  </BODY> -</HTML> -END +}; +my $link = [ $p.'edit/agent_type.cgi?', 'typenum' ]; + +%><%= include( 'elements/browse.html', +                 'title'   => 'Agent Types', +                 'menubar'     => [ #'Main menu' => $p, +                                    'Agents'    =>"${p}browse/agent.cgi", +                                  ], +                 'html_init'   => $html_init, +                 'name'        => 'agent types', +                 'query'       => { 'table'     => 'agent_type', +                                    'hashref'   => {}, +                                    'extra_sql' => 'ORDER BY typenum', # 'ORDER BY atype', +                                  }, +                 'count_query' => $count_query, +                 'header'      => [ '#', +                                    'Agent Type', +                                    'Packages', +                                  ], +                 'fields'      => [ 'typenum', +                                    'atype', +                                    $packages_sub, +                                  ], +                 'links'       => [ $link, +                                    $link, +                                    '', +                                  ], +             )  %> diff --git a/httemplate/browse/cust_main_county.cgi b/httemplate/browse/cust_main_county.cgi index 1e0e0880c..9e3feb8f3 100755 --- a/httemplate/browse/cust_main_county.cgi +++ b/httemplate/browse/cust_main_county.cgi @@ -1,33 +1,34 @@ -<!-- mason kludge --> -<% +<%= include('/elements/header.html', "Tax Rate Listing", menubar( +  'Edit tax rates' => $p. "edit/cust_main_county.cgi", +)) %> + +    Click on <u>expand country</u> to specify a country's tax rates by state. +    <BR>Click on <u>expand state</u> to specify a state's tax rates by county. +<%  my $conf = new FS::Conf;  my $enable_taxclasses = $conf->exists('enable_taxclasses'); -print header("Tax Rate Listing", menubar( -  'Main Menu' => $p, -  'Edit tax rates' => $p. "edit/cust_main_county.cgi", -)),<<END; -    Click on <u>expand country</u> to specify a country's tax rates by state. -    <BR>Click on <u>expand state</u> to specify a state's tax rates by county. -END +if ( $enable_taxclasses ) { %> -if ( $enable_taxclasses ) { -  print '<BR>Click on <u>expand taxclasses</u> to specify tax classes'; -} +  <BR>Click on <u>expand taxclasses</u> to specify tax classes -print '<BR><BR>'. &table(). <<END; -      <TR> -        <TH><FONT SIZE=-1>Country</FONT></TH> -        <TH><FONT SIZE=-1>State</FONT></TH> -        <TH>County</TH> -        <TH>Taxclass<BR><FONT SIZE=-1>(per-package classification)</FONT></TH> -        <TH>Tax name<BR><FONT SIZE=-1>(printed on invoices)</FONT></TH> -        <TH><FONT SIZE=-1>Tax</FONT></TH> -        <TH><FONT SIZE=-1>Exemption</TH> -      </TR> -END +<% } %> + +<BR><BR> +<%= table() %> + +  <TR> +    <TH><FONT SIZE=-1>Country</FONT></TH> +    <TH><FONT SIZE=-1>State</FONT></TH> +    <TH>County</TH> +    <TH>Taxclass<BR><FONT SIZE=-1>(per-package classification)</FONT></TH> +    <TH>Tax name<BR><FONT SIZE=-1>(printed on invoices)</FONT></TH> +    <TH><FONT SIZE=-1>Tax</FONT></TH> +    <TH><FONT SIZE=-1>Exemption</TH> +  </TR> +<%  my @regions = sort {    $a->country  cmp $b->country                       or $a->state    cmp $b->state                       or $a->county   cmp $b->county @@ -39,10 +40,12 @@ my $sup=0;  for ( my $i=0; $i<@regions; $i++ ) {     my $cust_main_county = $regions[$i];    my $hashref = $cust_main_county->hashref; -  print <<END; + +  %>        <TR> -        <TD BGCOLOR="#ffffff">$hashref->{country}</TD> -END +        <TD BGCOLOR="#ffffff"><%= $hashref->{country} %></TD> + +  <%    my $j;    if ( $sup ) { @@ -74,69 +77,73 @@ END        $j = 1;      } -    print "<TD ROWSPAN=$j", $hashref->{state} +    %> + +    <TD ROWSPAN=<%= $j %><%= +      $hashref->{state}          ? ' BGCOLOR="#ffffff">'. $hashref->{state}          : qq! BGCOLOR="#cccccc">(ALL) <FONT SIZE=-1>!.            qq!<A HREF="${p}edit/cust_main_county-expand.cgi?!. $hashref->{taxnum}. -          qq!">expand country</A></FONT>!; - -    print qq! <FONT SIZE=-1><A HREF="${p}edit/process/cust_main_county-collapse.cgi?!. $hashref->{taxnum}. qq!">collapse state</A></FONT>! if $j>1; - -    print "</TD>"; -  } - -#  $sup=$newsup; - -  print "<TD"; -  if ( $hashref->{county} ) { -    print ' BGCOLOR="#ffffff">'. $hashref->{county}; -  } else { -    print ' BGCOLOR="#cccccc">(ALL)'; -    if ( $hashref->{state} ) { -      print qq!<FONT SIZE=-1>!. -          qq!<A HREF="${p}edit/cust_main_county-expand.cgi?!. $hashref->{taxnum}. -          qq!">expand state</A></FONT>!; -    } -  } -  print "</TD>"; - -  print "<TD"; -  if ( $hashref->{taxclass} ) { -    print ' BGCOLOR="#ffffff">'. $hashref->{taxclass}; -  } else { -    print ' BGCOLOR="#cccccc">(ALL)'; -    if ( $enable_taxclasses ) { -      print qq!<FONT SIZE=-1>!. -            qq!<A HREF="${p}edit/cust_main_county-expand.cgi?taxclass!. -            $hashref->{taxnum}. qq!">expand taxclasses</A></FONT>!; -    } - -  } -  print "</TD>"; - -  print "<TD"; -  if ( $hashref->{taxname} ) { -    print ' BGCOLOR="#ffffff">'. $hashref->{taxname}; -  } else { -    print ' BGCOLOR="#cccccc">Tax'; -  } -  print "</TD>"; - -  print "<TD BGCOLOR=\"#ffffff\">$hashref->{tax}%</TD>". -        '<TD BGCOLOR="#ffffff">'; -  print '$'. sprintf("%.2f", $hashref->{exempt_amount} ). -        ' per month<BR>' -    if $hashref->{exempt_amount} > 0; -  print 'Setup fee<BR>' if $hashref->{setuptax} =~ /^Y$/i; -  print 'Recurring fee<BR>' if $hashref->{recurtax} =~ /^Y$/i; -  print '</TD></TR>'; - -} - -print <<END; -    </TABLE> -  </BODY> -</HTML> -END - -%> +          qq!">expand country</A></FONT>! +      %> +      <% if ( $j>1 ) { %> +        <FONT SIZE=-1><A HREF="<%= $p %>edit/process/cust_main_county-collapse.cgi?<%= $hashref->{taxnum} %>">collapse state</A></FONT> +      <% } %> + +    </TD> +  <% } %> + +<% #  $sup=$newsup; %> + +    <TD<% if ( $hashref->{county} ) { +            %> BGCOLOR="#ffffff"><%= $hashref->{county} %> +       <% } else { +            %> BGCOLOR="#cccccc">(ALL) +            <% if ( $hashref->{state} ) { %> +                 <FONT SIZE=-1><A HREF="<%= $p %>edit/cust_main_county-expand.cgi?<%= $hashref->{taxnum} %>">expand state</A></FONT> +            <% } %> +       <% } %> +    </TD> + +    <TD<% if ( $hashref->{taxclass} ) { +            %> BGCOLOR="#ffffff"><%= $hashref->{taxclass} %> +       <% } else { +            %> BGCOLOR="#cccccc">(ALL) +            <% if ( $enable_taxclasses ) { %> +                 <FONT SIZE=-1><A HREF="<%= $p %>edit/cust_main_county-expand.cgi?taxclass<%= $hashref->{taxnum} %>">expand taxclasses</A></FONT> +            <% } %> +       <% } %> +    </TD> + +    <TD<% if ( $hashref->{taxname} ) { +            %> BGCOLOR="#ffffff"><%= $hashref->{taxname} %> +       <% } else { +            %> BGCOLOR="#cccccc">Tax +       <% } %> +    </TD> + +    <TD BGCOLOR="#ffffff"><%= $hashref->{tax} %>%</TD> + +    <TD BGCOLOR="#ffffff"> + +      <% if ( $hashref->{exempt_amount} > 0 ) { %> +        $<%= sprintf("%.2f", $hashref->{exempt_amount} ) %> per month<BR> +      <% } %> + +      <% if ( $hashref->{setuptax} =~ /^Y$/i ) { %> +        Setup fee<BR> +      <% } %> +       +      <% if ( $hashref->{recurtax} =~ /^Y$/i ) { %> +        Recurring fee<BR> +      <% } %> + +    </TD> + +  </TR> + +<% } %> + +</TABLE> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/browse/msgcat.cgi b/httemplate/browse/msgcat.cgi index d4adf9f1a..318ebfdff 100755 --- a/httemplate/browse/msgcat.cgi +++ b/httemplate/browse/msgcat.cgi @@ -1,10 +1,6 @@ -<!-- mason kludge --> -<% - -print header("View Message catalog", menubar( -  'Main Menu' => $p, +<%= include('/elements/header.html', "View Message catalog", menubar(    'Edit message catalog' => $p. "edit/msgcat.cgi", -)), '<BR>'; +)) %><%  my $widget = new HTML::Widgets::SelectLayers(    'selected_layer' => 'en_US', @@ -38,13 +34,7 @@ my $widget = new HTML::Widgets::SelectLayers(    },  ); - -print $widget->html; - -print <<END; -    </TABLE> -  </BODY> -</HTML> -END -  %> + +<%=  $widget->html %> +<%= include('/elements/footer.html') %> diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 0afa54750..41d86358c 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -11,8 +11,8 @@ my $select = '*';  my $orderby = 'pkgpart';  if ( $cgi->param('active') ) { -  $orderby = 'num_active'; - +  $orderby = 'num_active DESC'; +}    $select = "      *, @@ -33,13 +33,13 @@ if ( $cgi->param('active') ) {    "; -} +#}  my $conf = new FS::Conf;  my $taxclasses = $conf->exists('enable_taxclasses');  my $html_init; -unless ( $cgi->param('active') ) { +#unless ( $cgi->param('active') ) {    $html_init = qq!      One or more service definitions are grouped together into a package       definition and given pricing information.  Customers purchase packages @@ -47,7 +47,7 @@ unless ( $cgi->param('active') ) {      <A HREF="${p}edit/part_pkg.cgi"><I>Add a new package definition</I></A>      <BR><BR>    !; -} +#}  my $posttotal;  if ( $cgi->param('showdisabled') ) { @@ -85,7 +85,7 @@ unless ( 0 ) { #already showing only one class or something?    $align .= 'l';  } -if ( $cgi->param('active') ) { +#if ( $cgi->param('active') ) {    push @header, 'Customer<BR>packages';    my %col = (      'active'      => '00CC00', @@ -117,7 +117,7 @@ if ( $cgi->param('active') ) {                              } (qw( active suspended cancelled ))                        ]; };    $align .= 'r'; -} +#}  push @header, 'Frequency';  push @fields, sub { shift->freq_pretty; }; diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html new file mode 100644 index 000000000..11b8df7bc --- /dev/null +++ b/httemplate/edit/access_group.html @@ -0,0 +1,10 @@ +<%= include( 'elements/edit.html', +                 'name'   => 'Internal Access Group', +                 'table'  => 'access_group', +                 'labels' => {  +                               'groupnum'   => 'Group number', +                               'groupname'  => 'Group name', +                             }, +                 'viewall_dir' => 'browse', +           ) +%> diff --git a/httemplate/edit/access_user.html b/httemplate/edit/access_user.html new file mode 100644 index 000000000..2b19dbf7b --- /dev/null +++ b/httemplate/edit/access_user.html @@ -0,0 +1,37 @@ +<%= include( 'elements/edit.html', +                 'name'   => 'Internal User', +                 'table'  => 'access_user', +                 'fields' => [ +                               'username', +                               { field=>'_password', type=>'password' }, +                               'last', +                               'first', +                             ], +                 'labels' => {  +                               'usernum'   => 'User number', +                               'username'  => 'Username', +                               '_password' => 'Password', +                               'last'      => 'Last name', +                               'first'     => 'First name', +                             }, +                 'viewall_dir' => 'browse', +                 'html_bottom' => +                   sub { +                     my $access_user = shift; + +                     '<BR>Internal Access Groups<BR>'. +                     ntable("#cccccc",2). +                     '<TR><TD>'. +                     include( '/elements/checkboxes-table.html', +                                'source_obj'   => $access_user, +                                'link_table'   => 'access_usergroup', +                                'target_table' => 'access_group', +                                'name_col'     => 'groupname', +                                'target_link'  => $p.'edit/access_group.html?', +                                #'disable-able' => 1, +                            ). +                     '</TR></TD></TABLE>' +                     ; +                   }, +           ) +%> diff --git a/httemplate/edit/agent_type.cgi b/httemplate/edit/agent_type.cgi index 944ddd0d0..f5afd3a96 100755 --- a/httemplate/edit/agent_type.cgi +++ b/httemplate/edit/agent_type.cgi @@ -14,9 +14,7 @@ if ( $cgi->param('error') ) {  }  my $action = $agent_type->typenum ? 'Edit' : 'Add'; -%> - -<%= include("/elements/header.html","$action Agent Type", menubar( +%><%= include("/elements/header.html","$action Agent Type", menubar(    'Main Menu' => "$p",    'View all agent types' => "${p}browse/agent_type.cgi",  )) @@ -29,47 +27,29 @@ my $action = $agent_type->typenum ? 'Edit' : 'Add';  <FORM ACTION="<%= popurl(1) %>process/agent_type.cgi" METHOD=POST>  <INPUT TYPE="hidden" NAME="typenum" VALUE="<%= $agent_type->typenum %>">  Agent Type #<%= $agent_type->typenum || "(NEW)" %> -<BR><BR> +<BR>  Agent Type  <INPUT TYPE="text" NAME="atype" SIZE=32 VALUE="<%= $agent_type->atype %>">  <BR><BR>  Select which packages agents of this type may sell to customers<BR> - -<% foreach my $part_pkg ( -     qsearch({ 'table'     => 'part_pkg', -               'hashref'   => { 'disabled' => '' }, -               'select'    => 'part_pkg.*', -               'addl_from' => 'LEFT JOIN type_pkgs USING ( pkgpart )', -               'extra_sql' => ( $agent_type->typenum -                                  ? 'OR typenum = '. $agent_type->typenum -                                  : '' -                              ), -            }) -   ) { +<%= ntable("#cccccc", 2) %><TR><TD> +<%= include('/elements/checkboxes-table.html', +              'source_obj'    => $agent_type, +              'link_table'    => 'type_pkgs', +              'target_table'  => 'part_pkg', +              'name_callback' => sub { $_[0]->pkg. ' - '. $_[0]->comment; }, +              'target_link'   => $p.'edit/part_pkg.cgi?', +              'disable-able'  => 1, + +           )  %> - -  <BR> -  <INPUT TYPE="checkbox" NAME="pkgpart<%= $part_pkg->pkgpart %>" <%= -        qsearchs('type_pkgs',{ -          'typenum' => $agent_type->typenum, -          'pkgpart' => $part_pkg->pkgpart, -        }) -          ? 'CHECKED ' -          : '' -  %> VALUE="ON"> - -  <A HREF="<%= $p %>edit/part_pkg.cgi?<%= $part_pkg->pkgpart %>"><%= $part_pkg->pkgpart %>:  -  <%= $part_pkg->pkg %> - <%= $part_pkg->comment %></A> -  <%= $part_pkg->disabled =~ /^Y/i ? ' (DISABLED)' : '' %> - -<% } %> - -<BR><BR> +</TD></TR></TABLE> +<BR>  <INPUT TYPE="submit" VALUE="<%= $agent_type->typenum ? "Apply changes" : "Add agent type" %>">      </FORM> -  </BODY> -</HTML> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/cust_bill_pay.cgi b/httemplate/edit/cust_bill_pay.cgi index 24bce308a..9d3bdd8cb 100755 --- a/httemplate/edit/cust_bill_pay.cgi +++ b/httemplate/edit/cust_bill_pay.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my($paynum, $amount, $invnum); @@ -18,78 +17,76 @@ my $otaker = getotaker;  my $p1 = popurl(1); -print header("Apply Payment", ''); -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT><BR><BR>" -  if $cgi->param('error'); -print <<END; -    <FORM ACTION="${p1}process/cust_bill_pay.cgi" METHOD=POST> -END +%><%= header("Apply Payment", '') %> +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +  <BR><BR> +<% } %> + +<FORM ACTION="<%= $p1 %>process/cust_bill_pay.cgi" METHOD=POST> + +<%  my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } );  die "payment $paynum not found!" unless $cust_pay;  my $unapplied = $cust_pay->unapplied; +%> + +Payment #<B><%= $paynum %></B> +<INPUT TYPE="hidden" NAME="paynum" VALUE="<%= $paynum %>"> -print "Payment # <B>$paynum</B>". -      qq!<INPUT TYPE="hidden" NAME="paynum" VALUE="$paynum">!. -      '<BR>Date: <B>'. time2str("%D", $cust_pay->_date). '</B>'. -      '<BR>Amount: $<B>'. $cust_pay->paid. '</B>'. -      "<BR>Unapplied amount: \$<B>$unapplied</B>" -      ; +<BR>Date: <B><%= time2str("%D", $cust_pay->_date) %></B> +<BR>Amount: $<B><%= $cust_pay->paid %></B> + +<BR>Unapplied amount: $<B><%= $unapplied %></B> + +<%  my @cust_bill = grep $_->owed != 0,                  qsearch('cust_bill', { 'custnum' => $cust_pay->custnum } ); -print <<END; +%> +  <SCRIPT>  function changed(what) {    cust_bill = what.options[what.selectedIndex].value; -END -foreach my $cust_bill ( @cust_bill ) { +<% foreach my $cust_bill ( @cust_bill ) {    my $invnum = $cust_bill->invnum;    my $changeto = $cust_bill->owed < $unapplied                     ? $cust_bill->owed                      : $unapplied; -  print <<END; +%>    if ( cust_bill == $invnum ) { -    what.form.amount.value = "$changeto"; +    what.form.amount.value = "<%= $changeto %>";    } -END -} +<% } %> -print <<END;    if ( cust_bill == "Refund" ) { -    what.form.amount.value = "$unapplied"; +    what.form.amount.value = "<%= $unapplied %>";    }  }  </SCRIPT> -END - -print qq!<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)">!, -      '<OPTION VALUE="">'; -foreach my $cust_bill ( @cust_bill ) { -  print '<OPTION'. ( $cust_bill->invnum eq $invnum ? ' SELECTED' : '' ). -        ' VALUE="'. $cust_bill->invnum. '">'. $cust_bill->invnum. -        ' -  '. time2str("%D",$cust_bill->_date). -        ' - $'. $cust_bill->owed; -} -print qq!<OPTION VALUE="Refund">Refund!; -print "</SELECT>"; -print qq!<BR>Amount \$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8>!; +<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)"> +<OPTION VALUE=""> + +<% foreach my $cust_bill ( @cust_bill ) { %> + +  <OPTION<%= $cust_bill->invnum eq $invnum ? ' SELECTED' : '' %> VALUE="<%= $cust_bill->invnum %>"><%= $cust_bill->invnum %> - <%= time2str("%D", $cust_bill->_date) %> - $<%= $cust_bill->owed %> + +<% } %> + +<OPTION VALUE="Refund">Refund +</SELECT> + +<BR>Amount $<INPUT TYPE="text" NAME="amount" VALUE="<%= $amount %>" SIZE=8 MAXLENGTH=8> -print <<END;  <BR> -<INPUT TYPE="submit" VALUE="Apply"> -END +<CENTER><INPUT TYPE="submit" VALUE="Apply"></CENTER> -print <<END; +</FORM> -    </FORM> -  </BODY> +</BODY>  </HTML> -END - -%> diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi index aae0df2fc..946b1087b 100755 --- a/httemplate/edit/cust_credit.cgi +++ b/httemplate/edit/cust_credit.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my $conf = new FS::Conf; @@ -25,39 +24,57 @@ my $otaker = getotaker;  my $p1 = popurl(1); -print header("Post Credit", ''); -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT>" -  if $cgi->param('error'); -print <<END, small_custview($custnum, $conf->config('countrydefault')); -    <FORM ACTION="${p1}process/cust_credit.cgi" METHOD=POST> -    <INPUT TYPE="hidden" NAME="crednum" VALUE=""> -    <INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum"> -    <INPUT TYPE="hidden" NAME="paybatch" VALUE=""> -    <INPUT TYPE="hidden" NAME="_date" VALUE="$_date"> -    <INPUT TYPE="hidden" NAME="credited" VALUE=""> -    <INPUT TYPE="hidden" NAME="otaker" VALUE="$otaker"> -END - -print '<BR><BR>Credit'. ntable("#cccccc", 2). -      '<TR><TD ALIGN="right">Date</TD><TD BGCOLOR="#ffffff">'. -      time2str("%D",$_date).  '</TD></TR>'; - -print qq!<TR><TD ALIGN="right">Amount</TD><TD BGCOLOR="#ffffff">\$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8></TD></TR>!; +%> + +<%= header("Post Credit", '') %> + +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +  <BR><BR> +<% } %> + +<!-- <%= small_custview($custnum, $conf->config('countrydefault')) %> --> + +<FORM ACTION="<%= $p1 %>process/cust_credit.cgi" METHOD=POST> +<INPUT TYPE="hidden" NAME="crednum" VALUE=""> +<INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>"> +<INPUT TYPE="hidden" NAME="paybatch" VALUE=""> +<INPUT TYPE="hidden" NAME="_date" VALUE="<%= $_date %>"> +<INPUT TYPE="hidden" NAME="credited" VALUE=""> +<INPUT TYPE="hidden" NAME="otaker" VALUE="<%= $otaker %>"> + +Credit + +<%= ntable("#cccccc", 2) %> +  <TR> +    <TD ALIGN="right">Date</TD> +    <TD BGCOLOR="#ffffff"><%= time2str("%D",$_date) %></TD> +  </TR> + +  <TR> +    <TD ALIGN="right">Amount</TD> +    <TD BGCOLOR="#ffffff">$<INPUT TYPE="text" NAME="amount" VALUE="<%= $amount %>" SIZE=8 MAXLENGTH=8></TD> +  </TR> + +<%  #print qq! <INPUT TYPE="checkbox" NAME="refund" VALUE="$refund">Also post refund!; +%> -print qq!<TR><TD ALIGN="right">Reason</TD><TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="reason" VALUE="$reason"></TD></TR>!; +  <TR> +    <TD ALIGN="right">Reason</TD> +    <TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="reason" VALUE="<%= $reason %>" SIZE=32></TD> +  </TR> -print qq!<TR><TD ALIGN="right">Auto-apply<BR>to invoices</TD><TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD>!; +  <TR> +    <TD ALIGN="right">Auto-apply<BR>to invoices</TD> +    <TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD> +  </TR> -print <<END;  </TABLE> +  <BR> -<INPUT TYPE="submit" VALUE="Post credit"> +<CENTER><INPUT TYPE="submit" VALUE="Post credit"></CENTER>      </FORM>    </BODY>  </HTML> -END - -%> diff --git a/httemplate/edit/cust_credit_bill.cgi b/httemplate/edit/cust_credit_bill.cgi index 1a97e1312..409ea3c25 100755 --- a/httemplate/edit/cust_credit_bill.cgi +++ b/httemplate/edit/cust_credit_bill.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my($crednum, $amount, $invnum); @@ -23,79 +22,78 @@ my $otaker = getotaker;  my $p1 = popurl(1); -print header("Apply Credit", ''); -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT><BR><BR>" -  if $cgi->param('error'); -print <<END; -    <FORM ACTION="${p1}process/cust_credit_bill.cgi" METHOD=POST> -END +%><%=  header("Apply Credit", '') %> +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +  <BR><BR> +<% } %> + +<FORM ACTION="<%= $p1 %>process/cust_credit_bill.cgi" METHOD=POST> + +<%  my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } );  die "credit $crednum not found!" unless $cust_credit;  my $credited = $cust_credit->credited; +%> + +Credit #<B><%= $crednum %></B> +<INPUT TYPE="hidden" NAME="crednum" VALUE="<%= $crednum %>"> + +<BR>Date: <B><%= time2str("%D", $cust_credit->_date) %></B> -print "Credit # <B>$crednum</B>". -      qq!<INPUT TYPE="hidden" NAME="crednum" VALUE="$crednum">!. -      '<BR>Date: <B>'. time2str("%D", $cust_credit->_date). '</B>'. -      '<BR>Amount: $<B>'. $cust_credit->amount. '</B>'. -      "<BR>Unapplied amount: \$<B>$credited</B>". -      '<BR>Reason: <B>'. $cust_credit->reason. '</B>' -      ; +<BR>Amount: $<B><%= $cust_credit->amount %></B> +<BR>Unapplied amount: $<B><%= $credited %></B> + +<BR>Reason: <B><%= $cust_credit->reason %></B> + +<%  my @cust_bill = grep $_->owed != 0,                  qsearch('cust_bill', { 'custnum' => $cust_credit->custnum } ); -print <<END; +%> +  <SCRIPT>  function changed(what) {    cust_bill = what.options[what.selectedIndex].value; -END -foreach my $cust_bill ( @cust_bill ) { +<% foreach my $cust_bill ( @cust_bill ) {    my $invnum = $cust_bill->invnum;    my $changeto = $cust_bill->owed < $cust_credit->credited                     ? $cust_bill->owed                      : $cust_credit->credited; -  print <<END; +%>    if ( cust_bill == $invnum ) { -    what.form.amount.value = "$changeto"; +    what.form.amount.value = "<%= $changeto %>";    } -END -} +<% } %> -print <<END;    if ( cust_bill == "Refund" ) { -    what.form.amount.value = "$credited"; +    what.form.amount.value = "<%= $credited %>";    }  }  </SCRIPT> -END - -print qq!<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)">!, -      '<OPTION VALUE="">'; -foreach my $cust_bill ( @cust_bill ) { -  print '<OPTION'. ( $cust_bill->invnum eq $invnum ? ' SELECTED' : '' ). -        ' VALUE="'. $cust_bill->invnum. '">'. $cust_bill->invnum. -        ' -  '. time2str("%D",$cust_bill->_date). -        ' - $'. $cust_bill->owed; -} -print qq!<OPTION VALUE="Refund">Refund!; -print "</SELECT>"; -print qq!<BR>Amount \$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8>!; +<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)"> +<OPTION VALUE=""> + +<% foreach my $cust_bill ( @cust_bill ) { %> + +<OPTION<%= $cust_bill->invnum eq $invnum ? ' SELECTED' : '' %> VALUE="<%= $cust_bill->invnum %>"><%= $cust_bill->invnum %> - <%= time2str("%D",$cust_bill->_date) %> - $<%= $cust_bill->owed %> + +<% } %> + +<OPTION VALUE="Refund">Refund +</SELECT> + +<BR>Amount $<INPUT TYPE="text" NAME="amount" VALUE="<%= $amount %>" SIZE=8 MAXLENGTH=8> -print <<END;  <BR> -<INPUT TYPE="submit" VALUE="Apply"> -END +<CENTER><INPUT TYPE="submit" VALUE="Apply"></CENTER> -print <<END; +</FORM> -    </FORM> -  </BODY> +</BODY>  </HTML> -END - -%> diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 80fec9359..bb2a8618e 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -397,49 +397,66 @@ unless ( $custnum ) {    if ( @part_pkg ) { -#    print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"), -#apiabuse & undesirable wrapping -    print "<BR>First package", &ntable("#cccccc"), -          qq!<TR><TD COLSPAN=2><SELECT NAME="pkgpart_svcpart">!; - -    print qq!<OPTION VALUE="">(none)!; - -    foreach my $part_pkg ( @part_pkg ) { -      print qq!<OPTION VALUE="!, -#              $part_pkg->pkgpart. "_". $pkgpart{ $part_pkg->pkgpart }, '"'; -              $part_pkg->pkgpart. "_". $part_pkg->svcpart('svc_acct'), '"'; -      print " SELECTED" if $saved_pkgpart && ( $part_pkg->pkgpart == $saved_pkgpart ); -      print ">", $part_pkg->pkg, " - ", $part_pkg->comment; -    } -    print "</SELECT></TD></TR>"; - -    #false laziness: (mostly) copied from edit/svc_acct.cgi -    #$ulen = $svc_acct->dbdef_table->column('username')->length; -    my $ulen = dbdef->table('svc_acct')->column('username')->length; -    my $ulen2 = $ulen+2; -    my $passwordmax = $conf->config('passwordmax') || 8; -    my $pmax2 = $passwordmax + 2; -    print <<END; -<TR><TD ALIGN="right">Username</TD> -<TD><INPUT TYPE="text" NAME="username" VALUE="$username" SIZE=$ulen2 MAXLENGTH=$ulen></TD></TR> -<TR><TD ALIGN="right">Password</TD> -<TD><INPUT TYPE="text" NAME="_password" VALUE="$password" SIZE=$pmax2 MAXLENGTH=$passwordmax> -(blank to generate)</TD></TR> -END - -    print '<TR><TD ALIGN="right">Access number</TD><TD>' -          . -          &FS::svc_acct_pop::popselector($popnum). -          '</TD></TR></TABLE>' -          ; -  } -} +    #    print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"), +    #apiabuse & undesirable wrapping + +    %> +    <BR>First package +    <%= ntable("#cccccc") %> +     +      <TR> +        <TD COLSPAN=2> +          <SELECT NAME="pkgpart_svcpart"> +            <OPTION VALUE="">(none) +     +            <% foreach my $part_pkg ( @part_pkg ) { %> +     +              <OPTION VALUE="<%= $part_pkg->pkgpart. "_". $part_pkg->svcpart('svc_acct') %>"<%= ( $saved_pkgpart && $part_pkg->pkgpart == $saved_pkgpart ) ? ' SELECTED' : '' %>><%= $part_pkg->pkg. " - ". $part_pkg->comment %> +     +            <% } %> +          </SELECT> +        </TD> +      </TR> +     +      <%  +        #false laziness: (mostly) copied from edit/svc_acct.cgi +        #$ulen = $svc_acct->dbdef_table->column('username')->length; +        my $ulen = dbdef->table('svc_acct')->column('username')->length; +        my $ulen2 = $ulen+2; +        my $passwordmax = $conf->config('passwordmax') || 8; +        my $pmax2 = $passwordmax + 2; +      %> +     +      <TR> +        <TD ALIGN="right">Username</TD> +        <TD> +          <INPUT TYPE="text" NAME="username" VALUE="<%= $username %>" SIZE=<%= $ulen2 %> MAXLENGTH=<%= $ulen %>> +        </TD> +      </TR> +     +      <TR> +        <TD ALIGN="right">Password</TD> +        <TD> +          <INPUT TYPE="text" NAME="_password" VALUE="<%= $password %>" SIZE=<%= $pmax2 %> MAXLENGTH=<%= $passwordmax %>> +          (blank to generate) +        </TD> +      </TR> +     +      <TR> +        <TD ALIGN="right">Access number</TD> +        <TD><%= FS::svc_acct_pop::popselector($popnum) %></TD> +      </TR> +    </TABLE> +     +  <% } %> + +<% } %> -my $otaker = $cust_main->otaker; -print qq!<INPUT TYPE="hidden" NAME="otaker" VALUE="$otaker">!, -      qq!<BR><INPUT TYPE="submit" NAME="submit" VALUE="!, -      $custnum ?  "Apply Changes" : "Add Customer", qq!"><BR>!, -      "</FORM></DIV></BODY></HTML>", -; +<INPUT TYPE="hidden" NAME="otaker" VALUE="<%= $cust_main->otaker %>"> +<BR> +<INPUT TYPE="submit" NAME="submit" VALUE="<%= $custnum ?  "Apply Changes" : "Add Customer" %>"> +<BR> +</FORM> + +<%= include('/elements/footer.html') %> -%> diff --git a/httemplate/edit/cust_pkg.cgi b/httemplate/edit/cust_pkg.cgi index ce1c86612..174d4dde1 100755 --- a/httemplate/edit/cust_pkg.cgi +++ b/httemplate/edit/cust_pkg.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my %pkg = (); @@ -29,48 +28,62 @@ if ( $cgi->param('error') ) {  }  my $p1 = popurl(1); -print header("Add/Edit Packages", ''); -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT>" -  if $cgi->param('error'); +%><%= include('/elements/header.html', "Add/Edit Packages", '') %> -print qq!<FORM ACTION="${p1}process/cust_pkg.cgi" METHOD=POST>!; +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +<% } %> -print qq!<INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum">!; +<FORM ACTION="<%= $p1 %>process/cust_pkg.cgi" METHOD=POST> +<INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>"> + +<%  #current packages -my @cust_pkg = qsearch('cust_pkg',{ 'custnum' => $custnum, 'cancel' => '' } ); +my @cust_pkg = qsearch('cust_pkg', { 'custnum' => $custnum, 'cancel' => '' } );  if (@cust_pkg) { -  print <<END; -Current packages - select to remove (services are moved to a new package below) -<TABLE> -  <TR STYLE="background-color: #cccccc;"> -    <TH COLSPAN="2">Pkg #</TH> -    <TH>Package description</TH> -  </TR> -<BR><BR> -END +%> + +  Current packages - select to remove (services are moved to a new package below) +  <TABLE> +    <TR STYLE="background-color: #cccccc;"> +      <TH COLSPAN="2">Pkg #</TH> +      <TH>Package description</TH> +    </TR> +  <BR><BR> -  foreach (sort { $all_pkg{$a->getfield('pkgpart')} cmp $all_pkg{$b->getfield('pkgpart')} } @cust_pkg) { +  <% + +  foreach ( sort {     $all_pkg{ $a->getfield('pkgpart') } +                   cmp $all_pkg{ $b->getfield('pkgpart') } +                 } +                 @cust_pkg +          ) +  {      my($pkgnum,$pkgpart)=( $_->getfield('pkgnum'), $_->getfield('pkgpart') );      my $checked = $remove_pkg{$pkgnum} ? ' CHECKED' : ''; -    print <<END; -  <TR> -    <TD><INPUT TYPE="checkbox" NAME="remove_pkg" VALUE="$pkgnum"${checked}></TD> -    <TD ALIGN="right">$pkgnum:</TD>\n -    <TD>$all_pkg{$pkgpart} - $all_comment{$pkgpart}</TD> -  </TR> -END -  } -  print qq!</TABLE><BR><BR>!; -} -print <<END; -Order new packages<BR><BR> -END +  %> + +    <TR> +      <TD><INPUT TYPE="checkbox" NAME="remove_pkg" VALUE="<%= $pkgnum %>"<%= $checked %>></TD> +      <TD ALIGN="right"><%= $pkgnum %>:</TD> +      <TD><%= $all_pkg{$pkgpart} %> - <%= $all_comment{$pkgpart} %></TD> +    </TR> + +  <% } %> + +  </TABLE> +  <BR><BR> +<% } %> + +Order new packages +<BR><BR> + +<%  my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum});  my $agent = qsearchs('agent',{'agentnum'=> $cust_main->agentnum }); @@ -79,13 +92,15 @@ my %agent_pkgs = map { ( $_->pkgpart , $all_pkg{$_->pkgpart} ) }  my $count = 0;  my $pkgparts = 0; -print <<END; +%> +  <TABLE>    <TR STYLE="background-color: #cccccc;">      <TH>Qty.</TH>      <TH COLSPAN="2">Package Description</TH>    </TR> -END + +<%  #foreach my $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {  foreach my $pkgpart ( sort { $agent_pkgs{$a} cmp $agent_pkgs{$b} }                               keys(%agent_pkgs) ) { @@ -93,38 +108,43 @@ foreach my $pkgpart ( sort { $agent_pkgs{$a} cmp $agent_pkgs{$b} }    next unless exists $pkg{$pkgpart}; #skip disabled ones    #print qq!<TR>! if ( $count == 0 );    my $value = $cgi->param("pkg$pkgpart") || 0; -  print <<END; +%> +    <TR> -    <TD><INPUT TYPE="text" NAME="pkg$pkgpart" VALUE="$value" SIZE="2" MAXLENGTH="2"></TD> -    <TD ALIGN="right">$pkgpart:</TD> -    <TD>$pkg{$pkgpart} - $comment{$pkgpart}</TD> +    <TD> +      <INPUT TYPE="text" NAME="<%= "pkg$pkgpart" %>" VALUE="<%= $value %>" SIZE="2" MAXLENGTH="2"> +    </TD> +    <TD ALIGN="right"><%= $pkgpart %>:</TD> +    <TD><%= $pkg{$pkgpart} %> - <%= $comment{$pkgpart}%></TD>    </TR> -END + +<%    $count ++ ;    #if ( $count == 2 ) {    #  print qq!</TR>\n! ;    #  $count = 0;    #}  } -print qq!</TABLE>!; - -unless ( $pkgparts ) { -  my $p2 = popurl(2); -  my $typenum = $agent->typenum; -  my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } ); -  my $atype = $agent_type->atype; -  print <<END; -(No <a href="${p2}browse/part_pkg.cgi">package definitions</a>, or agent type -<a href="${p2}edit/agent_type.cgi?$typenum">$atype</a> not allowed to purchase -any packages.) -END -} +%> -#submit -print <<END; -<P><INPUT TYPE="submit" VALUE="Order"> -    </FORM> -  </BODY> -</HTML> -END +</TABLE> + +<% unless ( $pkgparts ) { +     my $p2 = popurl(2); +     my $typenum = $agent->typenum; +     my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } ); +     my $atype = $agent_type->atype;  %> + +     (No <A HREF="<%= $p2 %>browse/part_pkg.cgi">package definitions</A>, +     or agent type +     <A HREF="<%= $p2 %>edit/agent_type.cgi?<%= $typenum %>"><%= $atype %></a> +     is not allowed to purchase any packages.) + +<% } %> + +<P><INPUT TYPE="submit" VALUE="Order"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 5486b4b00..120c03a3c 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -17,6 +17,13 @@    # 'menubar'     => '', #menubar arrayref    #    # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' +  # +  # 'html_bottom' => '', #string +  # 'html_bottom' => sub { +  #                        my $object = shift; +  #                        # ... +  #                        "html_string"; +  #                      },    my(%opt) = @_; @@ -27,6 +34,7 @@    my $fields = $opt{'fields'}                 #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ];                 || [ grep { $_ ne $pkey } fields($table) ]; +  #my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields;    my $object;    if ( $cgi->param('error') ) { @@ -63,10 +71,7 @@      );    } -%> - - -<%= include("/elements/header.html", $title, +%><%= include("/elements/header.html", $title,                include( '/elements/menubar.html', @menubar )             )  %> @@ -86,7 +91,18 @@  <%= ntable("#cccccc",2) %> -<% foreach my $field ( @$fields ) { %> +<% foreach my $f ( @$fields ) { + +    my( $field, $type); +    if ( ref($f) ) { +      $field = $f->{'field'}, +      $type  = $f->{'type'} || 'text', +    } else { +      $field = $f; +      $type = 'text'; +    } + +%>    <TR> @@ -98,12 +114,11 @@      </TD>      <% -      #just text in one size for now... eventually more options for -      # uneditable, hidden, <SELECT>, etc. fields +      #eventually more options for <SELECT>, etc. fields      %>      <TD> -      <INPUT TYPE="text" NAME="<%= $field %>" VALUE="<%= $object->$field() %>"> +      <INPUT TYPE="<%= $type %>" NAME="<%= $field %>" VALUE="<%= $object->$field() %>">      <TD>    </TR> @@ -112,6 +127,11 @@  </TABLE> +<%= ref( $opt{'html_bottom'} ) +      ? &{ $opt{'html_bottom'} }( $object ) +      : $opt{'html_bottom'} +%> +  <BR>  <INPUT TYPE="submit" VALUE="<%= $object->$pkey() ? "Apply changes" : "Add $opt{'name'}" %>"> diff --git a/httemplate/edit/part_referral.cgi b/httemplate/edit/part_referral.cgi index f784dfa3e..dce1e6394 100755 --- a/httemplate/edit/part_referral.cgi +++ b/httemplate/edit/part_referral.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my $part_referral; @@ -17,32 +16,29 @@ my $action = $part_referral->refnum ? 'Edit' : 'Add';  my $hashref = $part_referral->hashref;  my $p1 = popurl(1); -print header("$action Advertising source", menubar( + +%><%= include('/elements/header.html', "$action Advertising source", menubar(    'Main Menu' => popurl(2),    'View all advertising sources' => popurl(2). "browse/part_referral.cgi", -)); +)) %> + +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +<% } %> -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT>" -  if $cgi->param('error'); +<FORM ACTION="<%= $p1 %>process/part_referral.cgi" METHOD=POST> -print qq!<FORM ACTION="${p1}process/part_referral.cgi" METHOD=POST>!; +<INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $hashref->{refnum} %>"> -print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$hashref->{refnum}">!; +<%  #print "Referral #", $hashref->{refnum} ? $hashref->{refnum} : "(NEW)"; +%> -print <<END; -Advertising source <INPUT TYPE="text" NAME="referral" SIZE=32 VALUE="$hashref->{referral}"> -END +Advertising source <INPUT TYPE="text" NAME="referral" SIZE=32 VALUE="<%= $hashref->{referral} %>"> -print qq!<BR><INPUT TYPE="submit" VALUE="!, -      $hashref->{refnum} ? "Apply changes" : "Add advertising source", -      qq!">!; +<BR> +<INPUT TYPE="submit" VALUE="<%= $hashref->{refnum} ? "Apply changes" : "Add advertising source" %>"> -print <<END; -    </FORM> -  </BODY> -</HTML> -END +</FORM> -%> +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/part_virtual_field.cgi b/httemplate/edit/part_virtual_field.cgi index fb10321e8..7b2c768a7 100644 --- a/httemplate/edit/part_virtual_field.cgi +++ b/httemplate/edit/part_virtual_field.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my ($vfieldpart, $part_virtual_field); @@ -21,12 +20,14 @@ if ( $cgi->param('error') ) {  my $action = $part_virtual_field->vfieldpart ? 'Edit' : 'Add';  my $p1 = popurl(1); -print header("$action Virtual Field Definition", ''); -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT>" -  if $cgi->param('error'); -%> +%><%= include('/elements/header.html', "$action Virtual Field Definition") %> + +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +  <BR><BR> +<% } %> +  <FORM ACTION="<%=$p1%>process/generic.cgi" METHOD="POST">  <INPUT TYPE="hidden" NAME="table" VALUE="part_virtual_field"> @@ -83,10 +84,8 @@ Field #<B><%=$vfieldpart or "(NEW)"%></B><BR><BR>  </FORM> -<BR><BR> +<BR>  <FONT SIZE=-2>If you don't understand what <I>check_block</I> and   <I>list_source</I> mean, <B>LEAVE THEM BLANK</B>.  We mean it.</FONT> - -</BODY> -</HTML> +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html new file mode 100644 index 000000000..e8c6d07b1 --- /dev/null +++ b/httemplate/edit/process/access_group.html @@ -0,0 +1,5 @@ +<%= include( 'elements/process.html', +               'table'       => 'access_group', +               'viewall_dir' => 'browse', +           ) +%> diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html new file mode 100644 index 000000000..a6c2a36b1 --- /dev/null +++ b/httemplate/edit/process/access_user.html @@ -0,0 +1,8 @@ +<%= include( 'elements/process.html', +               'table'       => 'access_user', +               'viewall_dir' => 'browse', +               'process_m2m' => { 'link_table'   => 'access_usergroup', +                                  'target_table' => 'access_group', +                                }, +           ) +%> diff --git a/httemplate/edit/process/agent_type.cgi b/httemplate/edit/process/agent_type.cgi index 516594573..fd8ca8833 100755 --- a/httemplate/edit/process/agent_type.cgi +++ b/httemplate/edit/process/agent_type.cgi @@ -11,43 +11,24 @@ my $new = new FS::agent_type ( {  my $error;  if ( $typenum ) { -  $error=$new->replace($old); +  $error = $new->replace($old);  } else { -  $error=$new->insert; -  $typenum=$new->getfield('typenum'); +  $error    = $new->insert; +  $typenum  = $new->getfield('typenum');  } +#$error  ||= $new->process_m2m( );  if ( $error ) {    $cgi->param('error', $error);    print $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string );  } else { -  #false laziness w/ edit/process/part_svc.cgi -  foreach my $part_pkg (qsearch('part_pkg',{})) { -    my($pkgpart)=$part_pkg->getfield('pkgpart'); - -    my($type_pkgs)=qsearchs('type_pkgs',{ -        'typenum' => $typenum, -        'pkgpart' => $pkgpart, -    }); -    if ( $type_pkgs && ! $cgi->param("pkgpart$pkgpart") ) { -      my($d_type_pkgs)=$type_pkgs; #need to save $type_pkgs for below. -      $error=$d_type_pkgs->delete; -      die $error if $error; - -    } elsif ( $cgi->param("pkgpart$pkgpart") -              && ! $type_pkgs -    ) { -      #ok to clobber it now (but bad form nonetheless?) -      $type_pkgs=new FS::type_pkgs ({ -        'typenum' => $typenum, -        'pkgpart' => $pkgpart, -      }); -      $error= $type_pkgs->insert; -      die $error if $error; -    } - -  } +  my $error = $new->process_m2m( +    'link_table'   => 'type_pkgs', +    'target_table' => 'part_pkg', +    'params'       => scalar($cgi->Vars) +  ); +  die $error if $error;    print $cgi->redirect(popurl(3). "browse/agent_type.cgi");  } diff --git a/httemplate/edit/process/cust_bill_pay.cgi b/httemplate/edit/process/cust_bill_pay.cgi index 0025b16b5..fc668bb07 100755 --- a/httemplate/edit/process/cust_bill_pay.cgi +++ b/httemplate/edit/process/cust_bill_pay.cgi @@ -33,11 +33,19 @@ if ($cgi->param('invnum') =~ /^Refund$/) {  my $error = $new->insert;  if ( $error ) { +    $cgi->param('error', $error); -  print $cgi->redirect(popurl(2). "cust_bill_pay.cgi?". $cgi->query_string ); +  %><%= $cgi->redirect(popurl(2). "cust_bill_pay.cgi?". $cgi->query_string ) %><% +  } else { -  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} +  #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + +  %><%= header('Payment application sucessful') %> +  <SCRIPT TYPE="text/javascript"> +    window.top.location.reload(); +  </SCRIPT> + +  </BODY></HTML> -%> +<% } %> diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi index 85bfd4489..6a4ef194a 100755 --- a/httemplate/edit/process/cust_credit.cgi +++ b/httemplate/edit/process/cust_credit.cgi @@ -13,14 +13,23 @@ my $error = $new->insert;  if ( $error ) {    $cgi->param('error', $error); -  print $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ); + +  %><%= $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ) %><% +  } else { +    if ( $cgi->param('apply') eq 'yes' ) {      my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum })        or die "unknown custnum $custnum";      $cust_main->apply_credits;    } -  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} +  #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + +  %><%= header('Credit sucessful') %> +  <SCRIPT TYPE="text/javascript"> +    window.top.location.reload(); +  </SCRIPT> + +  </BODY></HTML> -%> +<% } %> diff --git a/httemplate/edit/process/cust_credit_bill.cgi b/httemplate/edit/process/cust_credit_bill.cgi index 28f892f62..3b759536f 100755 --- a/httemplate/edit/process/cust_credit_bill.cgi +++ b/httemplate/edit/process/cust_credit_bill.cgi @@ -34,11 +34,19 @@ if ($cgi->param('invnum') =~ /^Refund$/) {  my $error = $new->insert;  if ( $error ) { +    $cgi->param('error', $error); -  print $cgi->redirect(popurl(2). "cust_credit_bill.cgi?". $cgi->query_string ); +  %><%= $cgi->redirect(popurl(2). "cust_credit_bill.cgi?". $cgi->query_string ) %><% +  } else { -  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} +  #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + +  %><%= header('Credit application sucessful') %> +  <SCRIPT TYPE="text/javascript"> +    window.top.location.reload(); +  </SCRIPT> + +  </BODY></HTML> -%> +<% } %> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 83ff6f728..59ad35ee4 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -2,10 +2,21 @@    # options example...    #  +  ### +  ##req +  ##    # 'table' =>  +  #    # #? 'primary_key' => #required when the dbdef doesn't know...???    # #? 'fields' => [] +  # +  ### +  ##opt +  ###    # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' +  # 'process_m2m' => { 'link_table'   => 'link_table_name', +  #                    'target_table' => 'target_table_name', +  #                  }.    my(%opt) = @_; @@ -31,12 +42,16 @@    if ( $pkeyvalue ) {      $error = $new->replace($old);    } else { -    warn $new;      $error = $new->insert; -    warn $error;      $pkeyvalue = $new->getfield($pkey);    } +  if ( !$error && $opt{'process_m2m'} ) { +    $error = $new->process_m2m( %{ $opt{'process_m2m'} }, +                                'params' => scalar($cgi->Vars), +                              ); +  } +    if ( $error ) {      $cgi->param('error', $error);      print $cgi->redirect(popurl(2). "$table.html?". $cgi->query_string ); diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi index ca0e3398f..f47ba0a8f 100755 --- a/httemplate/edit/svc_domain.cgi +++ b/httemplate/edit/svc_domain.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge -->  <%  my($svcnum, $pkgnum, $svcpart, $kludge_action, $purpose, $part_svc, @@ -66,33 +65,31 @@ my $otaker = getotaker;  my $domain = $svc_domain->domain;  my $p1 = popurl(1); -print header("$action $svc", ''); - -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), -      "</FONT>" -  if $cgi->param('error'); - -print <<END; -    <FORM ACTION="${p1}process/svc_domain.cgi" METHOD=POST> -      <INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum"> -      <INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum"> -      <INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart"> -END - -print qq!<INPUT TYPE="radio" NAME="action" VALUE="N"!; -print ' CHECKED' if $kludge_action eq 'N'; -print qq!>New!; -print qq!<BR><INPUT TYPE="radio" NAME="action" VALUE="M"!; -print ' CHECKED' if $kludge_action eq 'M'; -print qq!>Transfer!; - -print <<END; -<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="$domain" SIZE=28 MAXLENGTH=63> -<BR>Purpose/Description: <INPUT TYPE="text" NAME="purpose" VALUE="$purpose" SIZE=64> -<P><INPUT TYPE="submit" VALUE="Submit"> -    </FORM> -  </BODY> -</HTML> -END  %> + +<%= include('/elements/header.html', "$action $svc", '') %> + +<% if ( $cgi->param('error') ) { %> +  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +<% } %> + +<FORM ACTION="<%= $p1 %>process/svc_domain.cgi" METHOD=POST> +<INPUT TYPE="hidden" NAME="svcnum" VALUE="<%= $svcnum %>"> +<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>"> +<INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $svcpart %>"> + +<INPUT TYPE="radio" NAME="action" VALUE="N"<%= $kludge_action eq 'N' ? ' CHECKED' : '' %>>New +<BR> + +<INPUT TYPE="radio" NAME="action" VALUE="M"<%= $kludge_action eq 'M' ? ' CHECKED' : '' %>>Transfer + +<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="<%= $domain %>" SIZE=28 MAXLENGTH=63> + +<BR>Purpose/Description: <INPUT TYPE="text" NAME="purpose" VALUE="<%= $purpose %>" SIZE=64> + +<P><INPUT TYPE="submit" VALUE="Submit"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html new file mode 100644 index 000000000..d26ebef35 --- /dev/null +++ b/httemplate/elements/checkboxes-table.html @@ -0,0 +1,110 @@ +<% + +  ## +  # required +  ## +  # 'target_table'    => 'table_name', +  # 'link_table'      => 'table_name', +  # +  # 'name_col' => 'name_column', +  # #or +  # 'name_callback' => sub { }, +  # +  ## +  # recommended (required?) +  ## +  # 'source_obj'   => $obj, +  # #or? +  # #'source_table' => 'table_name', +  # #'sourcenum'    => '4', #current value of primary key in source_table +  # #                       # (none is okay, just pass it if you have it) +  ## +  # optional +  ## +  # 'disable-able' => 1, + +  my( %opt ) = @_; + +  my $target_pkey = dbdef->table($opt{'target_table'})->primary_key; + +  my( $source_pkey, $sourcenum, $source_obj ); +  if ( $opt{'source_obj'} ) { + +    $source_obj = $opt{'source_obj'}; +    #$source_table = $source_obj->dbdef_table->table; +    $source_pkey = $source_obj->dbdef_table->primary_key; +    $sourcenum = $source_obj->$source_pkey(); + +  } else { + +    #$source_obj? +    $source_pkey = $opt{'source_table'} +                     ? dbdef->table($opt{'source_table'})->primary_key +                     : ''; +    $sourcenum = $opt{'sourcenum'}; +  } + +  my $hashref = $opt{'hashref'} || {}; + +  my $extra_sql = ''; + +  if ( $opt{'disable-able'} ) { +    $hashref->{'disabled'} = ''; + +    $extra_sql .= ( $sourcenum && $source_pkey )  +                    ? "OR $source_pkey = $sourcenum" +                    : ''; +  } + +%> + +<% foreach my $target_obj ( +     qsearch({ 'table'     => $opt{'target_table'}, +               'hashref'   => $hashref, +               'select'    => $opt{'target_table'}. '.*', +               'addl_from' => "LEFT JOIN $opt{'link_table'} USING ( $target_pkey )", +               'extra_sql' => $extra_sql, +            }) +   ) { + +     my $targetnum = $target_obj->$target_pkey(); +%> + +  <INPUT TYPE="checkbox" NAME="<%= $target_pkey. $targetnum %>" <%= +        qsearchs( $opt{'link_table'}, { +          $source_pkey => $sourcenum, +          $target_pkey => $targetnum, +        }) +          ? 'CHECKED ' +          : '' +  %> VALUE="ON"> + +  <% if ( $opt{'target_link'} ) { %> + +    <A HREF="<%= $opt{'target_link'} %><%= $targetnum %>"><% + +  } +  %><%= $targetnum %>:  + +  <% if ( $opt{'name_callback'} ) { %> + +    <%= &{ $opt{'name_callback'} }( $target_obj ) %><%= $opt{'target_link'} ? '</A>' : '' %> + +  <% } else { +       my $name_col = $opt{'name_col'}; +  %> + +    <%= $target_obj->$name_col() %><%= $opt{'target_link'} ? '</A>' : '' %> + +  <% } %> + +  <% if ( $opt{'disable-able'} ) { %> + +    <%= $target_obj->disabled =~ /^Y/i ? ' (DISABLED)' : '' %> + +  <% } %> + +  <BR> + +<% } %> + diff --git a/httemplate/elements/cssexpr.js b/httemplate/elements/cssexpr.js new file mode 100644 index 000000000..c434d8da0 --- /dev/null +++ b/httemplate/elements/cssexpr.js @@ -0,0 +1,66 @@ +function constExpression(x) { +	return x; +} + +function simplifyCSSExpression() { +	try { +		var ss,sl, rs, rl; +		ss = document.styleSheets; +		sl = ss.length +	 +		for (var i = 0; i < sl; i++) { +			simplifyCSSBlock(ss[i]); +		} +	} +	catch (exc) { +		//alert("Got an error while processing css. The page should still work but might be a bit slower"); +		throw exc; +	} +} + +function simplifyCSSBlock(ss) { +	var rs, rl; +	 +	for (var i = 0; i < ss.imports.length; i++) +		simplifyCSSBlock(ss.imports[i]); +	 +	if (ss.cssText.indexOf("expression(constExpression(") == -1) +		return; + +	rs = ss.rules; +	rl = rs.length; +	for (var j = 0; j < rl; j++) +		simplifyCSSRule(rs[j]); +	 +} + +function simplifyCSSRule(r) { +	var str = r.style.cssText; +	var str2 = str; +	var lastStr; +	do { +		lastStr = str2; +		str2 = simplifyCSSRuleHelper(lastStr); +	} while (str2 != lastStr) + +	if (str2 != str) +		r.style.cssText = str2; +} + +function simplifyCSSRuleHelper(str) { +	var i, i2; +	i = str.indexOf("expression(constExpression("); +	if (i == -1) return str; +	i2 = str.indexOf("))", i); +	var hd = str.substring(0, i); +	var tl = str.substring(i2 + 2); +	var exp = str.substring(i + 27, i2); +	var val = eval(exp) +	return hd + val + tl; +} + +if (/msie/i.test(navigator.userAgent) && window.attachEvent != null) { +	window.attachEvent("onload", function () { +		simplifyCSSExpression(); +	}); +} diff --git a/httemplate/elements/footer.html b/httemplate/elements/footer.html index 6029d7637..32d121996 100644 --- a/httemplate/elements/footer.html +++ b/httemplate/elements/footer.html @@ -1,2 +1,5 @@ +        </TD> +      </TR> +    </TABLE>    </BODY>  </HTML> diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 10e4e40f1..49814577e 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -2,20 +2,285 @@    my($title, $menubar) = ( shift, shift );    my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.    my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section +  my $conf = new FS::Conf;  %> -    <HTML> -      <HEAD> -        <TITLE> -          <%= $title %> -        </TITLE> -        <META HTTP-Equiv="Cache-Control" Content="no-cache"> -        <META HTTP-Equiv="Pragma" Content="no-cache"> -        <META HTTP-Equiv="Expires" Content="0">  -        <%= $head %> -      </HEAD> -      <BODY BGCOLOR="#e8e8e8"<%= $etc %>> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<HTML> +  <HEAD> +    <TITLE> +      <%= $title %> +    </TITLE> +    <META HTTP-Equiv="Cache-Control" Content="no-cache"> +    <META HTTP-Equiv="Pragma" Content="no-cache"> +    <META HTTP-Equiv="Expires" Content="0">  +    <script type="text/javascript" src="<%=$fsurl%>elements/cssexpr.js"></script> +    <script type="text/javascript" src="<%=$fsurl%>elements/xmenu.js"></script> +    <link href="<%=$fsurl%>elements/xmenu.css" type="text/css" rel="stylesheet"> +    <% + +      tie my %report_menu, 'Tie::IxHash', +        'Report one' => [ 'there', 'theretip' ], +        'Report too' => [ 'here',  'heretip'  ], +      ; + +      tie my %config_employees, 'Tie::IxHash', +        'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ], +        'View/Edit employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ], +      ; + +      tie my %config_export_svc_pkg, 'Tie::IxHash', +        'View/Edit exports'             => [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ], +        'View/Edit service definitions' => [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ], +        'View/Edit package definitions' => [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ], +        'View/Edit package classes'     => [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ], +      ; + +      tie my %config_agent, 'Tie::IxHash', +        'View/Edit agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ], +        'View/Edit agents'      => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ], +      ; + +      tie my %config_billing, 'Tie::IxHash', +        'View/Edit payment gateways'         => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ], +        'View/Edit invoice events'           => [ $fsurl.'browse/part_bill_event.cgi', 'Actions for overdue invoices' ], +        'View/Edit prepaid cards'            => [ $fsurl.'browse/prepay_credit.html', 'View outstanding cards, generate new cards' ], +        'View/Edit call rates and regions'   => [ $fsurl.'browse/rate.cgi', 'Manage rate plans, regions and prefixes for VoIP and call billing' ], +        'View/Edit locales and tax rates'    => [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ], +      ; + +      tie my %config_dialup, 'Tie::IxHash', +        'View/Edit access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ], +      ; + +      tie my %config_broadband, 'Tie::IxHash', +        'View/Edit routers'        => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ], +        'View/Edit address blocks' => [ $fsurl.'browse/addr_block.cgi', 'Manage address blocks and block assignments to broadband routers' ], +      ; + +      tie my %config_misc, 'Tie::IxHash', +        'View/Edit advertising sources' => [ $fsurl.'browse/part_referral.cgi', 'Where a customer heard about your service.  Tracked for informational purposes' ], +        'View/Edit virtual fields' => [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ], +        'View/Edit message catalog' => [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ], +        'View/Edit inventory classes and inventory' => [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ], +      ; + +      tie my %config_menu, 'Tie::IxHash', +        'Settings'      => [ $fsurl.'config/config-view.cgi', 'XXXconfigittip' ], +        'separator'     => '', #its a separator! +        'Employees'     => [ \%config_employees, 'XXXtooltip' ], +        'Provisioning, services and packages' +                        => [ \%config_export_svc_pkg, 'XXXtootip'    ], +        'Resellers'     => [ \%config_agent, 'XXXtootip'    ], +        'Billing'       => [ \%config_billing, 'XXXtootip'    ], +        'Dialup'        => [ \%config_dialup, 'XXXtootip'    ], +        'Fixed (username-less) broadband' +                        => [ \%config_broadband, 'XXXtootip'    ], +        'Miscellaneous' => [ \%config_misc, 'XXXtootip'    ], +      ; + +      tie my %menu, 'Tie::IxHash', +        'Home'          => [ $fsurl, 'hometip', ], +        'Top item one'  => [ 'nowhere_yet', 'nowheretip', ], +        'Top item too'  => [ 'nowhere_yet_either', 'eithertip', ], +        'Reports'       => [ \%report_menu, 'reportmenutip' ], +        'Configuration' => [ \%config_menu, 'configmenutip' ], +      ; + +      use vars qw($gmenunum); +      $gmenunum = 0; + +      sub submenu { +        my($submenu, $title) = @_; +        my $menunum = $gmenunum++; + +        #return two args: html, menuname + +        "var myMenu$menunum = new WebFXMenu;\n". +        #"myMenu$menunum.useAutoPosition = true;\n". +        "myMenu$menunum.emptyText = '$title';\n". + +        ( +          join("\n", map { +   +            if ( !ref( $submenu->{$_} ) ) { +   +              "myMenu$menunum.add(new WebFXMenuSeparator());"; +   +            } else { +   +              my($url_or_submenu, $tooltip ) = @{ $submenu->{$_} }; +              if ( ref($url_or_submenu) ) { +   +                my($subhtml, $submenuname ) = submenu($url_or_submenu, $_); #mmm, recursion +   +                "$subhtml\n". +                "myMenu$menunum.add(new WebFXMenuItem(\"$_\", null, \"$tooltip\", $submenuname ));"; +   +              } else { +   +                "myMenu$menunum.add(new WebFXMenuItem(\"$_\", \"$url_or_submenu\", \"$tooltip\" ));"; +   +              } +   +            } +   +          } keys %$submenu ) +        ). "\n". +        "myMenu$menunum.width = 224\n", + +        "myMenu$menunum"; + +      } + +    %> +    <SCRIPT TYPE="text/javascript"> + +      webfxMenuImagePath      = "<%=$fsurl%>images/"; +      webfxMenuUseHover       = 1; +      webfxMenuShowTime       = 300; +      webfxMenuHideTime       = 500; + +      var myBar = new WebFXMenuBar; + +      <% foreach my $item ( keys %menu ) { + +           my( $url_or_submenu, $tooltip ) = @{ $menu{$item} }; + +           if ( ref($url_or_submenu) ) { + +             warn $item; + +             my( $subhtml, $submenuname ) = submenu($url_or_submenu, $item); + +      %> + +             <%= $subhtml %> +             myBar.add(new WebFXMenuButton("<%= $item %>", null, "<%= $tooltip %>", <%= $submenuname %> )); + +      <%   } else { %> +         +             myBar.add(new WebFXMenuButton("<%= $item %>", "<%= $url_or_submenu %>", "<%= $tooltip %>" )); + +      <%   } + +        } +      %> + +      myBar.show( null, 'vertical' ); +      //myBar.show( null, 'horizontal' ); + +      //var myMenu = new WebFXMenu; +      //myMenu.add(new WebFXMenuItem("Menu Item 1", "http://www.domain.com", "Tool tip to show")); +      //myMenu.add(new WebFXMenuSeparator()); +      //myMenu.add(new WebFXMenuItem("Menu Item 2", "http://www.domain.com", "Tool tip to show")); +       +      //var mySubMenu = new WebFXMenu; +      //mySubMenu.add(new WebFXMenuItem("Menu Item 3", "http://www.domain.com", "Tool tip to show")); +      //myMenu.add(new WebFXMenuItem("Menu Item 4 with sub menu", null, "Tool tip to show", mySubMenu)); + +      myBar.width = 154; + +    </SCRIPT> + +    <SCRIPT TYPE="text/javascript"> +      function clearhint_search_cust () { +        alert(this); +        if ( this.value='(cust #, name or company)' ) +          this.value = ''; +      } +    </SCRIPT> + +    <%= $head %> + +  </HEAD> +  <BODY BACKGROUND="<%=$fsurl%>images/background-cheat.png" <%= $etc %> STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0"> +    <table width="100%" CELLPADDING=0 CELLSPACING=0 STYLE="padding-left:0; padding-right:4"> +      <tr> +        <td rowspan=2 BGCOLOR="#ffffff"> +          <IMG BORDER=0 ALT="freeside" SRC="<%=$fsurl%>images/small-logo.png"> +        </td> +        <td align=left rowspan=2 BGCOLOR="#ffffff"> <!-- valign="top" --> +          <font size=6><%= $conf->config('company_name') %> Billing</font> +        </td> +        <td align=right valign=top BGCOLOR="#ffffff">Logged in as <b><%= getotaker %> </b><br><FONT SIZE="-2"><a href="<%=$fsurl%>pref/XXXwritethis">Preferences</a> <BR><BR></FONT> +        </td> +      </tr> +      <tr> +        <td align=right valign=bottom BGCOLOR="#ffffff"> +   +          <table> +            <tr> +              <td align=right BGCOLOR="#ffffff"> +                <FONT SIZE="-2"> +                 <A HREF="http://www.sisd.com/freeside">Freeside</A> v<%= $FS::VERSION %><BR> +                 <A HREF="<%= $fsurl %>docs/">Documentation</A><BR> +                </FONT> +              </td> +              <% if ( $conf->config('ticket_system') eq 'RT_Internal' ) { %> +              <% eval "use RT;"; %> +                <td bgcolor=#000000></td> +                <td align=left> +                  <FONT SIZE="-2"> +                   <A HREF="http://www.bestpractical.com/rt">RT<A> v<%= $RT::VERSION %><BR> +                   <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR> +                  </FONT> +                </td> +              <% } %> +   +            </tr> +          </table> +   +        </td> +      </tr> +    </table> + +    <TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=4> +      <TR> +        <TD COLSPAN=4 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD> +      </TR> +      <TR> +        <TD COLSPAN=1 BGCOLOR="#000000" WIDTH="154"> +        </TD> +        <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> +          <FORM ACTION="<%=$fsurl%>edit/cust_main.cgi" METHOD="GET" STYLE="margin:0"> +            <INPUT TYPE="submit" VALUE="New customer"> +          </FORM> +        </TD> +        <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> +          <FORM ACTION="<%=$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0"> +            <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name or company)" SIZE="23" onFocus="clearhint_search_cust" onClick="clearhint_search_cust"> +            <INPUT TYPE="submit" VALUE="Search customers"> +          </FORM> +        </TD> +        <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> +          <FORM ACTION="<%=$fsurl%>rt/index.html" METHOD="GET" STYLE="margin:0"> +            <INPUT NAME="q" TYPE="text" VALUE="" onFocus="clearhint_search_ticket" onClick="clearhint_search_ticket"> +            <INPUT TYPE="submit" VALUE="Search tickets"> +          </FORM> +        </TD> +      </TR> +    </TABLE> +    <TABLE WIDTH="100%" HEIGHT="100%" CELLSPACING=0 CELLPADDING=4> +      <TR> +        <TD BGCOLOR="#000000" STYLE="padding:0" WIDTH="154"></TD> +        <TD STYLE="padding:0" WIDTH="13"><IMG BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gray-corner.png"></TD> +        <TD STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gray-top.png" HEIGHT="13" WIDTH="100%"></TD> +      </TR> +      <TR HEIGHT="100%"> +        <TD BGCOLOR="#000000" ALIGN="left" HEIGHT="100%" WIDTH="154" VALIGN="top" ALIGN="right"> +          <SCRIPT TYPE="text/javascript"> +            document.write(myBar); +          </SCRIPT> +          <BR> +          <IMG SRC="<%=$fsurl%>images/32clear.gif" HEIGHT="1" WIDTH="154"> + +        </TD> +        <TD STYLE="padding:0" HEIGHT="100%" WIDTH=13 VALIGN="top"><IMG WIDTH="13" HEIGHT="100%" BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gray-side.png"></TD> +        <TD BGCOLOR="#e8e8e8" HEIGHT="100%"> <!-- WIDTH="100%"> --> +            <FONT SIZE=6>              <%= $title %>            </FONT> +            <BR><BR> -          <%= $menubar ? "$menubar<BR><BR>" : '' %> +          <%= $menubar !~ /^\s*$/ ? "$menubar<BR><BR>" : '' %> diff --git a/httemplate/elements/menubar.html b/httemplate/elements/menubar.html index 87a50312c..29facb6b6 100644 --- a/httemplate/elements/menubar.html +++ b/httemplate/elements/menubar.html @@ -2,6 +2,7 @@    my($item, $url, @html);    while (@_) {      ($item, $url) = splice(@_,0,2); +    next if $item =~ /^\s*Main\s+Menu\s*$/i;      push @html, qq!<A HREF="$url">$item</A>!;    }  %> diff --git a/httemplate/elements/select-access_group.html b/httemplate/elements/select-access_group.html new file mode 100644 index 000000000..b05f565ea --- /dev/null +++ b/httemplate/elements/select-access_group.html @@ -0,0 +1,15 @@ +<%  +  my( $groupnum, %opt ) = @_; + +  %opt{'records'} = delete $opt{'access_group'} +    if $opt{'access_group'}; + +%><%= include( '/elements/select-table.html', +                 'table'       => 'access_group', +                 'name_col'    => 'groupname', +                 'value'       => $groupnum, +                 'empty_label' => '(none)', +                 #'hashref'     => { 'disabled' => '' }, +                 %opt, +             ) +%> diff --git a/httemplate/elements/tr-select-access_group.html b/httemplate/elements/tr-select-access_group.html new file mode 100644 index 000000000..0beec0842 --- /dev/null +++ b/httemplate/elements/tr-select-access_group.html @@ -0,0 +1,22 @@ +<% +  my( $groupnum, %opt ) = @_; + +  $opt{'access_group'} ||= [ qsearch( 'access_group', {} ) ]; # { disabled=>'' } ) + +  #warn "***** tr-select-access_group: \n". Dumper(%opt); +%> + +<% if ( scalar(@{ $opt{'access_group'} }) == 0 ) { %> + +  <INPUT TYPE="hidden" NAME="groupnum" VALUE=""> + +<% } else { %> + +  <TR> +    <TD ALIGN="right"><%= $opt{'label'} || 'Access group' %></TD> +    <TD> +      <%= include( '/elements/select-access_group.html', $groupnum, %opt ) %> +    </TD> +  </TR> + +<% } %> diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css new file mode 100644 index 000000000..5bb8a0deb --- /dev/null +++ b/httemplate/elements/xmenu.css @@ -0,0 +1,185 @@ + +.webfx-menu, .webfx-menu * { +	/* +	Set the box sizing to content box +	in the future when IE6 supports box-sizing +	there will be an issue to fix the sizes + +	There is probably an issue with IE5 mac now +	because IE5 uses content-box but the script +	assumes all versions of IE uses border-box. + +	At the time of this writing mozilla did not support +	box-sizing for absolute positioned element. + +	Opera only supports content-box +	*/ +	box-sizing:			content-box; +	-moz-box-sizing:	content-box; +} + +.webfx-menu { +	position:		absolute; +	z-index:		100; +	visibility:		hidden; +	width:			154px; +	border:			1px solid black; +	padding:		1px; +	background:		white; +	filter:			progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, Strength=4) +				alpha(Opacity=95); +	-moz-opacity:		0.95; +	/* a drop shadow would be nice in moz/others too... */ +} + +.webfx-menu-empty { +	display:		block; +	border:			1px solid white; +	padding:		2px 5px 2px 5px; +	font-size:		11px; +	/* font-family:		Tahoma, Verdan, Helvetica, Sans-Serif; */ +	color:			black; +} + +.webfx-menu a { +	display:		block; +	width:			expression(constExpression(ieBox ? "100%": "auto"));	/* should be ignored by mz and op */ +	height:			expression(constExpression("1px")); +	overflow:		visible;	 +	padding:		2px 0px 2px 5px; +	font-size:		11px; +	font-family:		Tahoma, Verdan, Helvetica, Sans-Serif; +	text-decoration:	none; +	vertical-align:		center; +	color:			black; +	border:			1px solid white; +}	 + +.webfx-menu a:visited, +.webfx-menu a:visited:hover { +	color:			black; +} + +.webfx-menu a:hover { +	color:			black; +	/* background:		#faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */ +	/* background:		#ffe6fe; */ +	/* background:		#ffc2fe; */ +	background:		#fff2fe; +	border:			1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/ +}	 + +.webfx-menu a .arrow { +	float:			right; +	border:			0; +	width:			3px; +	margin-right:	3px; +	margin-top:		4px; +} + +/* separtor */ +.webfx-menu div { +	height:			0; +	height:			expression(constExpression(ieBox ? "2px" : "0")); +	border-top:		1px solid #7e0079; /* rgb(120,172,255); */ +	border-bottom:	1px solid rgb(234,242,255); +	overflow:		hidden; +	margin:			2px 0px 2px 0px; +	font-size:		0mm; +} + +.webfx-menu-bar { +        /* i want a vertical bar */ +        display:                        block; + +	/* background:		rgb(120,172,255);/*rgb(255,128,0);*/ +	/* background:		 #a097ed; */ +	background:		 #000000; +	/* border:			1px solid #7E0079; */ +	/* border:			1px solid #000000; */ +	/* border: none */ + +	padding:		2px; +	 +	font-family:	Verdana, Helvetica, Sans-Serif; +	font-size:		11px; +	 +	/* IE5.0 has the wierdest box model for inline elements */ +	padding:		expression(constExpression(ie50 ? "0px" : "2px")); +} + +.webfx-menu-bar a, +.webfx-menu-bar a:visited { +        /* i want a vertical bar */ +        display:                        block; + +	/* border:				1px solid black; /*rgb(0,0,0);/*rgb(255,128,0);*/ +	/* border: 1px solid black; /* #ffffff; */ +	/* border-bottom: 1px solid black; */ +	border-bottom: 1px solid white; +	/* border-bottom:	1px solid rgb(0,66,174); +	/* border-bottom: 1px solid black; +	border-bottom: 1px solid black; +	border-bottom: 1px solid black; */ + +	padding:			1px 5px 1px 5px; + +	/* color:				black; */ +	color:				white; +	text-decoration:	none; + +	/* IE5.0 Does not paint borders and padding on inline elements without a height/width */ +	height:		expression(constExpression(ie50 ? "17px" : "auto")); +} + +.webfx-menu-bar a:hover { +	/* color:			black; */ +	color:			white; +	/* background:		rgb(120,172,255);	 */ +	/* background:		#BC79B8; */ +	background:		#7E0079; +	/* border-left:	1px solid rgb(234,242,255); +	border-right:	1px solid rgb(0,66,174); +	border-top:		1px solid rgb(234,242,255); +	border-bottom:	1px solid rgb(0,66,174); */ +} + +.webfx-menu-bar a .arrow { +	border:			0; +	float:			right; +/*	vertical-align:		top; */ +	width:			3px; +	margin-right:	3px; +	margin-top:		4px; +} + +.webfx-menu-bar a:active, .webfx-menu-bar a:focus { +	-moz-outline:	none; +	outline:		none; +	/* +		ie does not support outline but ie55 can hide the outline using +		a proprietary property on HTMLElement. Did I say that IE sucks at CSS? +	*/ +	ie-dummy:		expression(this.hideFocus=true); + +	border-left:	1px solid rgb(0,66,174); +	border-right:	1px solid rgb(234,242,255); +	border-top:		1px solid rgb(0,66,174); +	border-bottom:	1px solid rgb(234,242,255); +} + +.webfx-menu-title  { +	color:			black; +	/* background:		#faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */ +	background:		#7e0079; +/*	border:			1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/ +	padding:		3px 1px 3px 6px; +	display:		block; +	font-size:		13px; +	font-family:		Tahoma, Verdan, Helvetica, Sans-Serif; +	text-decoration:	none; +	color:			white; +/*	border:			1px solid white; */ +	border-bottom:		1px solid white; +}	 + diff --git a/httemplate/elements/xmenu.js b/httemplate/elements/xmenu.js new file mode 100644 index 000000000..134265f53 --- /dev/null +++ b/httemplate/elements/xmenu.js @@ -0,0 +1,668 @@ +//<script> +/* + * This script was created by Erik Arvidsson (erik@eae.net) + * for WebFX (http://webfx.eae.net) + * Copyright 2001 + *  + * For usage see license at http://webfx.eae.net/license.html	 + * + * Created:		2001-01-12 + * Updates:		2001-11-20	Added hover mode support and removed Opera focus hacks + *				2001-12-20	Added auto positioning and some properties to support this + *				2002-08-13	toString used ' for attributes. Changed to " to allow in args + */ +  +// check browsers +var ua = navigator.userAgent; +var opera = /opera [56789]|opera\/[56789]/i.test(ua); +var ie = !opera && /MSIE/.test(ua); +var ie50 = ie && /MSIE 5\.[01234]/.test(ua); +var ie6 = ie && /MSIE [6789]/.test(ua); +var ieBox = ie && (document.compatMode == null || document.compatMode != "CSS1Compat"); +var moz = !opera && /gecko/i.test(ua); +var nn6 = !opera && /netscape.*6\./i.test(ua); +var khtml = /KHTML/i.test(ua); + +// define the default values + +webfxMenuDefaultWidth			= 154; + +webfxMenuDefaultBorderLeft		= 1; +webfxMenuDefaultBorderRight		= 1; +webfxMenuDefaultBorderTop		= 1; +webfxMenuDefaultBorderBottom	= 1; + +webfxMenuDefaultPaddingLeft		= 1; +webfxMenuDefaultPaddingRight	= 1; +webfxMenuDefaultPaddingTop		= 1; +webfxMenuDefaultPaddingBottom	= 1; + +webfxMenuDefaultShadowLeft		= 0; +webfxMenuDefaultShadowRight		= ie && !ie50 && /win32/i.test(navigator.platform) ? 4 :0; +webfxMenuDefaultShadowTop		= 0; +webfxMenuDefaultShadowBottom	= ie && !ie50 && /win32/i.test(navigator.platform) ? 4 : 0; + + +webfxMenuItemDefaultHeight		= 18; +webfxMenuItemDefaultText		= "Untitled"; +webfxMenuItemDefaultHref		= "javascript:void(0)"; + +webfxMenuSeparatorDefaultHeight	= 6; + +webfxMenuDefaultEmptyText		= "Empty"; + +webfxMenuDefaultUseAutoPosition	= nn6 ? false : true; + + + +// other global constants + +webfxMenuImagePath				= ""; + +webfxMenuUseHover				= opera ? true : false; +webfxMenuHideTime				= 500; +webfxMenuShowTime				= 200; + + + +var webFXMenuHandler = { +	idCounter		:	0, +	idPrefix		:	"webfx-menu-object-", +	all				:	{}, +	getId			:	function () { return this.idPrefix + this.idCounter++; }, +	overMenuItem	:	function (oItem) { +		if (this.showTimeout != null) +			window.clearTimeout(this.showTimeout); +		if (this.hideTimeout != null) +			window.clearTimeout(this.hideTimeout); +		var jsItem = this.all[oItem.id]; +		if (webfxMenuShowTime <= 0) +			this._over(jsItem); +		else if ( jsItem ) +			//this.showTimeout = window.setTimeout(function () { webFXMenuHandler._over(jsItem) ; }, webfxMenuShowTime); +			// I hate IE5.0 because the piece of shit crashes when using setTimeout with a function object +			this.showTimeout = window.setTimeout("webFXMenuHandler._over(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuShowTime); +	}, +	outMenuItem	:	function (oItem) { +		if (this.showTimeout != null) +			window.clearTimeout(this.showTimeout); +		if (this.hideTimeout != null) +			window.clearTimeout(this.hideTimeout); +		var jsItem = this.all[oItem.id]; +		if (webfxMenuHideTime <= 0) +			this._out(jsItem); +		else if ( jsItem )  +			//this.hideTimeout = window.setTimeout(function () { webFXMenuHandler._out(jsItem) ; }, webfxMenuHideTime); +			this.hideTimeout = window.setTimeout("webFXMenuHandler._out(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuHideTime); +	}, +	blurMenu		:	function (oMenuItem) { +		window.setTimeout("webFXMenuHandler.all[\"" + oMenuItem.id + "\"].subMenu.hide();", webfxMenuHideTime); +	}, +	_over	:	function (jsItem) { +		if (jsItem.subMenu) { +			jsItem.parentMenu.hideAllSubs(); +			jsItem.subMenu.show(); +		} +		else +			jsItem.parentMenu.hideAllSubs(); +	}, +	_out	:	function (jsItem) { +		// find top most menu +		var root = jsItem; +		var m; +		if (root instanceof WebFXMenuButton) +			m = root.subMenu; +		else { +			m = jsItem.parentMenu; +			while (m.parentMenu != null && !(m.parentMenu instanceof WebFXMenuBar)) +				m = m.parentMenu; +		} +		if (m != null)	 +			m.hide();	 +	}, +	hideMenu	:	function (menu) { +		if (this.showTimeout != null) +			window.clearTimeout(this.showTimeout); +		if (this.hideTimeout != null) +			window.clearTimeout(this.hideTimeout); + +		this.hideTimeout = window.setTimeout("webFXMenuHandler.all['" + menu.id + "'].hide()", webfxMenuHideTime); +	}, +	showMenu	:	function (menu, src, dir) { +		if (this.showTimeout != null) +			window.clearTimeout(this.showTimeout); +		if (this.hideTimeout != null) +			window.clearTimeout(this.hideTimeout); + +		if (arguments.length < 3) +			dir = "vertical"; +		 +		menu.show(src, dir); +	} +}; + +function WebFXMenu() { +	this._menuItems	= []; +	this._subMenus	= []; +	this.id			= webFXMenuHandler.getId(); +	this.top		= 0; +	this.left		= 0; +	this.shown		= false; +	this.parentMenu	= null; +	webFXMenuHandler.all[this.id] = this; +} + +WebFXMenu.prototype.width			= webfxMenuDefaultWidth; +WebFXMenu.prototype.emptyText		= webfxMenuDefaultEmptyText; +WebFXMenu.prototype.useAutoPosition	= webfxMenuDefaultUseAutoPosition; + +WebFXMenu.prototype.borderLeft		= webfxMenuDefaultBorderLeft; +WebFXMenu.prototype.borderRight		= webfxMenuDefaultBorderRight; +WebFXMenu.prototype.borderTop		= webfxMenuDefaultBorderTop; +WebFXMenu.prototype.borderBottom	= webfxMenuDefaultBorderBottom; + +WebFXMenu.prototype.paddingLeft		= webfxMenuDefaultPaddingLeft; +WebFXMenu.prototype.paddingRight	= webfxMenuDefaultPaddingRight; +WebFXMenu.prototype.paddingTop		= webfxMenuDefaultPaddingTop; +WebFXMenu.prototype.paddingBottom	= webfxMenuDefaultPaddingBottom; + +WebFXMenu.prototype.shadowLeft		= webfxMenuDefaultShadowLeft; +WebFXMenu.prototype.shadowRight		= webfxMenuDefaultShadowRight; +WebFXMenu.prototype.shadowTop		= webfxMenuDefaultShadowTop; +WebFXMenu.prototype.shadowBottom	= webfxMenuDefaultShadowBottom; + + + +WebFXMenu.prototype.add = function (menuItem) { +	this._menuItems[this._menuItems.length] = menuItem; +	if (menuItem.subMenu) { +		this._subMenus[this._subMenus.length] = menuItem.subMenu; +		menuItem.subMenu.parentMenu = this; +	} +	 +	menuItem.parentMenu = this; +}; + +WebFXMenu.prototype.show = function (relObj, sDir) { +	if (this.useAutoPosition) +		this.position(relObj, sDir); + +	var divElement = document.getElementById(this.id); +	if ( divElement ) { + +	  divElement.style.left = opera ? this.left : this.left + "px"; +	  divElement.style.top = opera ? this.top : this.top + "px"; +	  divElement.style.visibility = "visible"; + +	  if ( ie ) { +	    var shimElement = document.getElementById(this.id + "Shim"); +	    if ( shimElement ) { +	      shimElement.style.width = divElement.offsetWidth; +	      shimElement.style.height = divElement.offsetHeight; +	      shimElement.style.top = divElement.style.top; +	      shimElement.style.left = divElement.style.left; +	      /*shimElement.style.zIndex = divElement.style.zIndex - 1; */ +	      shimElement.style.display = "block"; +	      shimElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'; +	    } +	  } + +	} + +	this.shown = true; + +	if (this.parentMenu) +		this.parentMenu.show(); +}; + +WebFXMenu.prototype.hide = function () { +	this.hideAllSubs(); +	var divElement = document.getElementById(this.id); +	if ( divElement ) { +	  divElement.style.visibility = "hidden"; +	  if ( ie ) { +	    var shimElement = document.getElementById(this.id + "Shim"); +	    if ( shimElement ) { +	      shimElement.style.display = "none"; +	    } +	  } +	} + +	this.shown = false; +}; + +WebFXMenu.prototype.hideAllSubs = function () { +	for (var i = 0; i < this._subMenus.length; i++) { +		if (this._subMenus[i].shown) +			this._subMenus[i].hide(); +	} +}; + +WebFXMenu.prototype.toString = function () { +	var top = this.top + this.borderTop + this.paddingTop; +	var str = "<div id='" + this.id + "' class='webfx-menu' style='" +  +	"width:" + (!ieBox  ? +		this.width - this.borderLeft - this.paddingLeft - this.borderRight - this.paddingRight  :  +		this.width) + "px;" + +	(this.useAutoPosition ? +		"left:" + this.left + "px;" + "top:" + this.top + "px;" : +		"") + +	(ie50 ? "filter: none;" : "") + +	"'>"; + +	if (this._menuItems.length == 0) { +		str +=	"<span class='webfx-menu-empty'>" + this.emptyText + "</span>"; +	} +	else {	 +		str += '<span class="webfx-menu-title" onmouseover="webFXMenuHandler.overMenuItem(this)"' + +			(webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") + +			 '>' + this.emptyText + '</span>'; +        	// str += '<div id="' + this.id + '-title">' + this.emptyText + '</div>'; +		// loop through all menuItems +		for (var i = 0; i < this._menuItems.length; i++) { +			var mi = this._menuItems[i]; +			str += mi; +			if (!this.useAutoPosition) { +				if (mi.subMenu && !mi.subMenu.useAutoPosition) +					mi.subMenu.top = top - mi.subMenu.borderTop - mi.subMenu.paddingTop; +				top += mi.height; +			} +		} + +	} +	 +	str += "</div>"; + +	if ( ie ) { +          str += "<iframe id='" + this.id + "Shim' src='javascript:false;' scrolling='no' frameBorder='0' style='position:absolute; top:0px; left: 0px; display:none;'></iframe>"; +	} +	 +	for (var i = 0; i < this._subMenus.length; i++) { +		this._subMenus[i].left = this.left + this.width - this._subMenus[i].borderLeft; +		str += this._subMenus[i]; +	} +	 +	return str; +}; +// WebFXMenu.prototype.position defined later + +function WebFXMenuItem(sText, sHref, sToolTip, oSubMenu) { +	this.text = sText || webfxMenuItemDefaultText; +	this.href = (sHref == null || sHref == "") ? webfxMenuItemDefaultHref : sHref; +	this.subMenu = oSubMenu; +	if (oSubMenu) +		oSubMenu.parentMenuItem = this; +	this.toolTip = sToolTip; +	this.id = webFXMenuHandler.getId(); +	webFXMenuHandler.all[this.id] = this; +}; +WebFXMenuItem.prototype.height = webfxMenuItemDefaultHeight; +WebFXMenuItem.prototype.toString = function () { +	return	"<a" + +			" id='" + this.id + "'" + +			" href=\"" + this.href + "\"" + +			(this.toolTip ? " title=\"" + this.toolTip + "\"" : "") + +			" onmouseover='webFXMenuHandler.overMenuItem(this)'" + +			(webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") + +			(this.subMenu ? " unselectable='on' tabindex='-1'" : "") + +			">" + +			(this.subMenu ? "<img class='arrow' src=\"" + webfxMenuImagePath + "arrow.right.black.png\">" : "") + +			this.text +  +			"</a>"; +}; + + +function WebFXMenuSeparator() { +	this.id = webFXMenuHandler.getId(); +	webFXMenuHandler.all[this.id] = this; +}; +WebFXMenuSeparator.prototype.height = webfxMenuSeparatorDefaultHeight; +WebFXMenuSeparator.prototype.toString = function () { +	return	"<div" + +			" id='" + this.id + "'" + +			(webfxMenuUseHover ?  +			" onmouseover='webFXMenuHandler.overMenuItem(this)'" + +			" onmouseout='webFXMenuHandler.outMenuItem(this)'" +			: +			"") + +			"></div>" +}; + +function WebFXMenuBar() { +	this._parentConstructor = WebFXMenu; +	this._parentConstructor(); +} +WebFXMenuBar.prototype = new WebFXMenu; +WebFXMenuBar.prototype.toString = function () { +	var str = "<div id='" + this.id + "' class='webfx-menu-bar'>"; +	 +	// loop through all menuButtons +	for (var i = 0; i < this._menuItems.length; i++) +		str += this._menuItems[i]; +	 +	str += "</div>"; + +	for (var i = 0; i < this._subMenus.length; i++) +		str += this._subMenus[i]; +	 +	return str; +}; + +function WebFXMenuButton(sText, sHref, sToolTip, oSubMenu) { +	this._parentConstructor = WebFXMenuItem; +	this._parentConstructor(sText, sHref, sToolTip, oSubMenu); +} +WebFXMenuButton.prototype = new WebFXMenuItem; +WebFXMenuButton.prototype.toString = function () { +	return	"<a" + +			" id='" + this.id + "'" + +			" href='" + this.href + "'" + +			(this.toolTip ? " title='" + this.toolTip + "'" : "") + +			(webfxMenuUseHover ? +				(" onmouseover='webFXMenuHandler.overMenuItem(this)'" + +				" onmouseout='webFXMenuHandler.outMenuItem(this)'") : +				( +					" onfocus='webFXMenuHandler.overMenuItem(this)'" + +					(this.subMenu ? +						" onblur='webFXMenuHandler.blurMenu(this)'" : +						"" +					) +				)) + +			">" + +			(this.subMenu ? "<img class='arrow' src='" + webfxMenuImagePath + "arrow.right.png'>" : "") +				 +			this.text +  +			"</a>"; +}; + + + + + +/* Position functions */ + + +function getInnerLeft(el) { + +	if (el == null) return 0; + +	if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0; + +	return parseInt( getLeft(el) + parseInt(getBorderLeft(el)) ); + +} + + + +function getLeft(el, debug) { + +	if (el == null) return 0; + +        //if ( debug ) +	//  alert ( el.offsetLeft + ' - ' + getInnerLeft(el.offsetParent) ); + +	return parseInt( el.offsetLeft + parseInt(getInnerLeft(el.offsetParent)) ); + +} + + + +function getInnerTop(el) { + +	if (el == null) return 0; + +	if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0; + +	return parseInt( getTop(el) + parseInt(getBorderTop(el)) ); + +} + + + +function getTop(el) { + +	if (el == null) return 0; + +	return parseInt( el.offsetTop + parseInt(getInnerTop(el.offsetParent)) ); + +} + + + +function getBorderLeft(el) { + +	return ie ? + +		el.clientLeft : + +		( khtml  +		    ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width")) +		    : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-left-width"))  +		); + +} + + + +function getBorderTop(el) { + +	return ie ? + +		el.clientTop : + +		( khtml  +		    ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width")) +		    : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-top-width")) +		); + +} + + + +function opera_getLeft(el) { + +	if (el == null) return 0; + +	return el.offsetLeft + opera_getLeft(el.offsetParent); + +} + + + +function opera_getTop(el) { + +	if (el == null) return 0; + +	return el.offsetTop + opera_getTop(el.offsetParent); + +} + + + +function getOuterRect(el, debug) { + +	return { + +		left:	(opera ? opera_getLeft(el) : getLeft(el, debug)), + +		top:	(opera ? opera_getTop(el) : getTop(el)), + +		width:	el.offsetWidth, + +		height:	el.offsetHeight + +	}; + +} + + + +// mozilla bug! scrollbars not included in innerWidth/height + +function getDocumentRect(el) { + +	return { + +		left:	0, + +		top:	0, + +		width:	(ie ? + +					(ieBox ? document.body.clientWidth : document.documentElement.clientWidth) : + +					window.innerWidth + +				), + +		height:	(ie ? + +					(ieBox ? document.body.clientHeight : document.documentElement.clientHeight) : + +					window.innerHeight + +				) + +	}; + +} + + + +function getScrollPos(el) { + +	return { + +		left:	(ie ? + +					(ieBox ? document.body.scrollLeft : document.documentElement.scrollLeft) : + +					window.pageXOffset + +				), + +		top:	(ie ? + +					(ieBox ? document.body.scrollTop : document.documentElement.scrollTop) : + +					window.pageYOffset + +				) + +	}; + +} + + +/* end position functions */ + +WebFXMenu.prototype.position = function (relEl, sDir) { +	var dir = sDir; +	// find parent item rectangle, piRect +	var piRect; +	if (!relEl) { +		var pi = this.parentMenuItem; +		if (!this.parentMenuItem) +			return; +		 +		relEl = document.getElementById(pi.id); +		if (dir == null) +			dir = pi instanceof WebFXMenuButton ? "vertical" : "horizontal"; +		//alert('created RelEl from parent: ' + pi.id); +		piRect = getOuterRect(relEl, 1); +	} +	else if (relEl.left != null && relEl.top != null && relEl.width != null && relEl.height != null) {	// got a rect +		//alert('passed a Rect as RelEl: ' + typeof(relEl)); + +		piRect = relEl; +	} +	else { +		//alert('passed an element as RelEl: ' + typeof(relEl)); +		piRect = getOuterRect(relEl); +	} + +	var menuEl = document.getElementById(this.id); +	var menuRect = getOuterRect(menuEl); +	var docRect = getDocumentRect(); +	var scrollPos = getScrollPos(); +	var pMenu = this.parentMenu; +	 +	if (dir == "vertical") { +		if (piRect.left + menuRect.width - scrollPos.left <= docRect.width) { +			//alert('piRect.left: ' + piRect.left); +			this.left = piRect.left; +			if ( ! ie ) +			  this.left = this.left + 138; +		} else if (docRect.width >= menuRect.width) { +			//konq (not safari though) winds up here by accident and positions the menus all weird +			//alert('docRect.width + scrollPos.left - menuRect.width'); + +			this.left = docRect.width + scrollPos.left - menuRect.width; +		} else { +			//alert('scrollPos.left: ' + scrollPos.left); +			this.left = scrollPos.left; +		} +			 +		if (piRect.top + piRect.height + menuRect.height <= docRect.height + scrollPos.top) + +			this.top = piRect.top + piRect.height; + +		else if (piRect.top - menuRect.height >= scrollPos.top) + +			this.top = piRect.top - menuRect.height; + +		else if (docRect.height >= menuRect.height) + +			this.top = docRect.height + scrollPos.top - menuRect.height; + +		else + +			this.top = scrollPos.top; +	} +	else { +		if (piRect.top + menuRect.height - this.borderTop - this.paddingTop <= docRect.height + scrollPos.top) + +			this.top = piRect.top - this.borderTop - this.paddingTop; + +		else if (piRect.top + piRect.height - menuRect.height + this.borderTop + this.paddingTop >= 0) + +			this.top = piRect.top + piRect.height - menuRect.height + this.borderBottom + this.paddingBottom + this.shadowBottom; + +		else if (docRect.height >= menuRect.height) + +			this.top = docRect.height + scrollPos.top - menuRect.height; + +		else + +			this.top = scrollPos.top; + + + +		var pMenuPaddingLeft = pMenu ? pMenu.paddingLeft : 0; + +		var pMenuBorderLeft = pMenu ? pMenu.borderLeft : 0; + +		var pMenuPaddingRight = pMenu ? pMenu.paddingRight : 0; + +		var pMenuBorderRight = pMenu ? pMenu.borderRight : 0; + +		 + +		if (piRect.left + piRect.width + menuRect.width + pMenuPaddingRight + + +			pMenuBorderRight - this.borderLeft + this.shadowRight <= docRect.width + scrollPos.left) + +			this.left = piRect.left + piRect.width + pMenuPaddingRight + pMenuBorderRight - this.borderLeft; + +		else if (piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight >= 0) + +			this.left = piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight; + +		else if (docRect.width >= menuRect.width) + +			this.left = docRect.width  + scrollPos.left - menuRect.width; + +		else + +			this.left = scrollPos.left; +	} +}; diff --git a/httemplate/index.html b/httemplate/index.html index c8a46d08f..33083f6e5 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -168,7 +168,7 @@      <TR><TD>        <BR>        <!-- <BR>View active NAS ports:  -        <A HREF="browse/nas.cgi">session server</A> +        <A HREF="browse/nas.cgi">session server</A> -->          <!-- or <A HREF="browse/nas-sqlradius.cgi">RADIUS</A>        <BR> -->        <A HREF="search/queue.html">View pending job queue</A> @@ -177,7 +177,15 @@        <BR><A HREF="misc/dump.cgi">Download database dump</A>        <BR><BR><CENTER><HR WIDTH="94%" NOSHADE></CENTER><BR>        <A NAME="config" HREF="config/config-view.cgi">Configuration</a><!-- - <font size="+2" color="#ff0000">start here</font> --> -      <BR><BR><A NAME="admin">Provisioning, services and packages</a> +      <BR><BR> +      <A NAME="employees">Employees</A> +        <UL> +          <LI><A HREF="browse/access_user.html">View/Edit employees</A> +            - Setup internal users +          <LI><A HREF="browse/access_group.html">View/Edit employee groups</A> +            - Employee groups allow you to control access to the backend +        </UL> +      <A NAME="admin">Provisioning, services and packages</a>          <ul>            <LI><A HREF="browse/part_export.cgi">View/Edit exports</A>              - Provisioning services to external machines, databases and APIs. diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index b40869476..41537ee7e 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -1,8 +1,6 @@  <%= include("/elements/header.html", 'Quick payment entry',              menubar(                       'Main Menu' => $p, #popurl(1), -                     'Old-style quick payment entry' => -                       $p. 'search/cust_main-quickpay.html',                     ),              ( $cgi->param('error') ? '' : 'onload="addRow()"' ),            ) diff --git a/httemplate/misc/payment.cgi b/httemplate/misc/payment.cgi index d4fb4a2be..ec50c03f1 100644 --- a/httemplate/misc/payment.cgi +++ b/httemplate/misc/payment.cgi @@ -35,28 +35,18 @@  <INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>">  <INPUT TYPE="hidden" NAME="payby" VALUE="<%= $payby %>">  <INPUT TYPE="hidden" NAME="paybatch" VALUE="<%= $paybatch %>"> -<SCRIPT> -var mywindow = -1; -function myopen(filename,windowname,properties) { -  myclose(); -  mywindow = window.open(filename,windowname,properties); -} -function myclose() { -  if ( mywindow != -1 ) -    mywindow.close(); -  mywindow = -1; -} -var achwindow = -1; -function achopen(filename,windowname,properties) { -  achclose(); -  achwindow = window.open(filename,windowname,properties); -} -function achclose() { -  if ( achwindow != -1 ) -    achwindow.close(); -  achwindow = -1; + +<SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_iframe.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_draggable.js"></SCRIPT> +<SCRIPT TYPE="text/javascript"> +function OLiframeContent(src, width, height, name) { +  return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"' +   +(name?' name="'+name+'" id="'+name+'"':'')+' scrolling="auto">' +   +'<div>[iframe not supported]</div></iframe>');  }  </SCRIPT> +  <% #include( '/elements/table.html', '#cccccc' ) %>  <%= ntable('#cccccc') %>    <TR> @@ -112,7 +102,7 @@ function achclose() {    <TR>      <TD ALIGN="right">CVV2</TD>      <TD><INPUT TYPE="text" NAME="paycvv" VALUE="<%= $paycvv %>" SIZE=4 MAXLENGTH=4> -        (<A HREF="javascript:myopen('../docs/cvv2.html','cvv2','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,width=480,height=288')">help</A>) +        (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)      </TD>    </TR>    <TR> @@ -173,7 +163,7 @@ function achclose() {      <TD ALIGN="right">ABA/Routing number</TD>      <TD>        <INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="payinfo2" VALUE="<%=$payinfo2%>"> -      (<A HREF="javascript:achopen('../docs/ach.html','ach','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,width=384,height=256')">help</A>) +      (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)      </TD>    </TR>    <TR> @@ -205,5 +195,5 @@ function achclose() {  <BR>  <INPUT TYPE="submit" NAME="process" VALUE="Process payment">  </FORM> -</BODY> -</HTML> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/cust_bill.cgi b/httemplate/search/cust_bill.cgi deleted file mode 100755 index 5b0538ca3..000000000 --- a/httemplate/search/cust_bill.cgi +++ /dev/null @@ -1,165 +0,0 @@ -<% - -my $conf = new FS::Conf; -my $maxrecords = $conf->config('maxsearchrecordsperpage'); - -my $orderby = ''; #removeme - -my $limit = ''; -$limit .= "LIMIT $maxrecords" if $maxrecords; - -my $offset = $cgi->param('offset') || 0; -$limit .= " OFFSET $offset" if $offset; - -my($total, $tot_amount, $tot_balance); - -my(@cust_bill); -if ( $cgi->keywords ) { -  my($query) = $cgi->keywords; -  my $owed = "charged - ( select coalesce(sum(amount),0) from cust_bill_pay -                          where cust_bill_pay.invnum = cust_bill.invnum ) -                      - ( select coalesce(sum(amount),0) from cust_credit_bill -                          where cust_credit_bill.invnum = cust_bill.invnum )"; -  my @where; -  if ( $query =~ /^(OPEN(\d*)_)?(invnum|date|custnum)$/ ) { -    my($open, $days, $field) = ($1, $2, $3); -    $field = "_date" if $field eq 'date'; -    $orderby = "ORDER BY cust_bill.$field"; -    push @where, "0 != $owed" if $open; -    push @where, "cust_bill._date < ". (time-86400*$days) if $days; -  } else { -    die "unknown query string $query"; -  } - -  my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : ''; - -  my $statement = "SELECT COUNT(*), sum(charged), sum($owed) -                   FROM cust_bill $extra_sql"; -  my $sth = dbh->prepare($statement) or die dbh->errstr. " doing $statement"; -  $sth->execute or die "Error executing \"$statement\": ". $sth->errstr; - -  ( $total, $tot_amount, $tot_balance ) = @{$sth->fetchrow_arrayref}; - -  @cust_bill = qsearch( -    'cust_bill', -    {}, -    "cust_bill.*, $owed as owed", -    "$extra_sql $orderby $limit" -  ); -} else { -  $cgi->param('invnum') =~ /^\s*(FS-)?(\d+)\s*$/; -  my $invnum = $2; -  @cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum } ); -  $total = scalar(@cust_bill); -} - -#if ( scalar(@cust_bill) == 1 ) { -if ( $total == 1 ) { -  my $invnum = $cust_bill[0]->invnum; -  print $cgi->redirect(popurl(2). "view/cust_bill.cgi?$invnum");  #redirect -} elsif ( scalar(@cust_bill) == 0 ) { -%> -<!-- mason kludge --> -<% -  eidiot("Invoice not found."); -} else { -%> -<!-- mason kludge --> -<% - -  #begin pager -  my $pager = ''; -  if ( $total != scalar(@cust_bill) && $maxrecords ) { -    unless ( $offset == 0 ) { -      $cgi->param('offset', $offset - $maxrecords); -      $pager .= '<A HREF="'. $cgi->self_url. -                '"><B><FONT SIZE="+1">Previous</FONT></B></A> '; -    } -    my $poff; -    my $page; -    for ( $poff = 0; $poff < $total; $poff += $maxrecords ) { -      $page++; -      if ( $offset == $poff ) { -        $pager .= qq!<FONT SIZE="+2">$page</FONT> !; -      } else { -        $cgi->param('offset', $poff); -        $pager .= qq!<A HREF="!. $cgi->self_url. qq!">$page</A> !; -      } -    } -    unless ( $offset + $maxrecords > $total ) { -      $cgi->param('offset', $offset + $maxrecords); -      $pager .= '<A HREF="'. $cgi->self_url. -                '"><B><FONT SIZE="+1">Next</FONT></B></A> '; -    } -  } -  #end pager - -  print header("Invoice Search Results", menubar( -          'Main Menu', popurl(2) -        )). -        "$total matching invoices found<BR>". -        "\$$tot_balance total balance<BR>". -        "\$$tot_amount total amount<BR>". -        "<BR>$pager". table(). <<END; -      <TR> -        <TH></TH> -        <TH>Balance</TH> -        <TH>Amount</TH> -        <TH>Date</TH> -        <TH>Contact name</TH> -        <TH>Company</TH> -      </TR> -END - -  foreach my $cust_bill ( @cust_bill ) { -    my($invnum, $owed, $charged, $date ) = ( -      $cust_bill->invnum, -      sprintf("%.2f", $cust_bill->getfield('owed')), -      sprintf("%.2f", $cust_bill->charged), -      $cust_bill->_date, -    ); -    my $pdate = time2str("%b %d %Y", $date); - -    my $rowspan = 1; - -    my $view = popurl(2). "view/cust_bill.cgi?$invnum"; -    print <<END; -      <TR> -        <TD ROWSPAN=$rowspan><A HREF="$view">$invnum</A></TD> -        <TD ROWSPAN=$rowspan ALIGN="right"><A HREF="$view">\$$owed</A></TD> -        <TD ROWSPAN=$rowspan ALIGN="right"><A HREF="$view">\$$charged</A></TD> -        <TD ROWSPAN=$rowspan><A HREF="$view">$pdate</A></TD> -END -    my $custnum = $cust_bill->custnum; -    my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); -    if ( $cust_main ) { -      my $cview = popurl(2). "view/cust_main.cgi?". $cust_main->custnum; -      my ( $name, $company ) = ( -        $cust_main->last. ', '. $cust_main->first, -        $cust_main->company, -      ); -      print <<END; -        <TD ROWSPAN=$rowspan><A HREF="$cview">$name</A></TD> -        <TD ROWSPAN=$rowspan><A HREF="$cview">$company</A></TD> -END -    } else { -      print <<END -        <TD ROWSPAN=$rowspan COLSPAN=2>WARNING: couldn't find cust_main.custnum $custnum (cust_bill.invnum $invnum)</TD> -END -    } - -    print "</TR>"; -  } -  $tot_balance = sprintf("%.2f", $tot_balance); -  $tot_amount = sprintf("%.2f", $tot_amount); -  print "</TABLE>$pager<BR>". table(). <<END; -      <TR><TD>       </TD><TH>Total<BR>Balance</TH><TH>Total<BR>Amount</TH></TR> -      <TR><TD></TD><TD ALIGN="right">\$$tot_balance</TD><TD ALIGN="right">\$$tot_amount</TD></TD></TR> -    </TABLE> -  </BODY> -</HTML> -END - -} - -%> diff --git a/httemplate/search/cust_main-otaker.cgi b/httemplate/search/cust_main-otaker.cgi index 03c2619af..6ac0bde18 100755 --- a/httemplate/search/cust_main-otaker.cgi +++ b/httemplate/search/cust_main-otaker.cgi @@ -1,28 +1,23 @@ -<HTML> -  <HEAD> -    <TITLE>Customer Search</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Customer Search -    </FONT> -    <BR> -    <FORM ACTION="cust_main.cgi" METHOD="GET"> -      Search for <B>Order taker</B>:  -      <INPUT TYPE="hidden" NAME="otaker_on" VALUE="TRUE"> -      <% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main") -           or die dbh->errstr; -         $sth->execute() or die $sth->errstr; -#         my @otakers = map { $_->[0] } @{$sth->selectall_arrayref}; -      %> -      <SELECT NAME="otaker"> -      <% my $otaker; while ( $otaker = $sth->fetchrow_arrayref ) { %> -        <OPTION><%= $otaker->[0] %></OTAKER> -      <% } %> -      </SELECT> -      <P><INPUT TYPE="submit" VALUE="Search"> +<%= include('/elements/header.html', 'Customer Search' ) %> -    </FORM> -  </BODY> -</HTML> +<FORM ACTION="cust_main.cgi" METHOD="GET"> +Search for <B>Order taker</B>:  +  <INPUT TYPE="hidden" NAME="otaker_on" VALUE="TRUE"> + +<% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main") +     or die dbh->errstr; +   $sth->execute() or die $sth->errstr; +   #my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref}; +%> +<SELECT NAME="otaker"> +<% my $otaker; while ( $otaker = $sth->fetchrow_arrayref ) { %> +  <OPTION><%= $otaker->[0] %> +<% } %> +</SELECT> + +<P><INPUT TYPE="submit" VALUE="Search"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/cust_main-payinfo.html b/httemplate/search/cust_main-payinfo.html deleted file mode 100755 index b82b610d8..000000000 --- a/httemplate/search/cust_main-payinfo.html +++ /dev/null @@ -1,20 +0,0 @@ -<HTML> -  <HEAD> -    <TITLE>Customer Search</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Customer Search -    </FONT> -    <BR> -    <FORM ACTION="cust_main.cgi" METHOD="GET"> -      Search for <B>Credit card #</B>:  -      <INPUT TYPE="hidden" NAME="card_on" VALUE="TRUE"> -      <INPUT TYPE="text" NAME="card"> - -      <P><INPUT TYPE="submit" VALUE="Search"> - -    </FORM> -  </BODY> -</HTML> - diff --git a/httemplate/search/cust_main-quickpay.html b/httemplate/search/cust_main-quickpay.html deleted file mode 100755 index 154a64199..000000000 --- a/httemplate/search/cust_main-quickpay.html +++ /dev/null @@ -1,44 +0,0 @@ -<HTML> -  <HEAD> -    <TITLE>Quick payment entry</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Quick payment entry -    </FONT> -    <BR><BR> -    <A HREF="../">Main Menu</A><BR><BR> -    <FORM ACTION="cust_main.cgi" METHOD="GET"> -      <INPUT TYPE="hidden" NAME="quickpay" VALUE="yes"> -      <INPUT TYPE="checkbox" NAME="last_on" CHECKED> Search for <B>last name</B>:  -      <INPUT TYPE="text" NAME="last_text"> -      using search method: <SELECT NAME="last_type"> -        <OPTION SELECTED>All -        <OPTION>Fuzzy -        <OPTION>Substring -        <OPTION>Exact -      </SELECT> - -      <P><INPUT TYPE="checkbox" NAME="company_on" CHECKED> Search for <B>company</B>:  -      <INPUT TYPE="text" NAME="company_text"> -      using search method: <SELECT NAME="company_type"> -        <OPTION SELECTED>All -        <OPTION>Fuzzy -        <OPTION>Substring -        <OPTION>Exact -      </SELECT> - -      <P><INPUT TYPE="submit" VALUE="Search"> - -    </FORM> - -  <HR>Explanation of search methods: -  <UL> -    <LI><B>All</B> - Try all search methods. -    <LI><B>Fuzzy</B> - Searches for matches that are close to your text. -    <LI><B>Substring</B> - Searches for matches that contain your text. -    <LI><B>Exact</B> - Finds exact matches only, but much faster than the other search methods. -  </UL> -  </BODY> -</HTML> - diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi index 36ad39da8..8b70ff490 100755 --- a/httemplate/search/cust_main.cgi +++ b/httemplate/search/cust_main.cgi @@ -220,14 +220,13 @@ if ( scalar(@cust_main) == 1 && ! $cgi->param('referral_custnum') ) {    eidiot "No matching customers found!\n";  } else {   %> -<!-- mason kludge --> -<% +<%= include('/elements/header.html', "Customer Search Results", '' ) %> -  $total ||= scalar(@cust_main); -  print header("Customer Search Results",menubar( -    'Main Menu', popurl(2) -  )), "$total matching customers found "; +  <% $total ||= scalar(@cust_main); %> +  <%= $total %> matching customers found + +  <%    #begin pager    my $pager = '';    if ( $total != scalar(@cust_main) && $maxrecords ) { @@ -368,12 +367,14 @@ END      my $pcompany = $company        ? qq!<A HREF="$view"><FONT SIZE=-1>$company</FONT></A>!        : '<FONT SIZE=-1> </FONT>'; -    print <<END; +    %> +      <TR> -      <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$custnum</FONT></A></TD> -      <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$last, $first</FONT></A></TD> -      <TD ROWSPAN=$rowspan>$pcompany</TD> -END +      <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= $custnum %></FONT></A></TD> +      <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$last, $first" %></FONT></A></TD> +      <TD ROWSPAN=<%= $rowspan || 1 %>><%= $pcompany %></TD> + +    <%      if ( defined dbdef->table('cust_main')->column('ship_last') ) {        my($ship_last,$ship_first,$ship_company)=(          $cust_main->ship_last || $cust_main->getfield('last'), @@ -383,15 +384,18 @@ END        my $pship_company = $ship_company          ? qq!<A HREF="$view"><FONT SIZE=-1>$ship_company</FONT></A>!          : '<FONT SIZE=-1> </FONT>'; -      print <<END; -      <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$ship_last, $ship_first</FONT></A></TD> -      <TD ROWSPAN=$rowspan>$pship_company</A></TD> -END -    } +      %> -    foreach my $addl_col ( @addl_cols ) { -      print "<TD ROWSPAN=$rowspan ALIGN=right><FONT SIZE=-1>"; -      if ( $addl_col eq 'tickets' ) { +      <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$ship_last, $ship_first" %></FONT></A></TD> +      <TD ROWSPAN=<%= $rowspan || 1 %>><%= $pship_company %></A></TD> + +    <% } + +    foreach my $addl_col ( @addl_cols ) { %> + +      <TD ROWSPAN=<%= $rowspan || 1 %> ALIGN=right><FONT SIZE=-1> + +      <% if ( $addl_col eq 'tickets' ) {          if ( @custom_priorities ) {            print &itable('', 0);            foreach my $priority ( @custom_priorities, '' ) { @@ -461,10 +465,14 @@ END      }      print "</TR>";    } + +  %> -  print "</TABLE>$pager</BODY></HTML>"; +  </TABLE><%= $pager %> -} +  <%= include('/elements/footer.html') %> + +<% }  #undef $cache; #does this help? diff --git a/httemplate/search/cust_pay.html b/httemplate/search/cust_pay.html deleted file mode 100755 index 6414cf771..000000000 --- a/httemplate/search/cust_pay.html +++ /dev/null @@ -1,18 +0,0 @@ -<HTML> -  <HEAD> -    <TITLE>Check # Search</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Check # Search -    </FONT> -    <BR><BR> -    <FORM ACTION="cust_pay.cgi" METHOD="GET"> -      Search for <B>check #</B>: -      <INPUT TYPE="text" NAME="payinfo"> -      <INPUT TYPE="hidden" NAME="payby" VALUE="BILL"> -      <BR><BR><INPUT TYPE="submit" VALUE="Search"> -    </FORM> -  </BODY> -</HTML> - diff --git a/httemplate/search/cust_pkg_report.cgi b/httemplate/search/cust_pkg_report.cgi index 412c3f79d..d9aada5f4 100755 --- a/httemplate/search/cust_pkg_report.cgi +++ b/httemplate/search/cust_pkg_report.cgi @@ -1,23 +1,22 @@ -<HTML> -  <HEAD> -    <TITLE>Packages</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Packages</H1> -    <FORM ACTION="cust_pkg.cgi" METHOD="GET"> -    <INPUT TYPE="hidden" NAME="magic" VALUE="bill"> -      Return packages with next bill date:<BR><BR> -      <TABLE> -        <%= include( '/elements/tr-input-beginning_ending.html' ) %> -        <%= include( '/elements/tr-select-agent.html', -                       $cgi->param('agentnum'), -                   ) -        %> -      </TABLE> -      <BR><INPUT TYPE="submit" VALUE="Get Report"> +<%= include('/elements/header.html', 'Packages' ) %> -    </FORM> +<FORM ACTION="cust_pkg.cgi" METHOD="GET"> +<INPUT TYPE="hidden" NAME="magic" VALUE="bill"> -  </BODY> -</HTML> +Return packages with next bill date: +<BR><BR> +  <TABLE> +    <%= include( '/elements/tr-input-beginning_ending.html' ) %> +    <%= include( '/elements/tr-select-agent.html', +                   $cgi->param('agentnum'), +               ) +    %> +  </TABLE> + +<BR> +<INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_bill.html b/httemplate/search/report_cust_bill.html index a7be76689..f1b7bfa14 100644 --- a/httemplate/search/report_cust_bill.html +++ b/httemplate/search/report_cust_bill.html @@ -1,28 +1,28 @@ -  <HEAD> -    <TITLE>Invoice report criteria</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Invoice report criteria</H1> -    <FORM ACTION="cust_bill.html" METHOD="GET"> -    <INPUT TYPE="hidden" NAME="magic" VALUE="_date"> -    <TABLE> -      <%= include( '/elements/tr-select-agent.html', -                     $cgi->param('agentnum'), -                     'label' => 'Invoices for agent: ', -                 ) -      %> -      <%= include( '/elements/tr-input-beginning_ending.html' ) %> -      <TR> -        <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="open" VALUE="1" CHECKED></TD> -        <TD>Show only open invoices</TD> -      </TR> -      <TR> -        <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="newest_percust" VALUE="1"></TD> -        <TD>Show only the single most recent invoice per-customer</TD> -      </TR> -    </TABLE> -    <BR><INPUT TYPE="submit" VALUE="Get Report"> -    </FORM> -  </BODY> -</HTML> +<%= include('/elements/header.html', 'Invoice report criteria' ) %> +<FORM ACTION="cust_bill.html" METHOD="GET"> +<INPUT TYPE="hidden" NAME="magic" VALUE="_date"> + +<TABLE> +  <%= include( '/elements/tr-select-agent.html', +                 $cgi->param('agentnum'), +                 'label' => 'Invoices for agent: ', +             ) +  %> +  <%= include( '/elements/tr-input-beginning_ending.html' ) %> +  <TR> +    <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="open" VALUE="1" CHECKED></TD> +    <TD>Show only open invoices</TD> +  </TR> +  <TR> +    <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="newest_percust" VALUE="1"></TD> +    <TD>Show only the single most recent invoice per-customer</TD> +  </TR> +</TABLE> + +<BR> +<INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_credit.html b/httemplate/search/report_cust_credit.html index 56bbd0ac0..8ca52dc9a 100644 --- a/httemplate/search/report_cust_credit.html +++ b/httemplate/search/report_cust_credit.html @@ -1,36 +1,38 @@ -<HTML> -  <HEAD> -    <TITLE>Credit report criteria</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Credit report criteria</H1> -    <FORM ACTION="cust_credit.html" METHOD="GET"> -    <INPUT TYPE="hidden" NAME="magic" VALUE="_date"> -    <TABLE> -      <TR> -        <TD ALIGN="right">Credits by employee: </TD> +<%= include('/elements/header.html', 'Credit report' ) %> + +<FORM ACTION="cust_credit.html" METHOD="GET"> +<INPUT TYPE="hidden" NAME="magic" VALUE="_date"> + +<TABLE> +  <TR> +    <TD ALIGN="right">Credits by employee: </TD> +  <%    my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_credit")      or die dbh->errstr;    $sth->execute or die $sth->errstr;    my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref};  %> -        <TD><SELECT NAME="otaker"> -              <OPTION VALUE="">all</OPTION> -              <% foreach my $otaker ( @otakers ) { %> -                <OPTION VALUE="<%= $otaker %>"><%= $otaker %></OPTION> -              <% } %> -            </SELECT> -        </TD> -      </TR> -      <%= include( '/elements/tr-select-agent.html', -                     $cgi->param('agentnum'), -                     'label' => 'for agent: ', -                 ) -      %> -      <%= include( '/elements/tr-input-beginning_ending.html' ) %> -    </TABLE> -    <BR><INPUT TYPE="submit" VALUE="Get Report"> -    </FORM> -  </BODY> -</HTML> + +    <TD><SELECT NAME="otaker"> +          <OPTION VALUE="">all</OPTION> +          <% foreach my $otaker ( @otakers ) { %> +            <OPTION VALUE="<%= $otaker %>"><%= $otaker %></OPTION> +          <% } %> +        </SELECT> +    </TD> +  </TR> +  <%= include( '/elements/tr-select-agent.html', +                 $cgi->param('agentnum'), +                 'label' => 'for agent: ', +             ) +  %> +  <%= include( '/elements/tr-input-beginning_ending.html' ) %> +</TABLE> + +<BR> +<INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_pay.html b/httemplate/search/report_cust_pay.html index 5d8b74e77..8adf7dc13 100644 --- a/httemplate/search/report_cust_pay.html +++ b/httemplate/search/report_cust_pay.html @@ -1,38 +1,43 @@ -<HTML> -  <HEAD> -    <TITLE>Payment report criteria</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Payment report criteria</H1> -    <FORM ACTION="cust_pay.cgi" METHOD="GET"> -    <INPUT TYPE="hidden" NAME="magic" VALUE="_date"> -    <TABLE> -      <TR> -        <TD ALIGN="right">Payments of type: </TD> -        <TD><SELECT NAME="payby"> -              <OPTION VALUE="">all</OPTION> -              <OPTION VALUE="CARD">credit card (all)</OPTION> -              <OPTION VALUE="CARD-VisaMC">credit card (Visa/MasterCard)</OPTION> -              <OPTION VALUE="CARD-Amex">credit card (American Express)</OPTION> -              <OPTION VALUE="CARD-Discover">credit card (Discover)</OPTION> -              <OPTION VALUE="CARD-Maestro">credit card (Maestro/Switch/Solo)</OPTION> -              <OPTION VALUE="CHEK">electronic check / ACH</OPTION> -              <OPTION VALUE="BILL">check</OPTION> -              <OPTION VALUE="PREP">prepaid card</OPTION> -              <OPTION VALUE="CASH">cash</OPTION> -              <OPTION VALUE="WEST">Western Union</OPTION> -              <OPTION VALUE="MCRD">manual credit card</OPTION> -            </SELECT> -        </TD> -      </TR> -      <%= include( '/elements/tr-select-agent.html', -                     $cgi->param('agentnum'), -                     'label' => 'for agent: ', -                 ) -      %> -      <%= include( '/elements/tr-input-beginning_ending.html' ) %> -    </TABLE> -    <BR><INPUT TYPE="submit" VALUE="Get Report"> -    </FORM> -  </BODY> -</HTML> +<%= include('/elements/header.html', 'Payment report' ) %> + +<FORM ACTION="cust_pay.cgi" METHOD="GET"> +<INPUT TYPE="hidden" NAME="magic" VALUE="_date"> + +<TABLE> + +  <TR> +    <TD ALIGN="right">Payments of type: </TD> +    <TD> +      <SELECT NAME="payby"> +        <OPTION VALUE="">all</OPTION> +        <OPTION VALUE="CARD">credit card (all)</OPTION> +        <OPTION VALUE="CARD-VisaMC">credit card (Visa/MasterCard)</OPTION> +        <OPTION VALUE="CARD-Amex">credit card (American Express)</OPTION> +        <OPTION VALUE="CARD-Discover">credit card (Discover)</OPTION> +        <OPTION VALUE="CARD-Maestro">credit card (Maestro/Switch/Solo)</OPTION> +        <OPTION VALUE="CHEK">electronic check / ACH</OPTION> +        <OPTION VALUE="BILL">check</OPTION> +        <OPTION VALUE="PREP">prepaid card</OPTION> +        <OPTION VALUE="CASH">cash</OPTION> +        <OPTION VALUE="WEST">Western Union</OPTION> +        <OPTION VALUE="MCRD">manual credit card</OPTION> +      </SELECT> +    </TD> +  </TR> + +  <%= include( '/elements/tr-select-agent.html', +                 $cgi->param('agentnum'), +                 'label' => 'for agent: ', +             ) +  %> + +  <%= include( '/elements/tr-input-beginning_ending.html' ) %> + +</TABLE> + +<BR> +<INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_prepaid_income.html b/httemplate/search/report_prepaid_income.html index 57c318eba..4359918f9 100644 --- a/httemplate/search/report_prepaid_income.html +++ b/httemplate/search/report_prepaid_income.html @@ -1,13 +1,13 @@ -<HTML> -  <HEAD> -    <TITLE>Prepaid Income (Unearned Revenue) Report</TITLE> -    <LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2"> -    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT> -    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT> -    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Prepaid Income (Unearned Revenue) Report</H1> +<%= include('/elements/header.html', 'Prepaid Income (Unearned Revenue) Report', +  '', +  '', +  '<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2"> +  <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT> +  <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT> +  <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT> +  ' +) %> +      <FORM ACTION="report_prepaid_income.cgi" METHOD="GET">      <TABLE>        <TR> @@ -32,8 +32,6 @@    });  </SCRIPT> -    <INPUT TYPE="submit" VALUE="Generate report"> -  </BODY> -</HTML> -    <TABLE> +<INPUT TYPE="submit" VALUE="Generate report"> +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_tax.html b/httemplate/search/report_tax.html index 7a8ecd4f0..bdeb8e237 100755 --- a/httemplate/search/report_tax.html +++ b/httemplate/search/report_tax.html @@ -1,40 +1,35 @@ -<HTML> -  <HEAD> -    <TITLE>Tax Report Criteria</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <H1>Tax Report Criteria</H1> -    <FORM ACTION="report_tax.cgi" METHOD="GET"> - -    <TABLE> - -     <%= include( '/elements/tr-select-agent.html' ) %> - -     <%= include( '/elements/tr-input-beginning_ending.html' ) %> - -     <% my $conf = new FS::Conf; -        if ( $conf->exists('enable_taxclasses') ) { -     %> -       <TR> -         <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_taxclasses" VALUE="1"></TD> -         <TD>Show tax classes</TD> -       </TR> -     <% } %> - -     <% my @pkg_class = qsearch('pkg_class', {}); -        if ( @pkg_class ) { -     %> -       <TR> -         <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_pkgclasses" VALUE="1"></TD> -         <TD>Show package classes</TD> -       </TR> -     <% } %> - -    </TABLE> - -    <BR><INPUT TYPE="submit" VALUE="Get Report"> -    </FORM> - -  </BODY> -</HTML> +<%= include('/elements/header.html', 'Tax Report' ) %> +<FORM ACTION="report_tax.cgi" METHOD="GET"> + +<TABLE> + + <%= include( '/elements/tr-select-agent.html' ) %> + + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + + <% my $conf = new FS::Conf; +    if ( $conf->exists('enable_taxclasses') ) { + %> +   <TR> +     <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_taxclasses" VALUE="1"></TD> +     <TD>Show tax classes</TD> +   </TR> + <% } %> + + <% my @pkg_class = qsearch('pkg_class', {}); +    if ( @pkg_class ) { + %> +   <TR> +     <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_pkgclasses" VALUE="1"></TD> +     <TD>Show package classes</TD> +   </TR> + <% } %> + +</TABLE> + +<BR><INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/sqlradius.html b/httemplate/search/sqlradius.html index 8f4878dbc..645505101 100644 --- a/httemplate/search/sqlradius.html +++ b/httemplate/search/sqlradius.html @@ -1,9 +1,5 @@ -<%= include( '/elements/header.html', 'Search RADIUS sessions', '', '', ' -<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2"> -<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT> -<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT> -<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT> -') %> +<%= include( '/elements/header.html', 'Search RADIUS sessions' ) %> +  <FORM NAME="OneTrueForm" ACTION="sqlradius.cgi" METHOD="GET">  <% #include( '/elements/table.html' ) %>  <%= ntable('#cccccc') %> @@ -47,48 +43,10 @@    </TR>  <% } %> -<TR> -  <TD ALIGN="right">From: </TD> -  <TD> -    <INPUT TYPE="text" NAME="beginning" ID="beginning_text" VALUE="" SIZE=11 MAXLENGTH=10> <IMG SRC="../images/calendar.png" ID="beginning_button" STYLE="cursor: pointer" TITLE="Select date"> -  </TD> -  <SCRIPT TYPE="text/javascript"> -    Calendar.setup({ -      inputField: "beginning_text", -      ifFormat:   "%m/%d/%Y", -      button:     "beginning_button", -      align:      "BR" -    }); -  </SCRIPT> -</TR> -<TR> -  <TD></TD> -  <TD><i>m/d/y</i></TD> -</TR> -<TR> -  <TD ALIGN="right">To: </TD> -  <TD> -    <INPUT TYPE="text" NAME="ending" ID="ending_text" VALUE="" SIZE=11 MAXLENGTH=10> <IMG SRC="../images/calendar.png" ID="ending_button" STYLE="cursor:pointer" TITLE="Select date"> -  </TD> -  <SCRIPT TYPE="text/javascript"> -    Calendar.setup({ -      inputField: "ending_text", -      ifFormat:   "%m/%d/%Y", -      button:     "ending_button", -      align:      "BR" -    }); -  </SCRIPT> -</TR> -<TR> -  <TD></TD> -  <TD><i>m/d/y</i> -  <BR><FONT SIZE="-1">(leave one or both dates blank for an open-ended search)</FONT> -  </TD> -</TR> +<%= include( '/elements/tr-input-beginning_ending.html' ) %> +  </TABLE>  <BR><INPUT TYPE="submit" VALUE="View sessions">  </FORM> -</BODY> -</HTML> - +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/svc_acct.html b/httemplate/search/svc_acct.html deleted file mode 100755 index c504c2f34..000000000 --- a/httemplate/search/svc_acct.html +++ /dev/null @@ -1,19 +0,0 @@ -<HTML> -  <HEAD> -    <TITLE>Account Search</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Account Search -    </FONT> -    <BR><BR> -    <FORM ACTION="svc_acct.cgi" METHOD="GET"> -      Search for <B>username</B>:  -      <INPUT TYPE="text" NAME="username"> - -      <P><INPUT TYPE="submit" VALUE="Search"> - -    </FORM> -  </BODY> -</HTML> - diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi index f261ea9f3..b02eea8bd 100755 --- a/httemplate/search/svc_domain.cgi +++ b/httemplate/search/svc_domain.cgi @@ -61,7 +61,7 @@ my $link_cust = sub {    $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';  }; -%><%= include ('elements/search.html', +%><%= include( 'elements/search.html',                   'title'             => "Domain Search Results",                   'name'              => 'domains',                   'query'             => $sql_query, diff --git a/httemplate/search/svc_domain.html b/httemplate/search/svc_domain.html deleted file mode 100755 index b759102f4..000000000 --- a/httemplate/search/svc_domain.html +++ /dev/null @@ -1,19 +0,0 @@ -<HTML> -  <HEAD> -    <TITLE>Domain Search</TITLE> -  </HEAD> -  <BODY BGCOLOR="#e8e8e8"> -    <FONT SIZE=7> -      Domain Search -    </FONT> -    <BR><BR> -    <FORM ACTION="svc_domain.cgi" METHOD="GET"> -      Search for <B>domain</B>:  -      <INPUT TYPE="text" NAME="domain"> - -      <P><INPUT TYPE="submit" VALUE="Search"> - -    </FORM> -  </BODY> -</HTML> - diff --git a/httemplate/search/svc_external.cgi b/httemplate/search/svc_external.cgi index 8dbb949c8..7968f3c43 100755 --- a/httemplate/search/svc_external.cgi +++ b/httemplate/search/svc_external.cgi @@ -38,17 +38,18 @@ if ( $query eq 'svcnum' ) {  }  if ( scalar(@svc_external) == 1 ) { -  print $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum); -  #exit; + +  %><%= $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum) %><% +  } elsif ( scalar(@svc_external) == 0 ) { -%> -<!-- mason kludge --> -<% -  eidiot "No matching external services found!\n"; -} else { -%> -<!-- mason kludge --> -<%= include("/elements/header.html","External Search Results",'') %> + +  %><%= include('/elements/header.html', 'External Search Results' ) %> + +  No matching external services found + +<% } else { + +  %><%= include('/elements/header.html', 'External Search Results', '') %>      <%= scalar(@svc_external) %> matching external services found      <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0> diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index ece1b62bb..32e0ee1fc 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -67,7 +67,7 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) {  <!--pkgnum: <%=$pkg->{pkgnum}%>-->  <TR> -  <TD ROWSPAN=<%=$rowspan%>> +  <TD ROWSPAN=<%= $rowspan || 1 %>>      <A NAME="cust_pkg<%=$pkg->{pkgnum}%>"><%=$pkg->{pkgnum}%></A>:      <%=$pkg->{pkg}%> - <%=$pkg->{comment}%><BR>  <% unless ($pkg->{cancel}) { %> @@ -75,7 +75,7 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) {      ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg,$cust_main->custnum)%> )  <% } %>    </TD> -  <TD ROWSPAN=<%=$rowspan%>> +  <TD ROWSPAN=<%= $rowspan || 1 %>>      <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">  <% diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index a0bec3906..f0cd993ff 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -58,7 +58,10 @@  <% } %> -<BR><A HREF="<%= $p %>edit/cust_credit.cgi?<%= $custnum %>">Post credit</A> +<BR> + +<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('<%= $p %>edit/cust_credit.cgi?<%= $custnum %>', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">Post credit</A> +  <BR>  <% @@ -115,8 +118,10 @@ foreach my $cust_pay ($cust_main->cust_pay) {      #completely unapplied      $pre = '<B><FONT COLOR="#FF0000">Unapplied ';      $post = '</FONT></B>'; -    $apply = qq! (<A HREF="${p}edit/cust_bill_pay.cgi?!. -             $cust_pay->paynum. '">apply</A>)'; +    $apply = qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_bill_pay.cgi?!. +             $cust_pay->paynum. +             qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!; +    } elsif (    scalar(@cust_bill_pay)   == 1              && scalar(@cust_pay_refund) == 0              && $cust_pay->unapplied == 0     ) { @@ -151,8 +156,9 @@ foreach my $cust_pay ($cust_main->cust_pay) {        $desc .= '  '.                 '<B><FONT COLOR="#FF0000">$'.                 $cust_pay->unapplied. ' unapplied</FONT></B>'. -               qq! (<A HREF="${p}edit/cust_bill_pay.cgi?!. -               $cust_pay->paynum. '">apply</A>)'. +               qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_bill_pay.cgi?!. +               $cust_pay->paynum.  +               qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!.                 '<BR>';      }    } @@ -264,8 +270,9 @@ foreach my $cust_credit ($cust_main->cust_credit) {      #completely unapplied      $pre = '<B><FONT COLOR="#FF0000">Unapplied ';      $post = '</FONT></B>'; -    $apply = qq! (<A HREF="${p}edit/cust_credit_bill.cgi?!. -             $cust_credit->crednum. '">apply</A>)'; +    $apply = qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_credit_bill.cgi?!. +             $cust_credit->crednum. +             qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!;    } elsif (    scalar(@cust_credit_bill)   == 1              && scalar(@cust_credit_refund) == 0              && $cust_credit->credited == 0      ) { @@ -299,8 +306,9 @@ foreach my $cust_credit ($cust_main->cust_credit) {      if ( $cust_credit->credited > 0 ) {        $desc .= '  <B><FONT COLOR="#FF0000">$'.                 $cust_credit->credited. ' unapplied</FONT></B>'. -               qq! (<A HREF="${p}edit/cust_credit_bill.cgi?!. -               $cust_credit->crednum. '">apply</A>)'. +               qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_credit_bill.cgi?!. +               $cust_credit->crednum. +               qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!.                 '<BR>';      }    } | 
