%doc>
Example:
 include( 'elements/process.html',
   ###
   # required
   ###
  'table' => 'tablename',
   #? 'primary_key' => #required when the dbdef doesn't know...???
   #? 'fields' => []   #""
   ###
   # optional
   ###
   'viewall_dir'  => '', #'search' or 'browse', defaults to 'search'
   OR
   'redirect'     => 'view/table.cgi?', # value of primary key is appended
                                        # (string or coderef returning a string)
   OR
   'popup_reload' => 'Momentary success message', #will reload parent window
   'error_redirect' => popurl(2).'edit/table.cgi?', #query string appended
   'edit_ext' => 'html', #defaults to 'html', you might want 'cgi' while the
                         #naming is still inconsistent
   'copy_on_empty'  => [ 'old_field_name', 'another_old_field', ... ],
   'clear_on_error' => [ 'form_field1', 'form_field2', ... ],
                  #pass an arrayref of hashrefs for multiple m2ms or m2names
                  #be certain you incorporate m2m_Common if you see error: param
   'process_m2m' => { 'link_table'   => 'link_table_name',
                      'target_table' => 'target_table_name',
                      #optional (see m2m_Common::process_m2m), if not specified
                      # all CGI params will be passed)
                      'params'       => 
                    },
   'process_m2name' => { 'link_table'   => 'link_table_name',
                         'link_static' => { 'column' => 'value' },
                         'num_col' => 'column', #if column name is different in
                                                #link_table than source_table 
                         'name_col' => 'name_column',
                         'names_list' => [ 'list', 'names' ],
                         
                         'param_style' => 'link_table.value checkboxes',
                         #or#
                         'param_style' => 'name_colN values',
                       },
   #checks CGI params and whatever else before much else runs
   #return an error string or empty for no error
   'precheck_callback' => sub { my( $cgi ) = @_; },
   #supplies arguments to insert() and replace()
   # for use with tables that are FS::option_Common
   'args_callback' => sub { my( $cgi, $object ) = @_; },
   'debug' => 1, #turns on debugging output
   #agent virtualization
   'agent_virt'       => 1,
   'agent_null_right' => 'Access Right Name',
 )
%doc>
%if ( $error ) {
%
%  my $edit_ext = $opt{'edit_ext'} || 'html';
%  my $url = $opt{'error_redirect'} || popurl(2)."$table.$edit_ext";
%  if ( length($cgi->query_string) > 1920 ) { #stupid IE 2083 URL limit
% 
%    my $session = int(rand(4294967296)); #XXX
%    my $pref = new FS::access_user_pref({
%      'usernum'    => $FS::CurrentUser::CurrentUser->usernum,
%      'prefname'   => "redirect$session",
%      'prefvalue'  => $cgi->query_string,
%      'expiration' => time + 3600, #1h?  1m?
%    });
%    my $pref_error = $pref->insert;
%    if ( $pref_error ) {
%      die "FATAL: couldn't even set redirect cookie: $pref_error".
%          " attempting to set redirect$session to ". $cgi->query_string."\n";
%    }
%
<% $cgi->redirect("$url?redirect=$session") %>
%
%  } else {
%
<% $cgi->redirect("$url?". $cgi->query_string ) %>
%
%  } 
%
% #different ways of handling success
%
%} elsif ( $opt{'popup_reload'} ) {
  <% include('/elements/header-popup.html', $opt{'popup_reload'} ) %>