task #0001697: Extension usage des étiquettes , tag on operation + export CSV + filter

This commit is contained in:
sparkyx 2020-11-10 19:48:20 +01:00
parent 656ab45372
commit 085efd0efa
27 changed files with 857 additions and 100 deletions

View file

@ -240,6 +240,8 @@ $path = array(
"save_filter"=>"ajax_search_filter",
// Load a search filter
"load_filter"=>"ajax_search_filter",
// display tag for filter
'display_filter_tag'=>'ajax_search_filter',
// search operation to reconcile
'search_op'=>'ajax_search_operation',
// delete operation
@ -269,7 +271,13 @@ $path = array(
// set the group for a tag
'tag_set_group'=>"ajax_tag_set_group",
// Document_state
"document_state"=>"ajax_document_state"
"document_state"=>"ajax_document_state",
// Operations tag add
'operation_tag_add'=>"ajax_operation_tag",
// Operations tag remove
'operation_tag_remove'=>"ajax_operation_tag",
// Operations tag select
'operation_tag_select'=>"ajax_operation_tag"
) ;
if (array_key_exists($op, $path)) {

View file

@ -1297,8 +1297,8 @@ function manage_search_filter(p_obj) {
onSuccess:function(req) {
remove_waiting_box();
var x=posX;
var y=posY-20;
create_div({'id':'boxfilter'+p_obj.div,'cssclass':'inner_box','html':req.responseText,'style':'top:'+y+'px;left:'+x+'px;position:absolute;width:400px'});
var y=calcy(200)
create_div({'id':'boxfilter'+p_obj.div,'cssclass':'inner_box','html':req.responseText,'style':'top:'+y+'px;left:'+x+'px;position:absolute;width:400px',drag:1});
$('boxfilter'+p_obj.div).show();
}
});
@ -1315,8 +1315,9 @@ function manage_search_filter(p_obj) {
function save_filter(p_div,p_dossier) {
var elt=['ledger_type','nb_jrn','date_start','date_end',
'date_paid_start','date_paid_end','desc','amount_min','amount_max','qcode','accounting',
'operation_filter'];
'operation_filter','tag_option'];
var eltValue={};
var i =0;
eltValue['gDossier']=p_dossier;
eltValue['op']="save_filter";
eltValue['div']=p_div;
@ -1338,6 +1339,12 @@ function save_filter(p_div,p_dossier) {
eltValue['r_jrn'+i]=$(idx).value
}
}
//ledger's tags
var aTag=Array.from(document.getElementsByName(p_div+"tag[]"));
eltValue["tag[]"]=[];
for (i=0 ; i < aTag.length;i++) {
eltValue["tag[]"][i]=aTag[i].value;
}
new Ajax.Request('ajax_misc.php', {
method:"POST",
@ -1349,7 +1356,7 @@ function save_filter(p_div,p_dossier) {
/*Add the new list to the selection */
var new_item=document.createElement('li');
new_item.innerHTML=answer.filter_name;
new_item.setAttribute("id","li"+p_div+"_"+answer.filter_id);
new_item.setAttribute("id","manageli"+p_div+"_"+answer.filter_id);
$('manage'+p_div).appendChild(new_item);
$(p_div+"filter_new").value="";
} else {
@ -1377,7 +1384,7 @@ function load_filter(p_div,p_dossier,p_filter_id) {
var answer=req.responseJSON;
console.log(answer);
var elt=['ledger_type','date_start','date_end','date_paid_start','date_paid_end',
'desc','amount_min','amount_max','qcode','accounting','operation_filter'];
'desc','amount_min','amount_max','qcode','accounting','operation_filter','tag_option'];
for (var i=0;i<elt.length;i++) {
var idx=elt[i];
$(p_div+idx).value=answer[elt[i]];
@ -1402,8 +1409,15 @@ function load_filter(p_div,p_dossier,p_filter_id) {
eltHidden.setAttribute("value",answer.r_jrn[i]);
eltLedgerId.appendChild(eltHidden);
}
new Ajax.Request("ajax_misc.php",{
method:"get",
parameters:{"gDossier":p_dossier,"div":p_div,"op":"display_filter_tag","filter_id":p_filter_id,
uf_tag:answer.uf_tag},
onSuccess:function (req) {
$(p_div+'tag_choose_td').update(req.responseText);
}
})
} catch (e) {
smoke.alert(e.message);

View file

@ -2711,13 +2711,16 @@ function activate_tag(p_dossier, p_tag_id) {
* Display a div with available tags, this div can update the cell
* tag_choose_td
* @param {type} p_dossier
* @param {string} p_prefix is the prefix of the div
* @param {string} Calling object either Tag_Operation or Tag_Action
* @returns {undefined}
*
*/
function search_display_tag(p_dossier, p_prefix)
function search_display_tag(p_dossier, p_prefix,p_object)
{
try {
waiting_box();
var queryString = "op=search_display_tag&gDossier=" + p_dossier + "&pref=" + p_prefix;
var queryString = { op : "search_display_tag",gDossier:p_dossier,pref:p_prefix,caller_obj:p_object};
var action = new Ajax.Request(
"ajax_misc.php",
{
@ -3818,4 +3821,137 @@ function uncheck_other(p_click,p_name)
aCheckbox[i].checked=false;
}
p_click.checked=true;
}
}
/**
* Manage the tag with operations
* @returns {undefined}
*/
var operation_tag = function (p_div)
{
this.ctl = p_div;
console.log("ctl "+p_div);
/**
* Show a list of tag which can be added to the current followup document
* @param {type} p_dossier
* @param {type} jrn_id
* @returns {undefined}
*/
this.select = function (p_dossier, p_jrn_id)
{
try {
waiting_box();
var queryString = {jrn_id:p_jrn_id,op:"operation_tag_select",gDossier:p_dossier,ctl:this.ctl};
var action = new Ajax.Request(
"ajax_misc.php",
{
method: 'get',
parameters: queryString,
onFailure: ajax_misc_failure,
onSuccess: function (req, j) {
remove_waiting_box();
var answer = req.responseXML;
var html = answer.getElementsByTagName('code');
if (html.length === 0)
{
var rec = unescape_xml(req.responseText);
error_message('erreur :' + rec);
}
var code_html = getNodeText(html[0]);
code_html = unescape_xml(code_html);
var pos = fixed_position(35, 229);
add_div({id: 'tag_div', style: pos, cssclass: 'inner_box tag', drag: 0});
remove_waiting_box();
$('tag_div').innerHTML = code_html;
}
}
);
} catch (e) {
error_message(e.message);
}
};
/**
* @brief Add the current tag to the current ag_id
* @param {type} p_dossier
* @param {type} ag_id
* @param p_isgroup g it is a group , t is a single tag
* @returns {undefined}
*/
this.add = function (p_dossier, p_jrn_id, t_id, p_isgroup)
{
try {
waiting_box();
var queryString = {t_id:t_id,jrn_id:p_jrn_id,op:"operation_tag_add",
gDossier:p_dossier,ctl:this.ctl,isgroup:p_isgroup};
var ctl=this.ctl;
var action = new Ajax.Request(
"ajax_misc.php",
{
method: 'get', parameters: queryString,
onFailure: ajax_misc_failure,
onSuccess: function (req, j) {
var answer = req.responseXML;
console.log("1-ctl "+ctl);
var html = answer.getElementsByTagName('code');
if (html.length === 0)
{
var rec = unescape_xml(req.responseText);
error_message('erreur :' + rec);
}
var code_html = getNodeText(html[0]);
code_html = unescape_xml(code_html);
remove_waiting_box();
$('operation_tag_td'+ctl).innerHTML = code_html;
removeDiv('tag_div');
}
}
);
} catch (e) {
error_message(e.message);
}
};
/**
* @brief remove the current tag to the current ag_id
* @param {type} p_dossier
* @param {type} ag_id
* @returns {undefined}
*/
this.remove = function (p_dossier, p_jrn_id, t_id)
{
var ctl=this.ctl;
console.log("remove-1.ctl "+ctl);
confirm_box(null, content[50], function () {
try {
waiting_box();
var queryString = {t_id:t_id,jrn_id:p_jrn_id,op:"operation_tag_remove",gDossier:p_dossier,ctl:ctl};
var action = new Ajax.Request(
"ajax_misc.php",
{
method: 'get',
parameters: queryString,
onFailure: ajax_misc_failure,
onSuccess: function (req, j) {
var answer = req.responseXML;
var html = answer.getElementsByTagName('code');
if (html.length === 0)
{
var rec = unescape_xml(req.responseText);
error_message('erreur :' + rec);
}
var code_html = getNodeText(html[0]);
code_html = unescape_xml(code_html);
remove_waiting_box();
console.log("remove-2.ctl "+ctl);
$('operation_tag_td'+ctl).innerHTML = code_html;
}
}
);
} catch (e) {
error_message(e.message);
}
});
};
};

View file

@ -124,7 +124,7 @@ if ( isset ($_GET['viewsearch']))
* Export to csv
*/
$r=HtmlInput::get_to_hidden(array('l','date_start','date_end','desc','amount_min','amount_max',
'qcode','accounting','unpaid','gDossier','ledger_type'));
'qcode','accounting','unpaid','gDossier','ledger_type','tag_option'));
if (isset($_GET['r_jrn'])) {
$http=new HttpInput();
$a_rjrn=$http->get("r_jrn","array");
@ -135,6 +135,16 @@ if ( isset ($_GET['viewsearch']))
}
}
}
if (isset($_GET['tag'])) {
$http=new HttpInput();
$aTag=$http->get("tag","array");
foreach ($aTag as $k=>$v) {
// Protect : check that $k and $v are numeric
if (isNumber($k)&&isNumber($v)) {
$r.=HtmlInput::hidden('tag[]',$v);
}
}
}
echo '<form action="export.php" method="get">';
echo $r;
echo HtmlInput::hidden('act','CSV:histo');

View file

@ -42,6 +42,7 @@ require_once NOALYSS_INCLUDE.'/lib/idate.class.php';
require_once NOALYSS_INCLUDE.'/class/noalyss_parameter_folder.class.php';
require_once NOALYSS_INCLUDE.'/lib/iconcerned.class.php';
require_once NOALYSS_INCLUDE.'/lib/http_input.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_operation.class.php';
$http=new HttpInput();
/**

View file

@ -0,0 +1,166 @@
<?php
/*
* This file is part of NOALYSS.
*
* PhpCompta is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* PhpCompta 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PhpCompta; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Copyright (2002-2020) Author Dany De Bontridder <danydb@noalyss.eu>
if (!defined('ALLOWED'))
die('Appel direct ne sont pas permis');
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_operation.class.php';
/**
* @file
* @brief manage the ajax calls for adding , deleting tag on operations
*/
try
{
$op=$http->request('op');
$jrn_id=$http->request('jrn_id', "number");
}
catch (Exception $ex)
{
echo $ex->getMessage();
}
// Security : check ledger accessible
global $g_user;
$ledger=$cn->get_value("select jr_def_id from jrn where jr_id=$1", [$jrn_id]);
if ($g_user->get_ledger_access($ledger)!='W')
{
record_log("AJT0001");
return;
}
switch ($op)
{
case 'operation_tag_select':
//--------------------------------------------------------------------------------------------------
// Display a list of available tag
//--------------------------------------------------------------------------------------------------
ob_start();
$tag_operation=new Tag_Operation($cn);
echo $tag_operation->select($ctl);
//------------------- Propose to add a tag
$js=sprintf("onclick=\"show_tag('%s','%s','%s','j')\"", Dossier::id(), '', '-1');
if ($g_user->check_action(TAGADD)==1)
{
echo HtmlInput::button("tag_add", _("Ajout d'un tag"), $js);
}
echo HtmlInput::button_close("tag_div");
$response=ob_get_clean();
if (headers_sent()&&DEBUG)
{
echo $response;
}
else
{
header('Content-type: text/xml; charset=UTF-8');
}
$html=escape_xml($response);
echo <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<data>
<ctl></ctl>
<code>$html</code>
</data>
EOF;
return;
case 'operation_tag_add':
//--------------------------------------------------------------------------------------------------
// Display all the tags attached to this operation
//--------------------------------------------------------------------------------------------------
$tag_operation=new Tag_Operation($cn);
$tag_operation->set_jrn_id($jrn_id);
$pref=$http->request("ctl");
if ($http->request("isgroup")=='t')
{
$tag_operation->tag_add($http->request('t_id', "number"));
}
else
{
// Add all the tag from the group
$aTag=$cn->get_array("select t_id,t_tag ,t_color from jnt_tag_group_tag jtgt join tags on (tag_id=t_id) where tag_group_id=$1 order by 2 ",
[$http->request("t_id", "number")]);
$nb_atag=count($aTag);
if ($nb_atag>0)
{
for ($i=0; $i<$nb_atag; $i++)
{
$tag_operation->tag_add($aTag[$i]['t_id']);
}
}
}
ob_start();
$tag_operation->tag_cell($ctl);
$response=ob_get_clean();
if (headers_sent()&&DEBUG)
{
echo $response;
}
else
{
header('Content-type: text/xml; charset=UTF-8');
}
$html=escape_xml($response);
echo <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<data>
<ctl></ctl>
<code>$html</code>
</data>
EOF;
return;
break;
case 'operation_tag_remove':
$tag_operation=new Tag_Operation($cn);
$tag_operation->set_jrn_id($jrn_id);
$pref=$http->request("ctl");
$tag_operation->tag_remove($http->request("t_id", "number"));
ob_start();
$tag_operation->tag_cell($pref);
$response=ob_get_clean();
if (headers_sent()&&DEBUG)
{
echo $response;
}
else
{
header('Content-type: text/xml; charset=UTF-8');
}
$html=escape_xml($response);
echo <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<data>
<ctl></ctl>
<code>$html</code>
</data>
EOF;
return;
break;
}

View file

@ -25,18 +25,18 @@ if (!defined('ALLOWED'))
* @brief add tag , used for follow up
* @see Tag
*/
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
//Single Tag
ob_start();
if ($_GET['clear']==1)
{
/* Add a clear button */
echo Tag::add_clear_button($_GET['pref']);
echo Tag_Action::add_clear_button($_GET['pref']);
}
if ($http->request("obj")=='t')
{
$tag=new Tag($cn, $http->get("id", "number"));
$tag=new Tag_Action($cn, $http->get("id", "number"));
$tag->update_search_cell($http->get("pref"));
}
elseif ($http->request("obj")=="g")
@ -47,7 +47,7 @@ elseif ($http->request("obj")=="g")
$pref=$http->get("pref");
if ( $nb_atag > 0) {
for ($i=0;$i<$nb_atag;$i++){
$tag=new Tag($cn,$aTag[$i]['t_id']);
$tag=new Tag_Action($cn,$aTag[$i]['t_id']);
$tag->update_search_cell($pref);
}
}

View file

@ -24,9 +24,9 @@ if ( !defined ('ALLOWED') ) die('Appel direct ne sont pas permis');
*@see Tag
*/
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
ob_start();
echo Tag::button_search($_GET['pref']);
echo Tag_Action::select_tag_search($_GET['pref']);
$response= ob_get_clean();
$html=escape_xml($response);
header('Content-type: text/xml; charset=UTF-8');

View file

@ -24,10 +24,27 @@ if ( !defined ('ALLOWED') ) die('Appel direct ne sont pas permis');
*@see Tag
*/
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
$tag=new Tag($cn);
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_operation.class.php';
$response= $tag->select_search($_GET['pref']);
try {
$caller_obj=$http->request("caller_obj");
$prefix=$http->request("pref");
} catch (Exception $ex) {
echo $ex->getMessage();
return;
}
if ( $caller_obj == 'Tag_Action' ) {
$tag=new Tag_Action($cn);
}elseif ($caller_obj=='Tag_Operation')
{
$tag=new Tag_Operation( $cn);
} else {
throw new Exception("AJD001 invalid caller [$caller_obj]");
}
$response= $tag->select_search($pref);
$html=escape_xml($response);
header('Content-type: text/xml; charset=UTF-8');

View file

@ -24,6 +24,7 @@ if (!defined('ALLOWED'))
require NOALYSS_INCLUDE.'/database/user_filter_sql.class.php';
require NOALYSS_INCLUDE.'/class/acc_ledger_search.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_operation.class.php';
$cn=Dossier::connect();
$dossier_id=Dossier::id();
global $g_user;
@ -55,12 +56,19 @@ if ($op=='save_filter')
$new->setp("amount_max", $http->post("amount_max", 'number', NULL));
$new->setp("qcode", $http->post("qcode", 'string', NULL));
$new->setp("accounting", $http->post("accounting", 'string', NULL));
$new->setp("uf_tag_option",$http->post("tag_option","string",null));
$new->setp("date_paid_start",
$http->post("date_paid_start", 'string', NULL));
$new->setp("date_paid_end", $http->post("date_paid_end", 'string', NULL));
$new->setp("ledger_type", $http->post("ledger_type", 'string'));
$new->setp("operation_filter", $http->post("operation_filter", 'string', NULL));
$new->setp("filter_name", h($http->post("filter_name", 'string')));
$tag=$http->post("tag","string",'');
if (is_array($tag) )
$new->setp("uf_tag",join(',',$tag));
else
$new->setp("uf_tag",null);
$aJrn=[];
$max=$http->post("nb_jrn");
for ($i=0; $i<$max; $i++)
@ -75,11 +83,11 @@ if ($op=='save_filter')
$new->save();
$rmAction=sprintf("delete_filter('%s','%s','%s')", trim($http->post('div')), $dossier_id,
$new->getp('id'));
$answer['filter_name']=sprintf('<a class="tinybutton" style="display:inline" id="" onclick="'.$rmAction.'">'.SMALLX.'</a>'
);
$answer['filter_name'].=sprintf("<a style=\"display:inline\" onclick=\"load_filter('%s','%s','%s')\">%s</a>",
$answer['filter_name']="";
$answer['filter_name'].=sprintf("<a class=\"line\" style=\"display:inline;text-decoration:underline\" onclick=\"load_filter('%s','%s','%s')\">%s</a>",
trim($http->post('div')), $dossier_id, $new->getp('id'),
$new->getp("filter_name"));
$answer['filter_name'].='<span id="'.uniqid().'" onclick="'.$rmAction.'" class="icon" style="display:inline;margin-left:2em">&#xe80f;</span>';;
$answer['filter_id']=$new->getp("id");
$answer['status']='OK';
}
@ -108,7 +116,8 @@ if ($op=="load_filter")
$record['desc']=$record['description'];
$record['r_jrn']=explode(",", $record['r_jrn']);
$record['tag']=explode(",",$record['uf_tag']);
$record['tag_option']=$record["uf_tag_option"];
$result=array_merge($answer, $record);
@ -148,7 +157,7 @@ if ($op=="display_search_filter")
echo "</li>";
echo "<li>";
echo HtmlInput::anchor(_("Remise à zéro"), "", "onclick=\"reset_filter('$p_div');removeDiv('boxfilter{$p_div}')\"");
echo HtmlInput::anchor(_("Remise à zéro"), "", "style=\"text-decoration:underline\" onclick=\"reset_filter('$p_div');removeDiv('boxfilter{$p_div}')\"");
echo "</li>";
// Link reset
@ -157,12 +166,11 @@ if ($op=="display_search_filter")
printf(' <li id="manageli%s_%d">', $p_div, $result[$i]["id"]);
$rmAction=sprintf("delete_filter('%s','%s','%s')", $p_div, $dossier_id,
$result[$i]['id']);
printf('<a class="tinybutton" style="display:inline" id="" onclick="'.$rmAction.'">'.SMALLX.'</a>'
);
printf("<a style=\"display:inline\" onclick=\"load_filter('%s','%s','%s');removeDiv('boxfilter%s')\">",
printf("<a href=\"javascript:void(0)\" style=\"display:inline;text-decoration:underline\" onclick=\"load_filter('%s','%s','%s');removeDiv('boxfilter%s')\">",
$p_div, $dossier_id, $result[$i]["id"],$p_div);
echo $result[$i]["filter_name"];
echo '</a>';
echo '<span id="'.uniqid().'" onclick="'.$rmAction.'" class="icon" style="display:inline;margin-left:2em">&#xe80f;</span>';
printf("</li>");
}
@ -198,4 +206,22 @@ if ($op=="delete_search_operation")
header('Content-Type: application/json;charset=utf-8');
echo json_encode($answer);
return;
}
//---------------------------------------------------------------------------------------------------------------
// display_filter_tag : transform uf_tag into a list of tag , and display those tags in cells
//----------------------------------------------------------------------------------------------------------------
if ($op=='display_filter_tag')
{
$tag=$http->request("uf_tag");
$div=$http->request("div");
$aTag=explode(',', $tag);
if (is_array($aTag))
{
$nb_tag=count($aTag);
for ($j=0; $j<$nb_tag; $j++)
{
$tag_operation=new Tag_Operation($cn, $aTag[$j]);
$tag_operation->update_search_cell($div);
}
}
}

View file

@ -23,9 +23,9 @@
*/
if ( !defined ('ALLOWED') ) die('Appel direct ne sont pas permis');
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
ob_start();
$tag=new Tag($cn);
$tag=new Tag_Action($cn);
$tag->select();
//------------------- Propose to add a tag
@ -35,8 +35,12 @@ if ( $g_user->check_action(TAGADD) == 1) { echo HtmlInput::button("tag_add", _("
echo HtmlInput::button_close("tag_div");
$response= ob_get_clean();
if (headers_sent() && DEBUG ){
echo $response;
} else {
header('Content-type: text/xml; charset=UTF-8');
}
$html=escape_xml($response);
header('Content-type: text/xml; charset=UTF-8');
echo <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<data>

View file

@ -23,9 +23,9 @@ if ( !defined ('ALLOWED') ) die('Appel direct ne sont pas permis');
*@brief Show the tags to select
*@see Tag
*/
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
ob_start();
$tag=new Tag($cn);
$tag=new Tag_Action($cn);
$tag->select_search();
$response= ob_get_clean();

View file

@ -21,6 +21,8 @@
// if (!defined('ALLOWED')) die('Appel direct ne sont pas permis');
require_once NOALYSS_INCLUDE."/class/tag_operation.class.php";
/**
* @file
* @brief search in ledger
@ -455,6 +457,7 @@ class Acc_Ledger_Search
$fil_paid='';
$fil_date_paid='';
$fil_hide_operation='';
$fil_tag='';
$and='';
$g_user=new User($this->cn);
@ -500,7 +503,27 @@ class Acc_Ledger_Search
$and='';
}
}
//----
// Search tags
if ( isset($p_array[$op."tag"] ))
{
$strTag=join(",", $p_array[$op."tag"]);
if ($p_array[$op."tag_option"] == 1){
// any tag
$fil_tag=$and.' jr_id in (select jrn_id from operation_tag where tag_id in ('.sql_string($strTag).')) ';
} else {
// all tags
$aTag=$p_array[$op."tag"];
$sub_tag=""; $nb_tag=count($aTag);
$and2='';
for ($x=0;$x < $nb_tag;$x++) {
$sub_tag = " tag_id = ".sql_string($aTag[$x]);
$fil_tag=$and.' jr_id in (select jrn_id from operation_tag where '.$sub_tag.')' ;
$and=" and ";
}
}
$and=" and ";
}
/* format the number */
$amount_min=abs(toNumber($amount_min));
$amount_max=abs(toNumber($amount_max));
@ -620,7 +643,7 @@ class Acc_Ledger_Search
" and uj_priv in ('R','W'))";
}
$where=$fil_ledger.$fil_amount.$fil_date.$fil_desc.$fil_sec.$fil_amount.
$fil_qcode.$fil_paid.$fil_account.$fil_date_paid.$fil_hide_operation;
$fil_qcode.$fil_paid.$fil_account.$fil_date_paid.$fil_hide_operation.$fil_tag;
$sql.=" where ".$where;
// Q?? Why do we return where if it is included in SQL ?

View file

@ -42,6 +42,7 @@ require_once NOALYSS_INCLUDE.'/class/document_option.class.php';
require_once NOALYSS_INCLUDE.'/class/default_menu.class.php';
require_once NOALYSS_INCLUDE.'/lib/inplace_edit.class.php';
require_once NOALYSS_INCLUDE.'/lib/noalyss_csv.class.php';
require_once NOALYSS_INCLUDE.'/class/tag_action.class.php';
/**
* \file

View file

@ -38,7 +38,7 @@ class Tag
return $this;
}
/**
/**
* Show the list of available tag
* @return HTML
*/
@ -48,19 +48,7 @@ class Tag
if ( $this->cn->count($ret) == 0) return "";
require_once NOALYSS_TEMPLATE.'/tag_list.php';
}
/**
* let select a tag to add
*/
function select()
{
$ret=$this->data->seek("where t_actif='Y' order by t_tag");
$ret=$this->cn->exec_sql(" select t_id,t_tag,t_description,'t' as tag_type ,t_color
from tags
where t_actif='Y'
union all
select tg_id,tg_name ,'G','g' ,1 from tag_group order by 2");
require_once NOALYSS_TEMPLATE.'/tag_select.php';
}
/**
* Display a inner window with the detail of a tag
*/
@ -93,43 +81,17 @@ class Tag
$this->data->t_id=$p_array['t_id'];
$this->data->delete();
}
/**
* Show a button to select tag for Search
* @return HTML
/***
* query the active tag and returns the database handler
*/
static function button_search($p_prefix)
{
$r="";
$r.=HtmlInput::button("choose_tag", _("Etiquette"), 'onclick="search_display_tag('.Dossier::id().',\''.$p_prefix.'\')"', "smallbutton");
return $r;
}
/**
* let select a tag to add to the search
*/
function select_search($p_prefix)
{
$res="";
$ret=$this->data->seek(' order by t_tag');
require_once NOALYSS_TEMPLATE.'/tag_search_select.php';
return HtmlInput::title_box('Tag', $p_prefix.'tag_div').$res;
}
/**
* In the screen search add this data to the cell
*/
function update_search_cell($p_prefix) {
echo '<span id="sp_'.$p_prefix.$this->data->t_id.'" class="tagcell">';
echo h($this->data->t_tag);
echo HtmlInput::hidden($p_prefix.'tag[]', $this->data->t_id);
$js=sprintf("$('sp_".$p_prefix.$this->data->t_id."').remove();");
echo Icon_Action::trash(uniqid(), $js);
echo '</span>';
}
/**
* clear the search cell
*/
static function add_clear_button($p_prefix) {
$clear=HtmlInput::button('clear', 'X', 'onclick="search_clear_tag('.Dossier::id().',\''.$p_prefix.'\');"', 'smallbutton');
return $clear;
function query_active_tag()
{
$ret=$this->cn->exec_sql(" select t_id,t_tag,t_description,'t' as tag_type ,t_color
from tags
where t_actif='Y'
union all
select tg_id,tg_name ,'G','g' ,1 from tag_group order by 2");
return $ret;
}
}

View file

@ -0,0 +1,94 @@
<?php
/*
* * Copyright (C) 2020 Dany De Bontridder <dany@alchimerys.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author : Dany De Bontridder danydb@noalyss.eu
*
*/
require_once NOALYSS_INCLUDE.'/class/tag.class.php';
/**
* @file
* @brief concerns the tags linked to an action
*/
class Tag_Action extends Tag
{
function __construct($p_cn, $p_id=-1 )
{
parent::__construct($p_cn, $p_id);
}
/**
* let select a tag to add
*/
function select($p_prefix="")
{
$ret=parent::query_active_tag();
require_once NOALYSS_TEMPLATE.'/tag_select.php';
}
/**
* Show a button to select tag for Search
* @return HTML
*/
static function select_tag_search($p_prefix)
{
$r="";
$r.=HtmlInput::button("choose_tag", _("Etiquette"),
'onclick="search_display_tag('.Dossier::id().',\''.$p_prefix.'\',\'Tag_Action\')"', "smallbutton");
return $r;
}
/**
* clear the search cell
*/
static function add_clear_button($p_prefix)
{
$clear=HtmlInput::button('clear', 'X', 'onclick="search_clear_tag('.Dossier::id().',\''.$p_prefix.'\');"',
'smallbutton');
return $clear;
}
/**
* In the screen search add this data to the cell
*/
function update_search_cell($p_prefix)
{
$data=$this->get_data();
echo '<span id="sp_'.$p_prefix.$data->t_id.'" class="tagcell">';
echo h($data->t_tag);
echo HtmlInput::hidden($p_prefix.'tag[]', $data->t_id);
$js=sprintf("$('sp_".$p_prefix.$data->t_id."').remove();");
echo Icon_Action::trash(uniqid(), $js);
echo '</span>';
}
/**
* let select a tag to add to the search
*/
function select_search($p_prefix)
{
$res="";
$ret=$this->get_data()->seek(' order by t_tag');
require_once NOALYSS_TEMPLATE.'/tag_search_select.php';
return HtmlInput::title_box('Tag', $p_prefix.'tag_div').$res;
}
}

View file

@ -0,0 +1,199 @@
<?php
/*
* This file is part of NOALYSS.
*
* PhpCompta is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* PhpCompta 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PhpCompta; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Copyright (2002-2020) Author Dany De Bontridder <danydb@noalyss.eu>
if (!defined('ALLOWED'))
die('Appel direct ne sont pas permis');
/**
* @file
* @brief concerns the tags linked to an accountancy writing
*/
class Tag_Operation extends Tag
{
private $jrn_id=-1;
function __construct($p_cn, $p_id=-1)
{
parent::__construct($p_cn, $p_id);
}
public function get_jrn_id()
{
return $this->jrn_id;
}
public function set_jrn_id($jrn_id)
{
$this->jrn_id=$jrn_id;
return $this;
}
/**
* let select a tag to add
*/
function select($p_prefix="")
{
$ret=parent::query_active_tag();
require_once NOALYSS_TEMPLATE.'/tag_select.php';
}
/**
* Show a button to select tag for Search
* @param $p_jr jr_id of the operation
* @param $p_div prefix of the dialog box
* @return HTML
*/
static function button_search($p_jr, $p_div)
{
$r="";
$js=sprintf("onclick=\"new operation_tag('%s').select('%s','%s')\"", $p_div, dossier::id(), $p_jr);
$r.=HtmlInput::button('tag_bt', _('Ajout étiquette'), $js, 'smallbutton');
return $r;
}
/**
* clear the search cell
*/
static function add_clear_button($p_prefix)
{
$clear=HtmlInput::button('clear', 'X', 'onclick="search_clear_tag('.Dossier::id().',\''.$p_prefix.'\');"',
'smallbutton');
return $clear;
}
/**
* In the screen search add this data to the cell
*/
function update_search_cell($p_prefix)
{
$data=$this->get_data();
echo '<span id="sp_'.$p_prefix.$data->t_id.'" class="tagcell">';
echo h($data->t_tag);
echo HtmlInput::hidden($p_prefix.'tag[]', $data->t_id);
$js=sprintf("$('sp_".$p_prefix.$data->t_id."').remove();");
echo Icon_Action::trash(uniqid(), $js);
echo '</span>';
}
/**
* Links a tag to an operation
* @param int $p_tag_id tag.t_id
*/
function tag_add($p_tag_id)
{
if ($this->jrn_id==-1)
{
throw new Exception("TO99 jrn_id unset");
}
$count=$this->cn->get_value('select count(*) from operation_tag'.
' where jrn_id=$1 and tag_id=$2', array($this->jrn_id, $p_tag_id));
if ($count>0)
return;
$sql=' insert into operation_tag (jrn_id,tag_id) values ($1,$2)';
$this->cn->exec_sql($sql, array($this->jrn_id, $p_tag_id));
}
/**
* @brief show the cell content in Display for the tags
* @param $div prefix of the DOM id
* called also by ajax
*/
function tag_cell($p_div)
{
global $g_user;
$a_tag=$this->tag_get();
$c=count($a_tag);
$ledger=$this->cn->get_value("select jr_def_id from jrn where jr_id=$1", [$this->jrn_id]);
$access=$g_user->get_ledger_access($ledger);
for ($e=0; $e<$c; $e++)
{
echo '<span class="tagcell tagcell-color'.$a_tag[$e]['t_color'].'">';
echo $a_tag[$e]['t_tag'];
if ($access=='W')
{
$js_remove=sprintf("new operation_tag('%s').remove('%s','%s','%s')", $p_div, dossier::id(),
$this->jrn_id, $a_tag[$e]['t_id']);
echo Icon_Action::trash(uniqid(), $js_remove);
}
echo '</span>';
echo '&nbsp;';
echo '&nbsp;';
}
}
/**
* @brief get the tags of the current objet
* @return an array idx [ag_id,t_id,at_id,t_tag]
*/
function tag_get()
{
if ($this->jrn_id==-1)
{
throw new Exception("TO01 jrn_id unset");
}
$sql='select b.jrn_id,a.t_id,a.t_id,a.t_tag,a.t_color'
.' from '
.' tags as a join operation_tag as b on (a.t_id=b.tag_id)'
.' where jrn_id=$1 '
.' order by a.t_tag';
$array=$this->cn->get_array($sql, array($this->jrn_id));
return $array;
}
/**
* Remove a tag
* @param int $p_tag_id tag id
*/
function tag_remove($p_tag_id)
{
if ($this->jrn_id==-1)
{
throw new Exception("TO01 jrn_id unset");
}
$this->cn->exec_sql("delete from operation_tag where jrn_id=$1 and tag_id=$2", [$this->jrn_id, $p_tag_id]);
}
/**
* let select a tag to add to the search
*/
function select_search($p_prefix)
{
$res="";
$ret=$this->get_data()->seek(' order by t_tag');
require_once NOALYSS_TEMPLATE.'/tag_search_select.php';
return HtmlInput::title_box('Tag', $p_prefix.'tag_div').$res;
}
/**
* Show a button to select tag for Search
* @return HTML
*/
static function select_tag_search($p_prefix)
{
$r="";
$r.=HtmlInput::button("choose_tag", _("Etiquette"),
'onclick="search_display_tag('.Dossier::id().',\''.$p_prefix.'\',\'Tag_Operation\')"', "smallbutton");
return $r;
}
}
?>

View file

@ -107,7 +107,7 @@ if ( !defined ("NOALYSS_PACKAGE_REPOSITORY")) {
if ( ! defined ("SYSINFO_DISPLAY")) {
define ("SYSINFO_DISPLAY",TRUE);
}
define ("DBVERSION",150);
define ("DBVERSION",151);
define ("MONO_DATABASE",25);
define ("DBVERSIONREPO",18);
define ('NOTFOUND','--not found--');

View file

@ -56,6 +56,9 @@ class User_filter_SQL extends Noalyss_SQL
, "all_ledger"=>"all_ledger"
,"operation_filter"=>"operation_filter"
,'filter_name'=>"filter_name"
,'uf_tag'=>'uf_tag'
,'uf_tag_option'=>'uf_tag_option'
);
/*
* Type of columns
@ -78,6 +81,8 @@ class User_filter_SQL extends Noalyss_SQL
, "all_ledger"=>"numeric"
,"operation_filter"=>"text"
,"filter_name"=>"text"
,'uf_tag'=>'text'
,'uf_tag_option'=>'numeric'
);

View file

@ -175,17 +175,28 @@ echo '</form>';
*/
$r = HtmlInput::get_to_hidden(array('l', 'date_paid_start','date_paid_end',
'date_start', 'date_end', 'desc', 'amount_min', 'amount_max', 'qcode','operation_filter',
'accounting', 'unpaid', 'gDossier', 'ledger_type', 'p_action'));
'accounting', 'unpaid', 'gDossier', 'ledger_type', 'p_action','search_optag_option'));
if (isset($_GET['search_opr_jrn']))
{
foreach ($a_search_opr_jrn as $k => $v)
if (isNumber($v)) $r.=HtmlInput::hidden('r_jrn[' . $k . ']', $v);
}
$r.=HtmlInput::hidden("tag_option",$http->request("search_optag_option","string",0));
if (isset($_GET['r_jrn']))
{
foreach ($a_rjn as $k => $v)
if (isNumber($v)) $r.=HtmlInput::hidden('r_jrn[' . $k . ']', $v);
}
if (isset($_GET['search_optag'])) {
$http=new HttpInput();
$aTag=$http->get("search_optag","array");
foreach ($aTag as $k=>$v) {
// Protect : check that $k and $v are numeric
if (isNumber($k)&&isNumber($v)) {
$r.=HtmlInput::hidden('tag[]',$v);
}
}
}
echo '<form action="export.php" method="get">';
echo $r;
echo HtmlInput::hidden('act', 'CSV:histo');

View file

@ -0,0 +1,15 @@
begin;
alter table tags add column t_color int;
alter table tags alter t_color set default 1;
update tags set t_color=1;
create table operation_tag (opt_id bigserial primary key, jrn_id bigint , tag_id int);
alter table operation_tag add constraint opt_jrnx foreign key (jrn_id) references jrn (jr_id) on update cascade on delete cascade;
alter table operation_tag add constraint opt_tag_id foreign key (tag_id) references tags (t_id) on update cascade on delete cascade;
comment on table operation_tag is 'Tag attached to an operation';
ALTER TABLE public.user_filter ADD uf_tag text ;
alter table user_filter add uf_tag_option int;
COMMENT ON COLUMN public.user_filter.uf_tag IS 'Tag list';
COMMENT ON COLUMN public.user_filter.uf_tag_option IS '0 : all tags must be present, 1: at least one';
insert into version (val,v_description) values (151,'Tag with color and operation');
commit;

View file

@ -33,16 +33,16 @@ echo HtmlInput::request_to_hidden(array("closed_action","remind_date_end","remin
<li>
<?php $radio->value="ETIADD";echo $radio->input(); ?>
<?php echo _("Ajout d'étiquettes");?>
<?php echo Tag::button_search('add'); ?>
<?php echo Tag::add_clear_button('add'); ?>
<?php echo Tag_Action::select_tag_search('add'); ?>
<?php echo Tag_Action::add_clear_button('add'); ?>
<span id="addtag_choose_td">
</span>
</li>
<li>
<?php $radio->value="ETIREM";echo $radio->input(); ?>
<?php echo _("Enlever des étiquettes");?>
<?php echo Tag::button_search('rem'); ?>
<?php echo Tag::add_clear_button('rem'); ?>
<?php echo Tag_Action::select_tag_search('rem'); ?>
<?php echo Tag_Action::add_clear_button('rem'); ?>
<span id="remtag_choose_td">
</span>
</li>

View file

@ -129,14 +129,14 @@
<p>
<?php echo _('Etiquette'); ?>
<span id="searchtag_choose_td">
<?php echo Tag::button_search('search'); ?>
<?php echo Tag_Action::select_tag_search('search'); ?>
<?php
if ( isset($_GET['searchtag'])) {
$http=new HttpInput();
echo Tag::add_clear_button('search');
echo Tag_Action::add_clear_button('search');
$asearchtag= $http->get("searchtag","array",array());
for ($i=0;$i<count($asearchtag);$i++) {
$t=new Tag($cn, $asearchtag[$i]);
$t=new Tag_Action($cn, $asearchtag[$i]);
echo $t->update_search_cell('search');
}
}

View file

@ -160,7 +160,7 @@ $uniq=uniqid("tab",TRUE);
Dossier / Etiquette
</TD>
<td id="action_tag_td">
<td id="action_tag_td" style="max-width:35rem">
<?php
$this->tag_cell($p_view);
?>

View file

@ -44,6 +44,7 @@ $a_tab['linked_operation_div']=array('id'=>'linked_operation_div'.$div,'label'=>
$a_tab['document_operation_div']=array('id'=>'document_operation_div'.$div,'label'=>_('Document').'('.$nb_document.')','display'=>'block');
$a_tab['linked_action_div']=array('id'=>'linked_action_div'.$div,'label'=>_('Actions Gestion').'('.count($a_followup).')','display'=>'none');
$a_tab['analytic_div']=array('id'=>'analytic_div'.$div,'label'=>_('Comptabilité Analytique'),'display'=>'none');
$a_tab['tag_operation_div']=array('id'=>'tag_operation_div'.$div,'label'=>_('Etiquette'),'display'=>'none');
// show tabs
@ -308,7 +309,23 @@ require_once NOALYSS_TEMPLATE.'/ledger_detail_file.php';
</span>
<?php endif;?>
</div>
<div id="tag_operation_div<?=$div?>" style="overflow:auto;display:<?php echo $a_tab['tag_operation_div']['display']?>">
<div id="operation_tag_td<?=$div?>">
<?php
/******************************************************************************************************************
* Tags on operation
*****************************************************************************************************************/
$tag_operation=new Tag_Operation($cn);
$tag_operation->set_jrn_id($obj->det->jr_id);
$tag_operation->tag_cell($div);
?>
</div>
<?php
// Button add tags
if ( $access=='W') { echo Tag_Operation::button_search($obj->det->jr_id,$div);}
?>
</div>
<hr>
<?php
echo '<p style="text-align:center">';

View file

@ -87,5 +87,40 @@ echo $f_accounting->input(); ?>
<?php echo $f_paid->input(); ?>
</td>
</tr>
<tr>
<td style="text-align:right;width:30em">
<?php
$iselect= new ISelect($this->div."tag_option");
$iselect->value=array(
array("value"=>0,"label"=>_("Toutes les étiquettes")),
array("value"=>1,"label"=>_("Au moins une étiquette"))
);
$iselect->set_value($http->request($this->div."tag_option","number",0));
echo $iselect->input();
?>
<?php
echo Tag_Operation::select_tag_search($this->div);
?>
</td>
<td >
<span id="<?=$this->div?>tag_choose_td">
<?php
$aTag= $http->request($this->div."tag","string",0);
if (is_array($aTag) ) {
$nb_tag=count($aTag);
for ($j=0;$j< $nb_tag;$j++) {
$tag_operation=new Tag_Operation($this->cn,$aTag[$j]);
$tag_operation->update_search_cell($this->div);
}
}
?>
</span>
</td>
</tr>
</table>

View file

@ -27,15 +27,28 @@ if ( $max == 0 ) {
</tr>
<?php
$gDossier=Dossier::id();
$ag_id=$http->request("ag_id","number");
if (isNumber($ag_id) == 0 ) die ('ERROR : parameters invalid');
$id="none";
if ( get_class($this) == 'Tag_Action' ) {
$id=$http->request("ag_id","number");
} elseif (get_class($this)=='Tag_Operation')
{
$id=$http->request("jrn_id");
}
if (isNumber($id) == 0 ) die ('ERROR : parameters invalid');
for ($i=0;$i<$max;$i++):
$row=Database::fetch_array($ret, $i);
?>
<tr class="<?php echo (($i%2==0)?'even':'odd');?>">
<td class="tagcell-color<?=$row['t_color']?>">
<?php
$js=sprintf("action_tag_add('%s','%s','%s','%s')",$gDossier,$ag_id,$row['t_id'],$row['tag_type']);
if ( get_class($this) == 'Tag_Action' ) {
$js=sprintf("action_tag_add('%s','%s','%s','%s')",$gDossier,$id,$row['t_id'],$row['tag_type']);
} else {
$js=sprintf("new operation_tag('%s').add('%s','%s','%s','%s')",$p_prefix,$gDossier,$id,$row['t_id'],$row['tag_type']);
}
echo HtmlInput::anchor($row['t_tag'], "", "onclick=\"$js\"");
?>
</td>