diff --git a/html/css/style-classic7.css b/html/css/style-classic7.css
index 9b7d338f2..42a46484a 100644
--- a/html/css/style-classic7.css
+++ b/html/css/style-classic7.css
@@ -4089,4 +4089,16 @@ h2.h-section {
*/
.bt-error {
color:var(--color-red);
+}
+
+
+
+
+#jrn_note_td {
+
+ background-color: lightyellow;
+}
+
+.font-small {
+ font-size: 0.90rem;
}
\ No newline at end of file
diff --git a/html/js/noalyss_script.js b/html/js/noalyss_script.js
index 943328823..4590e6b7a 100644
--- a/html/js/noalyss_script.js
+++ b/html/js/noalyss_script.js
@@ -21,7 +21,8 @@
/**
*
- * javascript script, always added to every page
+ * javascript script, always added to every page, it is the first script and
+ * should contain all the global variables
*
*/
var ask_reload = 0;
@@ -34,6 +35,16 @@ var layer=0;
var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
var width = viewport.width; // Usable window width
var height = viewport.height;
+var g_enable_tinymce=true;
+/**
+ * if browser < 2021, function window.crypto.randomUUID is not implemented
+ * so we tinyMCE cannot work
+*/
+if ( ! window.crypto.randomUUID) {
+ console.info("too old browser: implement function randomUUID")
+ g_enable_tinymce=false;
+}
+
/**
* return undefined if nothing is found , otherwise return the DOM elemnt, try to find an DOM Element inside p_element
@@ -4726,6 +4737,7 @@ Noalyss = function () {
*/
Noalyss.prototype.activate_tinymce=function (domid,mode,p_height) {
+ if ( ! g_enable_tinymce ) return;
tinymce.remove('#'+domid);
if (! p_height) p_height=500;
if ( mode == 'minimal' || ! mode )
@@ -4800,5 +4812,130 @@ Noalyss.prototype.activate_tinymce=function (domid,mode,p_height) {
}
}
+/**
+ * Input NOTE on operation from Detail Operation
+ * @param {int} dossier_id
+ * @param {int} jrn_id
+ * @param {string} div_prefix
+ * @returns {undefined}
+ */
+Noalyss.prototype.input_note=function (dossier_id,jrn_id,div_prefix)
+{
+
+ try
+ {
+ var dgbox = "box_input_note"+div_prefix;
+ waiting_box();
+ removeDiv(dgbox);
+ var queryString = {
+ op:'ledger'
+ ,act:'note_input'
+ ,jr_id:jrn_id
+ ,div:div_prefix
+ ,gDossier:dossier_id
+ ,tinymce:g_enable_tinymce
+ };
+ var action = new Ajax.Request(
+ "ajax_misc.php",
+ {
+ method: 'get',
+ parameters: queryString,
+ onFailure: ajax_misc_failure,
+ onSuccess: function (req) {
+ remove_waiting_box();
+ if (req.responseText == 'NOCONX') {
+ reconnect();
+ return;
+ }
+ var y = calcy(15);
+ var div_style = "position:absolute;" + ";top:" + y + "px";
+ add_div({id: dgbox, cssclass: 'inner_box2', html: loading(), style: div_style, drag: true});
+ let response=req.responseXML;
+ let html=getNodeText(response.getElementsByTagName("code")[0])
+ let ctl=getNodeText(response.getElementsByTagName("ctl")[0]);
+ $(dgbox).update(html);
+
+ }
+ }
+ );
+ } catch (e)
+ {
+ alert_box(e.message);
+ }
+}
+/**
+ * Save note, call from ajax_ledger.php act = note_input
+ * @param {DOMObjet} dom_form
+ * @returns {undefined}
+ */
+Noalyss.prototype.save_note=function (dom_form)
+{
+ try
+ {
+ waiting_box();
+ let queryString=dom_form.serialize(true);
+ console.debug(queryString)
+ if ( g_enable_tinymce ) {
+ queryString['note_html'] = tinymce.get(queryString['input_html']).getContent();
+ }else{
+ queryString['note_html'] =$F($F('input_html'))
+ }
+ queryString['op'] = 'ledger';
+ var x=this;
+ var action = new Ajax.Request(
+ "ajax_misc.php",
+ {
+ method: 'POST',
+ parameters: queryString,
+ onFailure: ajax_misc_failure,
+ onSuccess: function (req) {
+ remove_waiting_box();
+ if (req.responseText == 'NOCONX') {
+ reconnect();
+ return;
+ }
+ let response=req.responseXML;
+ let html=getNodeText(response.getElementsByTagName("code")[0])
+ let ctl=getNodeText(response.getElementsByTagName("ctl")[0]);
+ console.debug(response);
+ $('note_html'+ctl).update(html);
+ x.refresh_note(queryString['jr_id'],queryString['gDossier']);
+ removeDiv('box_input_note'+queryString['div']);
+ }
+ }
+ );
+ } catch (e)
+ {
+ alert_box(e.message);
+ }
+
+}
+Noalyss.prototype.refresh_note=function(jrn_id,dossier_id)
+{
+ if ( document.getElementById("als_note"+jrn_id)) {
+ new Ajax.Updater('als_note'+jrn_id,'ajax_misc.php',{
+ method:'get',
+ parameters:{
+ op:'ledger'
+ ,'act':'note_refresh'
+ ,jr_id:jrn_id
+ ,gDossier:dossier_id
+ ,div:'not-set'
+ }
+ })
+ } else if ( document.getElementById("jrn_note_td")) {
+ new Ajax.Updater('jrn_note_td','ajax_misc.php',{
+ method:'get',
+ parameters:{
+ op:'ledger'
+ ,'act':'note_refresh'
+ ,jr_id:jrn_id
+ ,gDossier:dossier_id
+ ,div:'not-set'
+ }
+ })
+ }
+
+}
noalyss=new Noalyss();
diff --git a/include/ajax/ajax_ledger.php b/include/ajax/ajax_ledger.php
index c26cf593a..f988848b6 100644
--- a/include/ajax/ajax_ledger.php
+++ b/include/ajax/ajax_ledger.php
@@ -412,8 +412,7 @@ switch ($action) {
from jrnx join jrn on (j_grpt=jr_grpt_id)
where jr_id=$1)
', array($jr_id));
- $cn->exec_sql("select comptaproc.jrn_add_note($1,$2)",
- array($jr_id, $http->post('jrn_note')));
+
$rapt = $http->post('rapt');
if ($g_parameter->MY_UPDLAB == 'Y' && isset ($_POST['j_id'])) {
@@ -556,6 +555,66 @@ switch ($action) {
break;
+//------------------------------------------------
+// Display note
+//------------------------------------------------
+ case 'note_input':
+ $acc_operation_note= Acc_Operation_Note::build_jrn_id($jr_id);
+ try {
+ $ctl="box_input_note".$div;
+ $html=HtmlInput::title_box(_("Note"), $ctl);
+ $textarea= Acc_Operation_Note::build_textarea($div);
+ if ( $http->get('tinymce')=='true')
+ $textarea->value=$acc_operation_note->getJrnNoteSql()->get("n_html");
+ else {
+ $textarea->set_enrichText('plain');
+ $textarea->value=$acc_operation_note->getJrnNoteSql()->get("n_text");
+ }
+
+ // start FORM
+ $html.=sprintf('
";
+ } catch (Exception $exc) {
+ echo $exc->getTraceAsString();
+ }
+
+ break;
+ case 'note_save':
+//------------------------------------------------
+// save note
+//------------------------------------------------
+
+ /**
+ * received parameters
+ * - gDossier
+ * - div
+ * - jr_id
+ * - note_html
+ */
+ $ctl="box_input_note".$div;
+ $acc_operation_note= Acc_Operation_Note::build_jrn_id($jr_id);
+ $acc_operation_note->setOperation_id($jr_id);
+ $acc_operation_note->setNote($http->post("note_html",'raw'));
+ $acc_operation_note->save();
+ $html=$http->post("note_html","raw");
+ break;
+ case 'note_refresh':
+ $acc_operation_note= Acc_Operation_Note::build_jrn_id($jr_id);
+ echo $acc_operation_note->getNote();
+
+ return;
}
$html = escape_xml($html);
if (!headers_sent()) {
diff --git a/include/class/acc_ledger_sale.class.php b/include/class/acc_ledger_sale.class.php
index 5d3f554c8..81d4521fe 100644
--- a/include/class/acc_ledger_sale.class.php
+++ b/include/class/acc_ledger_sale.class.php
@@ -1026,7 +1026,7 @@ class Acc_Ledger_Sale extends Acc_Ledger {
$r.=' ' . _('Client') . ' ' . HtmlInput::card_detail($e_client).":".hb( $client_name) . ' ';
$r.='';
$r.='';
- $r.=''._('Note').' '.h($p_array['jrn_note_input']).' ';
+ $r.=''._('Note').'
'.$p_array['jrn_note_input'].'
';
$r.='';
$r.='';
$r.='
';
diff --git a/include/class/acc_ledger_search.class.php b/include/class/acc_ledger_search.class.php
index 625c02e36..8ff7c4d81 100644
--- a/include/class/acc_ledger_search.class.php
+++ b/include/class/acc_ledger_search.class.php
@@ -343,6 +343,7 @@ class Acc_Ledger_Search
p_closed,
jr_pj_number,
n_text,
+ n_html,
(select string_agg(a,' ')
from (select ''||t_tag||' ' a
from operation_tag ot join tags t on(ot.tag_id=t.t_id)
@@ -943,7 +944,14 @@ class Acc_Ledger_Search
if ( $row['analytic_op'] != "")
$r.=sprintf('∋ ');
$r.="";
- $r.=td(h($row['n_text']), ' style="font-size:0.87em%"');
+ // Note
+ $r.='';
+ $r.='';
+ $r.= $row['n_text'];
+ $r.='';
+ $r.=' ';
+ $r.=' ';
+
// Amount
// If the ledger is financial :
// the credit must be negative and written in red
diff --git a/include/class/acc_operation.class.php b/include/class/acc_operation.class.php
index e4175573b..f7ed26821 100644
--- a/include/class/acc_operation.class.php
+++ b/include/class/acc_operation.class.php
@@ -1117,9 +1117,15 @@ class Acc_Detail extends Acc_Operation
{
$this->det->$key=$val;
}
- $sql="select n_text from jrn_note where jr_id=$1";
- $this->det->note=$this->db->get_value($sql,array($this->jr_id));
- $this->det->note=strip_tags($this->det->note);
+ $sql="select n_text,n_html from jrn_note where jr_id=$1";
+ $a=$this->db->get_row($sql,array($this->jr_id));
+ if ( empty($a)) {
+ $this->det->note="";
+ $this->det->note_html=null;
+ } else {
+ $this->det->note=strip_tags($a['n_text']);
+ $this->det->note_html=($a['n_html'] == "")?$a['n_text']:$a['n_html'];
+ }
}
/**
*
diff --git a/include/class/acc_operation_note.class.php b/include/class/acc_operation_note.class.php
index c6188b6e8..2d72c6fef 100644
--- a/include/class/acc_operation_note.class.php
+++ b/include/class/acc_operation_note.class.php
@@ -35,7 +35,7 @@ class Acc_Operation_Note
private $id;
private $operation_id; //!< jrn.jr_id
private $jrn_note_sql;
-
+
function __construct(Jrn_Note_SQL $p_Jrn_Note_SQL)
{
$this->jrn_note_sql = $p_Jrn_Note_SQL;
@@ -79,12 +79,18 @@ class Acc_Operation_Note
{
$cn=Dossier::connect();
$this->jrn_note_sql->setp("jr_id",$this->operation_id);
- $this->jrn_note_sql->setp("n_text",$this->note);
+ $this->jrn_note_sql->setp("n_text", strip_tags($this->note));
if ( empty($this->jrn_note_sql->n_text) && $this->id > -1 ) {
$this->jrn_note_sql->delete();
return $this;
}
+ // forbid the tag script, iframe and A
+ $n=str_ireplace('
EOF;
diff --git a/include/template/acc_operation_note-input.php b/include/template/acc_operation_note-input.php
index 2860e8e10..607f0b19a 100644
--- a/include/template/acc_operation_note-input.php
+++ b/include/template/acc_operation_note-input.php
@@ -21,15 +21,24 @@
* \brief display input textarea for operation note
* \see Acc_Operation_Note
*/
+//@var $note (itextarea);
+
+$note=new ITextarea("jrn_note_input");
+$note->set_enrichText("no-toolbar");
+$note->heigh=130;
+$note->value=$p_current;
+
?>
=\HtmlInput::title_box(_("Note"),"jrn_note_div","hide")?>
+=$note->input()?>
-
- =HtmlInput::button_hide("jrn_note_div")?>
+
+ =_("Fermer")?>
+
diff --git a/include/template/form_ledger_detail.php b/include/template/form_ledger_detail.php
index 7fe94e7e3..ed8e2d91a 100644
--- a/include/template/form_ledger_detail.php
+++ b/include/template/form_ledger_detail.php
@@ -71,12 +71,14 @@ $default_currency=new Acc_Currency(Dossier::connect(),0);
-
- =_("Note")?>
+
+
-
-
-
+
diff --git a/include/template/ledger_detail_ach.php b/include/template/ledger_detail_ach.php
index 1f088d878..e9fc3deaf 100644
--- a/include/template/ledger_detail_ach.php
+++ b/include/template/ledger_detail_ach.php
@@ -5,10 +5,17 @@
/**
* @var $str_anc String HTML contains the detail of analytic
* @var $g_user Noalyss_User inherited , it is the connected user
- * @var $div (string) current DIV ID
+ * @var $div (string) current DIV ID prefix (det
where is a number
*/
$str_anc="";
global $div,$g_parameter,$cn,$access,$jr_id,$obj;
+
+//@var $dossier_id (int) folder id
+$dossier_id=Dossier::id();
+
+//@var $jr_id (int) jrn.jr_id
+//@var $obj (Acc_Operation) current operation detail
+
?>
- Note
+
+ =_("Note")?>
+
-
- id="jrn_note";
- $inote->style=' class="itextarea" style="width:90%;height:100%;"';
- $inote->value = strip_tags($obj->det->note);
- echo $inote->input();
- ?>
-
+
+ =$obj->det->note_html?>
+
diff --git a/include/template/ledger_detail_fin.php b/include/template/ledger_detail_fin.php
index 35a95680a..326da5ced 100644
--- a/include/template/ledger_detail_fin.php
+++ b/include/template/ledger_detail_fin.php
@@ -3,6 +3,11 @@
//see licence.txt
$str_anc="";
global $g_parameter,$g_user;
+//@var $dossier_id (int) folder id
+$dossier_id=Dossier::id();
+
+//@var $jr_id (int) jrn.jr_id
+//@var $obj (Acc_Operation) current operation detail
//* @var $div (string) current DIV ID
?>
@@ -77,17 +82,14 @@ echo td(_('Pièce')).td($itext->input());
- Note
-
+
+ =_("Note")?>
+
+
+
-
- style=' class="itextarea" style="width:90%;height:100%;"';
- $inote->value = strip_tags($obj->det->note);
- echo $inote->input();
- ?>
-
+
+ =$obj->det->note_html?>
diff --git a/include/template/ledger_detail_misc.php b/include/template/ledger_detail_misc.php
index 375f1449c..f72da784f 100644
--- a/include/template/ledger_detail_misc.php
+++ b/include/template/ledger_detail_misc.php
@@ -10,6 +10,12 @@ require_once NOALYSS_TEMPLATE.'/ledger_detail_top.php';
$exercice=$periode_id->get_exercice();
$owner = new Noalyss_Parameter_Folder($cn);
//* @var $div (string) current DIV
+//@var $dossier_id (int) folder id
+$dossier_id=Dossier::id();
+
+//@var $jr_id (int) jrn.jr_id
+//@var $obj (Acc_Operation) current operation detail
+
?>
@@ -72,17 +78,13 @@ $owner = new Noalyss_Parameter_Folder($cn);
- Note
+
+ =_("Note")?>
+
-
- style=' class="itextarea" style="width:90%;height:100%;"';
- $inote->value = strip_tags($obj->det->note);
- echo $inote->input();
- ?>
-
+
+ =$obj->det->note_html?>
diff --git a/include/template/ledger_detail_ven.php b/include/template/ledger_detail_ven.php
index 0aafd1148..1690c228c 100644
--- a/include/template/ledger_detail_ven.php
+++ b/include/template/ledger_detail_ven.php
@@ -4,6 +4,12 @@
//* @var $div (string) current DIV
global $div, $g_parameter, $cn, $access, $jr_id, $obj,$g_user;
+//@var $dossier_id (int) folder id
+$dossier_id=Dossier::id();
+
+//@var $jr_id (int) jrn.jr_id
+//@var $obj (Acc_Operation) current operation detail
+
?>
@@ -109,18 +115,14 @@ $str_anc = "";
- Note
+
+ =_("Note")?>
+
-
- style = ' class="itextarea" style="width:90%;height:100%;"';
- $inote->value = strip_tags($obj->det->note);
- echo $inote->input();
- ?>
-
+
+ =$obj->det->note_html?>
diff --git a/sql/upgrade.sql b/sql/upgrade.sql
index 1c58add80..dac09c491 100644
--- a/sql/upgrade.sql
+++ b/sql/upgrade.sql
@@ -305,4 +305,39 @@ comment on sequence seq_doc_type_stdinv is 'Sequence for standard invoice';
INSERT INTO public.menu_ref (me_code, me_menu, me_file, me_url, me_description, me_parameter, me_javascript, me_type, me_description_etendue)
VALUES('RAW:xml-invoice', 'Exporte la facture XML', 'export_xml-invoice.php', NULL, 'export la facture électronique en XML', NULL, NULL, 'PR', NULL);
-insert into profile_menu (me_code,p_id, p_type_display) select 'RAW:xml-invoice',p_id,'P' from profile;
\ No newline at end of file
+insert into profile_menu (me_code,p_id, p_type_display) select 'RAW:xml-invoice',p_id,'P' from profile;
+
+alter table jrn_note add column n_html text;
+comment on columnt table.jrn_note is ' contains the HTML version from n_text';
+update jrn_note set n_html=n_text;
+
+-- replace jrn_add_note
+DROP FUNCTION comptaproc.jrn_add_note(int8, text);
+
+CREATE OR REPLACE FUNCTION comptaproc.jrn_add_note(p_jrid bigint, p_note text,p_note_html text)
+ RETURNS void
+ LANGUAGE plpgsql
+AS $function$
+declare
+ tmp bigint;
+begin
+ if length(trim(p_note)) = 0 then
+ delete from jrn_note where jr_id= p_jrid;
+ return;
+ end if;
+
+
+ select n_id into tmp from jrn_note where jr_id = p_jrid;
+ p_note_html := regexp_replace (p_note_html,'