Topic: Problem with editing customer contacts

Begin e.g. by creating a new customer. If I then try to edit the contact information for this customer (in the tab "Contacts") I always get the error message "The contact name cannot be empty", even though I did not commit this error.

Here is a link to the screenshots that illustrate the problem: http://shares.jansson-fam.se/s#27218b90-96ce-4e18-91b5-2a8547eea422/bo.clouddrive.jansson-fam.se/FA_Errors/

Note: Scroll to the images "Customer*.png"

Re: Problem with editing customer contacts

You are right. We are looking into this.

/Joe

Re: Problem with editing customer contacts

This has now been fixed.

If you need the fix then please download ui_controls.inc and replace in

/includes/ui/ui_controls.inc

/Joe

Post's attachments

ui_controls.inc 16.2 kb, 100 downloads since 2015-04-04 

You don't have the permssions to download the attachments of this post.

Re: Problem with editing customer contacts

Thanks for your quick response and clear instruction how to implement your patch!
Now it works as expected.
I look forward to an equally clear instruction later regarding 'Security Role Clone / Addition errors on the edit / save'.
Best regards!

Re: Problem with editing customer contacts

Thanks joe for the quick fix but i wonder why its not included in the v2.3.24 released?

Re: Problem with editing customer contacts

The bug was first detected after the 2.3.24 release :-(

Joe

7 (edited by RandomName 06/29/2015 04:38:55 pm)

Re: Problem with editing customer contacts

I downloaded the latest version (few days back) and this bug is still there.

https:/sourceforge.net/projects/frontaccounting/files/latest/download
frontaccounting-2.3.24.tar.gz

Re: Problem with editing customer contacts

This bug was first detected after the release of 2.3.24.

Please use the link 5 posts earlier and replace your download, /includes/ui/ui_controls.inc, in your setup.

Joe

9 (edited by RandomName 07/01/2015 08:17:03 am)

Re: Problem with editing customer contacts

joe wrote:

This bug was first detected after the release of 2.3.24.

Please use the link 5 posts earlier and replace your download, /includes/ui/ui_controls.inc, in your setup.

Joe

I did that.
You got about 30-50 download per day?  Why not release 2.3.24.1 and save hundreds of people hundreds of hours?

Re: Problem with editing customer contacts

Eek! Thanks for this fix from me too! I was wondering if I was doing something wrong.

Marc

Re: Problem with editing customer contacts

Here it the patch so you do not have to register to download the file


<?php
/**********************************************************************
    Copyright (C) FrontAccounting, LLC.
    Released under the terms of the GNU General Public License, GPL, 
    as published by the Free Software Foundation, either version 3 
    of the License, or (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
    See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
***********************************************************************/
/*
    Retrieve value of POST variable(s).
    For $name passed as array $dflt is not used, 
    default values can be passed as values with non-numeric keys instead.
    If some field have user formatted numeric value, pass float default value to
    convert automatically to POSIX.
*/
function get_post($name, $dflt='')
{
    if (is_array($name)) {
        $ret = array();
        foreach($name as $key => $dflt)
            if (!is_numeric($key)) {
                $ret[$key] = is_float($dflt) ? input_num($key, $dflt) : get_post($key, $dflt);
            } else {
                $ret[$dflt] = get_post($dflt, null);
            }
        return $ret;
    } else
        return is_float($dflt) ? input_num($name, $dflt) : 
                ((!isset($_POST[$name]) || $_POST[$name] === '') ? $dflt : $_POST[$name]);
}
//---------------------------------------------------------------------------------

function start_form($multi=false, $dummy=false, $action="", $name="")
{
    // $dummy - leaved for compatibility with 2.0 API

    if ($name != "")
        $name = "name='$name'";
    if ($action == "")
        $action = $_SERVER['PHP_SELF'];

    if ($multi)
        echo "<form enctype='multipart/form-data' method='post' action='$action' $name>\n";
    else
        echo "<form method='post' action='$action' $name>\n";

}

/*
    Flush hidden fields buffer.
*/
function output_hidden()
{
    global $hidden_fields;

    if (is_array($hidden_fields))
        echo implode('', $hidden_fields);
    $hidden_fields = array();
}
//---------------------------------------------------------------------------------

function end_form($breaks=0)
{
    global $Ajax, $hidden_fields;

    $_SESSION['csrf_token'] = hash('sha256', uniqid(mt_rand(), true));
    if ($breaks)
        br($breaks);
    hidden('_focus');
    hidden('_modified', get_post('_modified', 0));
    hidden('_token', $_SESSION['csrf_token']);
    
    output_hidden();
    echo "</form>\n";
    $Ajax->activate('_token');
}

function check_csrf_token()
{
    if ($_SESSION['csrf_token'] != @$_POST['_token'])
    {
        display_error(_("Request from outside of this page is forbidden."));
        error_log(_("CSRF attack detected from: ").@$_SERVER['HTTP_HOST'].' ('.@$_SERVER['HTTP_REFERER'].')');
        return false;
    }
    return true;
}

function start_table($class=false, $extra="", $padding='2', $spacing='0')
{
    echo "<center><table";
    if ($class == TABLESTYLE_NOBORDER)
        echo " class='tablestyle_noborder'";
    elseif ($class == TABLESTYLE2)
        echo " class='tablestyle2'";
    elseif ($class == TABLESTYLE)
        echo " class='tablestyle'";
    if ($extra != "")
        echo " $extra";
    echo " cellpadding='$padding' cellspacing='$spacing'>\n";
}

function end_table($breaks=0)
{
    echo "</table></center>\n";
    output_hidden();
    if ($breaks)
        br($breaks);
}

function start_outer_table($class=false, $extra="", $padding='2', $spacing='0', $br=false)
{
    if ($br)
        br();
    start_table($class, $extra, $padding, $spacing);
    echo "<tr valign=top><td>\n"; // outer table
}

function table_section($number=1, $width=false)
{
    if ($number > 1)
    {
        echo "</table>\n";
        output_hidden();
        $width = ($width ? "width='$width'" : "");
        //echo "</td><td class='tableseparator' $width>\n"; // outer table
        echo "</td><td style='border-left:1px solid #cccccc;' $width>\n"; // outer table
    }
    echo "<table class='tablestyle_inner'>\n";
}    

function end_outer_table($breaks=0, $close_table=true)
{
    if ($close_table)
    {
        echo "</table>\n";
        output_hidden();
    }
    echo "</td></tr>\n";
    end_table($breaks);
}
//
//  outer table spacer
//
function vertical_space($params='')
{
    echo "</td></tr><tr><td valign=center $params>";
}

function meta_forward($forward_to, $params="")
{
    global $Ajax;
    echo "<meta http-equiv='Refresh' content='0; url=$forward_to?$params'>\n";
    echo "<center><br>" . _("You should automatically be forwarded.");
    echo " " . _("If this does not happen") . " " . "<a href='$forward_to?$params'>" . _("click here") . "</a> " . _("to continue") . ".<br><br></center>\n";
    if ($params !='') $params = '?'.$params;
    $Ajax->redirect($forward_to.$params);
    exit;
}

//-----------------------------------------------------------------------------------
// Find and replace hotkey marker.
// if $clean == true marker is removed and clean label is returned 
// (for use in wiki help system), otherwise result is array of label 
// with underlined hotkey letter and access property string.
//
function access_string($label, $clean=false)
{
    $access = '';
    $slices = array();

    if (preg_match('/(.*)&([a-zA-Z0-9])(.*)/', $label, $slices))    
    {
        $label = $clean ? $slices[1].$slices[2].$slices[3] :
            $slices[1].'<u>'.$slices[2].'</u>'.$slices[3];
        $access = " accesskey='".strtoupper($slices[2])."'";
    }
    
    $label = str_replace( '&&', '&', $label);

    return $clean ? $label : array($label, $access);
}

function hyperlink_back($center=true, $no_menu=true, $type_no=0, $trans_no=0, $final=false)
{
    global $path_to_root;

    if ($center)
        echo "<center>";
    $id = 0;    
    if ($no_menu && $trans_no != 0)
    {
        include_once($path_to_root."/admin/db/attachments_db.inc");
        $id = has_attachment($type_no, $trans_no);
        $attach = get_attachment_string($type_no, $trans_no);
        echo $attach;    
    }
    $width = ($id != 0 ? "30%" : "20%");    
    start_table(false, "width='$width'");
    start_row();
    if ($no_menu)
    {
        echo "<td align=center><a href='javascript:window.print();'>"._("Print")."</a></td>\n";
    }
    echo "<td align=center><a href='javascript:goBack(".($final ? '-2' : '').");'>".($no_menu ? _("Close") : _("Back"))."</a></td>\n";
    end_row();
    end_table();
    if ($center)
        echo "</center>";
    echo "<br>";
}

function hyperlink_no_params($target, $label, $center=true)
{
    $id = default_focus();
    $pars = access_string($label);
    if ($target == '')
        $target = $_SERVER['PHP_SELF'];
    if ($center)
        echo "<br><center>";
    echo "<a href='$target' id='$id' $pars[1]>$pars[0]</a>\n";
    if ($center)
        echo "</center>";
}

function hyperlink_no_params_td($target, $label)
{
    echo "<td>";
    hyperlink_no_params($target, $label);
    echo "</td>\n";
}

function viewer_link($label, $url='', $class='', $id='',  $icon=null)
{
    global $path_to_root;
    
    if ($class != '')
        $class = " class='$class'";

    if ($id != '')
        $class = " id='$id'";

    if ($url != "")
    {
        $pars = access_string($label);
        if (user_graphic_links() && $icon)
            $pars[0] = set_icon($icon, $pars[0]);
        $preview_str = "<a target='_blank' $class $id href='$path_to_root/$url' onclick=\"javascript:openWindow(this.href,this.target); return false;\"$pars[1]>$pars[0]</a>";
    }
    else
        $preview_str = $label;
 return $preview_str;
}

function menu_link($url, $label, $id=null)
{

    $id = default_focus($id);
    $pars = access_string($label);
    return "<a href='$url' class='menu_option' id='$id' $pars[1]>$pars[0]</a>";
}

function submenu_option($title, $url, $id=null)
{
    global $path_to_root;
    display_note(menu_link($path_to_root . $url, $title, $id), 0, 1);
}

function submenu_view($title, $type, $number, $id=null)
{
    display_note(get_trans_view_str($type, $number, $title, false, 'viewlink', $id), 0, 1);
}

function submenu_print($title, $type, $number, $id=null, $email=0, $extra=0)
{
    display_note(print_document_link($number, $title, true, $type, false, 'printlink', $id, $email, $extra), 0, 1);
}
//-----------------------------------------------------------------------------------

function hyperlink_params($target, $label, $params, $center=true)
{
    $id = default_focus();
    
    $pars = access_string($label);
    if ($target == '')
        $target = $_SERVER['PHP_SELF'];
    if ($center)
        echo "<br><center>";
    echo "<a id='$id' href='$target?$params'$pars[1]>$pars[0]</a>\n";
    if ($center)
        echo "</center>";
}

function hyperlink_params_td($target, $label, $params)
{
    echo "<td>";
    hyperlink_params($target, $label, $params, false);
    echo "</td>\n";
}

//-----------------------------------------------------------------------------------

function hyperlink_params_separate($target, $label, $params, $center=false)
{
    $id = default_focus();

    $pars = access_string($label);
    if ($center)
        echo "<br><center>";
    echo "<a target='_blank' id='$id' href='$target?$params' $pars[1]>$pars[0]</a>\n";
    if ($center)
        echo "</center>";
}

function hyperlink_params_separate_td($target, $label, $params)
{
    echo "<td>";
    hyperlink_params_separate($target, $label, $params);
    echo "</td>\n";
}

//--------------------------------------------------------------------------------------------------

function alt_table_row_color(&$k, $extra_class=null)
{
    $classes = $extra_class ? array($extra_class) : array();
    if ($k == 1)
    {
        array_push($classes, 'oddrow');
        $k = 0;
    }
    else
    {
        array_push($classes, 'evenrow');
        $k++;
    }
    echo "<tr class='".implode(' ', $classes)."'>\n";
}

function table_section_title($msg, $colspan=2)
{
    echo "<tr><td colspan=$colspan class='tableheader'>$msg</td></tr>\n";
}

function table_header($labels, $params='')
{
    start_row();
    foreach ($labels as $label)
        labelheader_cell($label, $params);
    end_row();
}
//-----------------------------------------------------------------------------------

function start_row($param="")
{
    if ($param != "")
        echo "<tr $param>\n";
    else
        echo "<tr>\n";
}

function end_row()
{
    echo "</tr>\n";
}

function br($num=1)
{
    for ($i = 0; $i < $num; $i++)
        echo "<br>";
}

$ajax_divs = array();

function div_start($id='', $trigger=null, $non_ajax=false)
{
    global $ajax_divs;

    if ($non_ajax) { // div for non-ajax elements
           array_push($ajax_divs, array($id, null));
           echo "<div style='display:none' class='js_only' ".($id !='' ? "id='$id'" : '').">";
    } else { // ajax ready div
           array_push($ajax_divs, array($id, $trigger===null ? $id : $trigger));
           echo "<div ". ($id !='' ? "id='$id'" : '').">";
           ob_start();
    }
}

function div_end()
{
    global $ajax_divs, $Ajax;

    output_hidden();
    if (count($ajax_divs))
    {
        $div = array_pop($ajax_divs);
        if ($div[1] !== null)
            $Ajax->addUpdate($div[1], $div[0], ob_get_flush());
    }
    echo "</div>";
}

//-----------------------------------------------------------------------------
//    Tabbed area:
//     $name - prefix for widget internal elements:
//        Nth tab submit name:  {$name}_N
//        div id:    _{$name}_div
//        sel (hidden) name: _{$name}_sel
// $tabs - array of tabs; string: tab title or array(tab_title, enabled_status)

function tabbed_content_start($name, $tabs, $dft='') {
    global $Ajax;

    $selname = '_'.$name.'_sel';
    $div = '_'.$name.'_div';

    $sel = find_submit($name.'_', false);
    if($sel==null)
        $sel = get_post($selname, (string)($dft==='' ? key($tabs) : $dft));

    if ($sel!==@$_POST[$selname])
        $Ajax->activate($name);

    $_POST[$selname] = $sel;

    div_start($name);
    $str = "<ul class='ajaxtabs' rel='$div'>\n";
    foreach($tabs as $tab_no => $tab) {
        
        $acc = access_string(is_array($tab) ? $tab[0] : $tab);
        $disabled = (is_array($tab) && !$tab[1])  ? 'disabled ' : '';
        $str .= ( "<li>"
            ."<button type='submit' name='{$name}_".$tab_no
            ."' class='".((string)$tab_no===$sel ? 'current':'ajaxbutton')."' $acc[1] $disabled>"
            ."<span>$acc[0]</span>"
            ."</button>\n"
            ."</li>\n" );
    }

    $str .= "</ul>\n";
    $str .= "<div class='spaceBox'></div>\n";
    $str .= "<input type='hidden' name='$selname' value='$sel'>\n";
    $str .= "<div class='contentBox' id='$div'>\n";
    echo $str;
}

function tabbed_content_end() {
    output_hidden();
    echo "</div>"; // content box (don't change to div_end() unless div_start() is used above)
    div_end(); // tabs widget
}

function tab_changed($name)
{
    $to = find_submit("{$name}_", false);
    if (!$to) return null;

    return array('from' => $from = get_post("_{$name}_sel"),
        'to' => $to);
}

/* Table editor interfaces. Key is editor type
    0 => url of editor page
    1 => hotkey code
    2 => context help
*/
$popup_editors = array(
    'customer' => array('/sales/manage/customers.php?debtor_no=', 
        113,    _("Customers"), 900, 500),
    'branch' => array('/sales/manage/customer_branches.php?SelectedBranch=', 
        114, _("Branches"), 900, 700),
    'supplier' => array('/purchasing/manage/suppliers.php?supplier_id=', 
        113, _("Suppliers"), 900, 700),
    'item' => array('/inventory/manage/items.php?stock_id=', 
        115, _("Items"), 800, 600)
);
/*
    Bind editors for various selectors.
    $type - type of editor
    $input - name of related input field
    $caller - optional function key code (available values F1-F12: 112-123,
        true: default)
*/
function set_editor($type, $input, $caller=true)
{
    global $path_to_root, $Editors, $popup_editors, $Pagehelp;

    $key = $caller===true ? $popup_editors[$type][1] : $caller;

    $Editors[$key] = array( $path_to_root . $popup_editors[$type][0], $input, 
        $popup_editors[$type][3], $popup_editors[$type][4]);
    
    $help = 'F' . ($key - 111) . ' - ';
    $help .= $popup_editors[$type][2];
    $Pagehelp[] = $help;
}
//------------------------------------------------------------------------------
// Procedures below are now obsolete. Preserved for eventual future use.

/*
    External page call with saving current context.
    $call - url of external page
    $ctx - optional. name of SESSION context object or array of names of POST 
        variables saved on call
*/
function context_call($call, $ctx='')
{
    if (is_array($ctx)) 
    {
        foreach($ctx as $postname)
        {
             $context[$postname] = get_post($postname);
        }
    } else 
        $context = isset($_SESSION[$ctx]) ? $_SESSION[$ctx] : null;

    array_unshift($_SESSION['Context'], array('name' => $ctx, 
        'ctx' => $context,
        'caller' => $_SERVER['PHP_SELF'],
        'ret' => array()));
    meta_forward($call);
}
/*
    Restores context after external page call and
    returns array of data passed by external page.
*/
function context_restore()
{
    if ( count($_SESSION['Context'])) {
        if ($_SERVER['PHP_SELF'] == $_SESSION['Context'][0]['caller']) {
            $ctx = array_shift($_SESSION['Context']);
            if ($ctx) {
                if (is_array($ctx['ctx'])) {
                    foreach($ctx['ctx'] as $name => $val) 
                    {
                        $_POST[$name] = $val;
                    }
                } else
                    if ($ctx['name']!='')
                        $_SESSION[$ctx['name']] = $ctx['ctx'];
                return $ctx['ret'];
            }
        }
    }
    return false;
}

/*
    Return to caller page if the page was called from external context.
*/
function context_return($ret)
{
    if ( count($_SESSION['Context'])) {
        $ctx = &$_SESSION['Context'][0];
        $ctx['ret'] = $ret;
        meta_forward( $ctx['caller'] );
    }
}
/*
    Clearing context stack after page cancel.
*/
function context_reset()
{
    $_SESSION['Context'] = array();
}
/*
    Context stack initialization
*/
if (!isset($_SESSION['Context'])) {
        context_reset();
}
/*
    Redirector for selector F4 calls.
    $sel_editors is array of selname=>editor_page
*/
function editor_redirect($sel_editors, $save_fun='') {
    foreach ($sel_editors as $selname=>$editor)
        if (isset($_POST['_'.$selname.'_editor'])) {
            if (function_exists($save_fun))
                $save_fun();
            unset($_POST['_'.$selname.'_editor']);
            context_call($editor, array_keys($_POST));
        }
}
/*
    Return procedure for selector F4 calls
*/
function editor_return($vars, $restore_fun='') {
    if (function_exists($restore_fun))
        $restore_fun();

    if ($ret = context_restore()) {
        foreach ($vars as $postname=>$retname)
            if (isset($ret[$retname])) {
                $_POST[$postname] = $ret[$retname];
                set_focus($postname);
            }
    }
}

function confirm_dialog($submit, $msg) {
    if (find_post($submit)) {
        display_warning($msg);
        br();
        submit_center_first('DialogConfirm', _("Proceed"), '', true);
        submit_center_last('DialogCancel', _("Cancel"), '', 'cancel');
        return 0;
    } else
        return get_post('DialogConfirm', 0);
}

/*
    Block menu/shortcut links during transaction procesing.
*/
function page_processing($msg = false)
{
    global $Ajax;

    if ($msg === true)
        $msg = _('Entered data has not been saved yet.\nDo you want to abandon changes?');

    $js = "_validate._processing=" . (
        $msg ? '\''.strtr($msg, array("\n"=>'\\n')) . '\';' : 'null;');
    if (in_ajax()) {
        $Ajax->addScript(true, $js);
    } else
        add_js_source($js);
}

function page_modified($status = true)
{
    global $Ajax;

    $js = "_validate._modified=" . ($status ? 1:0).';';
    if (in_ajax()) {
        $Ajax->addScript(true, $js);
    } else
        add_js_source($js);
}

?>

Re: Problem with editing customer contacts

@joe: It might be useful to enable downloads without registration so that we do not have a bloated set of users with 0 posts. Can then delete users with 0 posts as well.

Re: Problem with editing customer contacts

There are no setup options to make that in the maintenance setup.
However we can hack the code manually if this should be done.

Another option in these situations is to create a link to the file in the Git repository, where the file can be downloaded.

Joe

14 (edited by apmuthu 08/06/2015 02:53:28 am)

Re: Problem with editing customer contacts

Files in the Git repo can be linked, but others not there will need to be put into the Github's Wiki or attached to the GitHub Issues - most will not take the trouble to do it.

Thanks for looking into it anyway. It is probably set so to avoid bandwidth leeching.

Re: Problem with editing customer contacts

Dear Joe, I downloaded ui_controls.inc from post 3 and replace in /includes/ui/ui_controls.inc but still unable to see previous customer list into scroll botton.. please reply me with solution or procedure to fix it.

Re: Problem with editing customer contacts

@AjayPrajapti,  can you tell us which version of  FA and your php version. also enable debugging mode and tells what is the error you see on the screen.

Subscription service based on FA
HRM CRM POS batch Themes