noalyss-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Noalyss-commit] [noalyss] 65/73: Task #0001992: Prévision, calcul avec


From: Dany De Bontridder
Subject: [Noalyss-commit] [noalyss] 65/73: Task #0001992: Prévision, calcul avec comptabilité analytique
Date: Fri, 28 May 2021 05:26:48 -0400 (EDT)

sparkyx pushed a commit to branch master
in repository noalyss.

commit 1a632a2d1c8a8957e3c752e07ef1efd299fe8827
Author: sparkyx <danydb@noalyss.eu>
AuthorDate: Mon May 24 12:39:50 2021 +0200

    Task #0001992: Prévision, calcul avec comptabilité analytique
---
 html/ajax_misc.php                                 |   6 +-
 html/css/style-classic7.css                        |   4 +
 html/document/fr_be/bnb-asbl.form                  | 324 ++++++++--------
 html/document/fr_be/bnb.form                       | 282 +++++++-------
 html/js/scripts.js                                 |  30 ++
 include/ajax/ajax_forecast_item.php                |   2 +-
 include/ajax/ajax_report_definition.php            | 115 ++++++
 include/ajax/ajax_search_account_card.php          | 129 ++++++
 include/class/acc_report.class.php                 | 368 ++++--------------
 include/class/acc_report_mtable.class.php          | 129 ++++++
 include/class/acc_report_row.class.php             | 122 ------
 include/class/anc_account.class.php                |  99 +++++
 include/class/anticipation.class.php               |  38 +-
 include/class/document.class.php                   |  44 +--
 include/class/forecast.class.php                   |   4 +-
 include/class/forecast_item_mtable.class.php       |  38 +-
 include/class/user.class.php                       |   2 +-
 include/constant.php                               |   2 +-
 include/database/forecast_item_sql.class.php       |   4 -
 ...sql.class.php => form_definition_sql.class.php} |  43 +-
 ...tem_sql.class.php => form_detail_sql.class.php} |  48 +--
 include/export/export_reportinit_csv.php           |   3 +-
 include/impress_rapport.inc.php                    |  40 +-
 include/lib/ac_common.php                          |  25 +-
 include/lib/impress.class.php                      | 432 ++++++++++++++-------
 include/lib/manage_table_sql.class.php             |   9 +-
 include/lib/message_javascript.php                 |   3 +
 include/report.inc.php                             | 120 +++---
 .../sql/patch/upgrade160.sql                       |  29 ++
 include/template/acc_report-create.php             |  52 +++
 include/template/anticipation-display.php          |  32 +-
 include/template/dashboard.php                     |   4 +-
 include/template/forecast_item_mtable-input.php    |  59 +--
 scenario/test_parse_formula.php                    |  60 ---
 sql/upgrade.sql                                    |  33 --
 unit-test/create-dossier-test.sh                   |   2 +-
 unit-test/include/class/impressTest.class.php      |  61 ++-
 37 files changed, 1548 insertions(+), 1249 deletions(-)

diff --git a/html/ajax_misc.php b/html/ajax_misc.php
index 1bcf63f..ca89223 100644
--- a/html/ajax_misc.php
+++ b/html/ajax_misc.php
@@ -291,7 +291,11 @@ $path = array(
     // manage forecast
     "forecast"=>"ajax_forecast",
     // manage company
-    "company"=>"ajax_company"
+    "company"=>"ajax_company",
+    // report definition 
+    "report_definition"=>"ajax_report_definition",
+    // search all card , analytic or accounting
+    "search_account_card"=>"ajax_search_account_card"
 )    ;
 
 if (array_key_exists($op, $path)) {
diff --git a/html/css/style-classic7.css b/html/css/style-classic7.css
index 9ba0a8c..6866145 100644
--- a/html/css/style-classic7.css
+++ b/html/css/style-classic7.css
@@ -761,6 +761,10 @@ filter: progid:DXImageTransform.Microsoft.gradient( 
startColorstr='#ffffff', end
     color: #746B6B;
     font-family: SansationLight;
     font-size: 0.80rem;
+
+    padding: 9px;
+    color: navy;
+    font-size: 0.85rem;
 }
 a#anchorbutton:hover, .button:hover,a.button:hover,div.content a.button:hover  
{
     cursor:pointer;
diff --git a/html/document/fr_be/bnb-asbl.form 
b/html/document/fr_be/bnb-asbl.form
index 753466d..7aa525a 100644
--- a/html/document/fr_be/bnb-asbl.form
+++ b/html/document/fr_be/bnb-asbl.form
@@ -1,166 +1,166 @@
 # Les postesg*(-1)
-$C10=round([10%s],2)*(-1)
-$C100=round([100%s],2)*(-1)
-$C101=round([101%s],2)
-$C11=round([11%s],2)*(-1)
-$C12=round([12%s],2)*(-1)
-$C13=round([13%s],2)*(-1)
-$C130=round([130%s],2)*(-1)
-$C131=round([131%s],2)*(-1)
-$C1310=round([1310%s],2)*(-1)
-$C1311=round([1311%s],2)*(-1)
-$C132=round([132%s],2)*(-1)
-$C133=round([133%s],2)*(-1)
-$C14=round([14%s],2)*(-1)
-$C140=round([140%s],2)*(-1)
-$C141=round([141%s],2)
-$C15=round([15%s],2)*(-1)
-$C16=round([16%s],2)*(-1)
-$C160=round([160%s],2)*(-1)
-$C161=round([161%s],2)*(-1)
-$C162=round([162%s],2)*(-1)
-$C163=round([163%s],2)*(-1)
-$C164=round([164%s],2)*(-1)
-$C165=round([165%s],2)*(-1)
-$C168=round([168%s],2)*(-1)
-$C17=round([17%s],2)*(-1)
-$C170=round([170%s],2)*(-1)
-$C171=round([171%s],2)*(-1)
-$C172=round([172%s],2)*(-1)
-$C173=round([173%s],2)*(-1)
-$C174=round([174%s],2)*(-1)
-$C175=round([175%s],2)*(-1)
-$C176=round([176%s],2)*(-1)
-$C178=round([178%s],2)*(-1)
-$C179=round([179%s],2)*(-1)
-$C1790=round([1790%s],2)*(-1)
-$C1791=round([1791%s],2)*(-1)
-$C1792=round([1792%s],2)*(-1)
-$C19=round([19%s],2)*(-1)
-$C2=round([2%s],2)*(-1)
-$C20=round([20%s],2)
-$C21=round([21%s],2)
-$C22=round([22%s],2)
-$C2201=round([2201%s],2)
-$C2202=round([2202%s],2)
-$C2211=round([2211%s],2)
-$C2212=round([2212%s],2)
-$C2221=round([2221%s],2)
-$C2222=round([2222%s],2)
-$C2231=round([2231%s],2)
-$C2232=round([2232%s],2)
-$C23=round([23%s],2)
-$C231=round([231%s],2)
-$C232=round([232%s],2)
-$C24=round([24%s],2)
-$C241=round([241%s],2)
-$C242=round([242%s],2)
-$C25=round([25%s],2)
-$C26=round([26%s],2)
-$C27=round([27%s],2)
-$C28=round([28%s],2)
-$C29=round([29%s],2)
-$C290=round([290%s],2)
-$C291=round([291%s],2)
-$C2915=round([2915%s],2)
-$C3=round([3%s],2)
-$C30=round([30%s],2)
-$C31=round([31%s],2)
-$C32=round([32%s],2)
-$C33=round([33%s],2)
-$C34=round([34%s],2)
-$C35=round([35%s],2)
-$C36=round([36%s],2)
-$C37=round([37%s],2)
-$C40=round([40%s],2)
-$C41=round([41%s],2)
-$C415=round([415%s],2)
-$C42=round([42%s],2)*(-1)
-$C43=round([43%s],2)*(-1)
-$C439=round([439%s],2)*(-1)
-$C44=round([44%s],2)*(-1)
-$C440=round([440%s],2)*(-1)
-$C441=round([441%s],2)*(-1)
-$C444=round([444%s],2)*(-1)
-$C45=round([45%s],2)*(-1)
-$C450=round([450%s],2)*(-1)
-$C451=round([451%s],2)*(-1)
-$C452=round([452%s],2)*(-1)
-$C453=round([453%s],2)*(-1)
-$C454=round([454%s],2)*(-1)
-$C455=round([455%s],2)*(-1)
-$C456=round([456%s],2)*(-1)
-$C457=round([457%s],2)*(-1)
-$C458=round([458%s],2)*(-1)
-$C459=round([459%s],2)*(-1)
-$C46=round([46%s],2)
-$C47=round([47%s],2)*(-1)
-$C48=round([48%s],2)*(-1)
-$C480=round([480%s],2)*(-1)
-$C488=round([488%s],2)*(-1)
-$C4890=round([4890%s],2)*(-1)
-$C4891=round([4891%s],2)*(-1)
-$C49=round([49%s],2)
-$C490=round([490%s],2)
-$C491=round([491%s],2)
-$C492=round([492%s],2)*(-1)
-$C493=round([493%s],2)*(-1)
-$C50=round([50%s],2)
-$C51=round([51%s],2)
-$C52=round([52%s],2)
-$C53=round([53%s],2)
-$C54=round([54%s],2)
-$C55=round([55%s],2)
-$C56=round([56%s],2)
-$C57=round([57%s],2)
-$C58=round([58%s],2)
-$C60=round([60%s],2)
-$C61=round([61%s],2)
-$C62=round([62%s],2)
-$C63=round([63%s],2)
-$C630=round([630%s],2)
-$C631=round([631%s],2)
-$C632=round([632%s],2)
-$C633=round([633%s],2)
-$C634=round([634%s],2)
-$C635=round([635%s],2)
-$C636=round([636%s],2)
-$C637=round([637%s],2)
-$C649=round([649%s],2)*(-1)
-$C64=round([64%s],2)
-$C65=round([65%s],2)
-$C66=round([66%s],2)
-$C67=round([67%s],2)
-$C68=round([68%s],2)
-$C680=round([680%s],2)
-$C689=round([689%s],2)
-$C69=round([69%s],2)
-$C690=round([690%s],2)
-$C691=round([691%s],2)
-$C692=round([692%s],2)
-$C6920=round([6920%s],2)
-$C6921=round([6921%s],2)
-$C693=round([693%s],2)
-$C694=round([694%s],2)
-$C695=round([695%s],2)
-$C696=round([696%s],2)
-$C7=round([7%s],2)*(-1)
-$C70=round([70%s],2)*(-1)
-$C71=round([71%s],2)*(-1)
-$C73=round([73%s],2)*(-1)
-$C72=round([72%s],2)*(-1)
-$C74=round([74%s],2)*(-1)
-$C75=round([75%s],2)*(-1)
-$C76=round([76%s],2)*(-1)
-$C77=round([77%s],2)*(-1)
-$C780=round([780%s],2)*(-1)
-$C789=round([789%s],2)*(-1)
-$C79=round([79%s],2)*(-1)
-$C790=round([790%s],2)*(-1)
-$C791=round([791%s],2)*(-1)
-$C792=round([792%s],2)*(-1)
-$C793=round([793%s],2)*(-1)
-$C794=round([794%s],2)*(-1)
+$C10=round([10%-s],2)*(-1)
+$C100=round([100%-s],2)*(-1)
+$C101=round([101%-s],2)
+$C11=round([11%-s],2)*(-1)
+$C12=round([12%-s],2)*(-1)
+$C13=round([13%-s],2)*(-1)
+$C130=round([130%-s],2)*(-1)
+$C131=round([131%-s],2)*(-1)
+$C1310=round([1310%-s],2)*(-1)
+$C1311=round([1311%-s],2)*(-1)
+$C132=round([132%-s],2)*(-1)
+$C133=round([133%-s],2)*(-1)
+$C14=round([14%-s],2)*(-1)
+$C140=round([140%-s],2)*(-1)
+$C141=round([141%-s],2)
+$C15=round([15%-s],2)*(-1)
+$C16=round([16%-s],2)*(-1)
+$C160=round([160%-s],2)*(-1)
+$C161=round([161%-s],2)*(-1)
+$C162=round([162%-s],2)*(-1)
+$C163=round([163%-s],2)*(-1)
+$C164=round([164%-s],2)*(-1)
+$C165=round([165%-s],2)*(-1)
+$C168=round([168%-s],2)*(-1)
+$C17=round([17%-s],2)*(-1)
+$C170=round([170%-s],2)*(-1)
+$C171=round([171%-s],2)*(-1)
+$C172=round([172%-s],2)*(-1)
+$C173=round([173%-s],2)*(-1)
+$C174=round([174%-s],2)*(-1)
+$C175=round([175%-s],2)*(-1)
+$C176=round([176%-s],2)*(-1)
+$C178=round([178%-s],2)*(-1)
+$C179=round([179%-s],2)*(-1)
+$C1790=round([1790%-s],2)*(-1)
+$C1791=round([1791%-s],2)*(-1)
+$C1792=round([1792%-s],2)*(-1)
+$C19=round([19%-s],2)*(-1)
+$C2=round([2%-s],2)*(-1)
+$C20=round([20%-s],2)
+$C21=round([21%-s],2)
+$C22=round([22%-s],2)
+$C2201=round([2201%-s],2)
+$C2202=round([2202%-s],2)
+$C2211=round([2211%-s],2)
+$C2212=round([2212%-s],2)
+$C2221=round([2221%-s],2)
+$C2222=round([2222%-s],2)
+$C2231=round([2231%-s],2)
+$C2232=round([2232%-s],2)
+$C23=round([23%-s],2)
+$C231=round([231%-s],2)
+$C232=round([232%-s],2)
+$C24=round([24%-s],2)
+$C241=round([241%-s],2)
+$C242=round([242%-s],2)
+$C25=round([25%-s],2)
+$C26=round([26%-s],2)
+$C27=round([27%-s],2)
+$C28=round([28%-s],2)
+$C29=round([29%-s],2)
+$C290=round([290%-s],2)
+$C291=round([291%-s],2)
+$C2915=round([2915%-s],2)
+$C3=round([3%-s],2)
+$C30=round([30%-s],2)
+$C31=round([31%-s],2)
+$C32=round([32%-s],2)
+$C33=round([33%-s],2)
+$C34=round([34%-s],2)
+$C35=round([35%-s],2)
+$C36=round([36%-s],2)
+$C37=round([37%-s],2)
+$C40=round([40%-s],2)
+$C41=round([41%-s],2)
+$C415=round([415%-s],2)
+$C42=round([42%-s],2)*(-1)
+$C43=round([43%-s],2)*(-1)
+$C439=round([439%-s],2)*(-1)
+$C44=round([44%-s],2)*(-1)
+$C440=round([440%-s],2)*(-1)
+$C441=round([441%-s],2)*(-1)
+$C444=round([444%-s],2)*(-1)
+$C45=round([45%-s],2)*(-1)
+$C450=round([450%-s],2)*(-1)
+$C451=round([451%-s],2)*(-1)
+$C452=round([452%-s],2)*(-1)
+$C453=round([453%-s],2)*(-1)
+$C454=round([454%-s],2)*(-1)
+$C455=round([455%-s],2)*(-1)
+$C456=round([456%-s],2)*(-1)
+$C457=round([457%-s],2)*(-1)
+$C458=round([458%-s],2)*(-1)
+$C459=round([459%-s],2)*(-1)
+$C46=round([46%-s],2)
+$C47=round([47%-s],2)*(-1)
+$C48=round([48%-s],2)*(-1)
+$C480=round([480%-s],2)*(-1)
+$C488=round([488%-s],2)*(-1)
+$C4890=round([4890%-s],2)*(-1)
+$C4891=round([4891%-s],2)*(-1)
+$C49=round([49%-s],2)
+$C490=round([490%-s],2)
+$C491=round([491%-s],2)
+$C492=round([492%-s],2)*(-1)
+$C493=round([493%-s],2)*(-1)
+$C50=round([50%-s],2)
+$C51=round([51%-s],2)
+$C52=round([52%-s],2)
+$C53=round([53%-s],2)
+$C54=round([54%-s],2)
+$C55=round([55%-s],2)
+$C56=round([56%-s],2)
+$C57=round([57%-s],2)
+$C58=round([58%-s],2)
+$C60=round([60%-s],2)
+$C61=round([61%-s],2)
+$C62=round([62%-s],2)
+$C63=round([63%-s],2)
+$C630=round([630%-s],2)
+$C631=round([631%-s],2)
+$C632=round([632%-s],2)
+$C633=round([633%-s],2)
+$C634=round([634%-s],2)
+$C635=round([635%-s],2)
+$C636=round([636%-s],2)
+$C637=round([637%-s],2)
+$C649=round([649%-s],2)*(-1)
+$C64=round([64%-s],2)
+$C65=round([65%-s],2)
+$C66=round([66%-s],2)
+$C67=round([67%-s],2)
+$C68=round([68%-s],2)
+$C680=round([680%-s],2)
+$C689=round([689%-s],2)
+$C69=round([69%-s],2)
+$C690=round([690%-s],2)
+$C691=round([691%-s],2)
+$C692=round([692%-s],2)
+$C6920=round([6920%-s],2)
+$C6921=round([6921%-s],2)
+$C693=round([693%-s],2)
+$C694=round([694%-s],2)
+$C695=round([695%-s],2)
+$C696=round([696%-s],2)
+$C7=round([7%-s],2)*(-1)
+$C70=round([70%-s],2)*(-1)
+$C71=round([71%-s],2)*(-1)
+$C73=round([73%-s],2)*(-1)
+$C72=round([72%-s],2)*(-1)
+$C74=round([74%-s],2)*(-1)
+$C75=round([75%-s],2)*(-1)
+$C76=round([76%-s],2)*(-1)
+$C77=round([77%-s],2)*(-1)
+$C780=round([780%-s],2)*(-1)
+$C789=round([789%-s],2)*(-1)
+$C79=round([79%-s],2)*(-1)
+$C790=round([790%-s],2)*(-1)
+$C791=round([791%-s],2)*(-1)
+$C792=round([792%-s],2)*(-1)
+$C793=round([793%-s],2)*(-1)
+$C794=round([794%-s],2)*(-1)
 # Les formules (*-1)
 #
 $S1=$C20+$C21+$C22+$C23+$C24+$C25+$C26+$C27+$C28
diff --git a/html/document/fr_be/bnb.form b/html/document/fr_be/bnb.form
index 0328ced..f35598c 100644
--- a/html/document/fr_be/bnb.form
+++ b/html/document/fr_be/bnb.form
@@ -1,148 +1,148 @@
 # Les postesg*(-1)
-$C10=round([10%s],2)*(-1)
-$C100=round([100%s],2)*(-1)
-$C101=round([101%s],2)
-$C11=round([11%s],2)*(-1)
-$C12=round([12%s],2)*(-1)
-$C13=round([13%s],2)*(-1)
-$C130=round([130%s],2)*(-1)
-$C131=round([131%s],2)*(-1)
-$C1310=round([1310%s],2)*(-1)
-$C1311=round([1311%s],2)*(-1)
-$C132=round([132%s],2)*(-1)
-$C133=round([133%s],2)*(-1)
-$C14=round([14%s],2)*(-1)
-$C140=round([140%s],2)*(-1)
-$C141=round([141%s],2)
-$C15=round([15%s],2)*(-1)
-$C16=round([16%s],2)*(-1)
-$C160=round([160%s],2)*(-1)
-$C161=round([161%s],2)*(-1)
-$C162=round([162%s],2)*(-1)
-$C163=round([163%s],2)*(-1)
-$C164=round([164%s],2)*(-1)
-$C165=round([165%s],2)*(-1)
-$C168=round([168%s],2)*(-1)
-$C17=round([17%s],2)*(-1)
-$C170=round([170%s],2)*(-1)
-$C171=round([171%s],2)*(-1)
-$C172=round([172%s],2)*(-1)
-$C173=round([173%s],2)*(-1)
-$C174=round([174%s],2)*(-1)
-$C175=round([175%s],2)*(-1)
-$C176=round([176%s],2)*(-1)
-$C178=round([178%s],2)*(-1)
-$C179=round([179%s],2)*(-1)
-$C19=round([19%s],2)*(-1)
-$C2=round([2%s],2)*(-1)
-$C20=round([20%s],2)
-$C21=round([21%s],2)
-$C22=round([22%s],2)
-$C23=round([23%s],2)
-$C24=round([24%s],2)
-$C25=round([25%s],2)
-$C26=round([26%s],2)
-$C27=round([27%s],2)
-$C28=round([28%s],2)
-$C29=round([29%s],2)
-$C290=round([290%s],2)
-$C291=round([291%s],2)
-$C3=round([3%s],2)
-$C30=round([30%s],2)
-$C31=round([31%s],2)
-$C32=round([32%s],2)
-$C33=round([33%s],2)
-$C34=round([34%s],2)
-$C35=round([35%s],2)
-$C36=round([36%s],2)
-$C37=round([37%s],2)
-$C40=round([40%s],2)
-$C41=round([41%s],2)
-$C42=round([42%s],2)*(-1)
-$C43=round([43%s],2)*(-1)
-$C439=round([439%s],2)*(-1)
-$C44=round([44%s],2)*(-1)
-$C440=round([440%s],2)*(-1)
-$C441=round([441%s],2)*(-1)
-$C444=round([444%s],2)*(-1)
-$C45=round([45%s],2)*(-1)
-$C450=round([450%s],2)*(-1)
-$C451=round([451%s],2)*(-1)
-$C452=round([452%s],2)*(-1)
-$C453=round([453%s],2)*(-1)
-$C454=round([454%s],2)*(-1)
-$C455=round([455%s],2)*(-1)
-$C456=round([456%s],2)*(-1)
-$C457=round([457%s],2)*(-1)
-$C458=round([458%s],2)*(-1)
-$C459=round([459%s],2)*(-1)
-$C46=round([46%s],2)
-$C47=round([47%s],2)*(-1)
-$C48=round([48%s],2)*(-1)
-$C49=round([49%s],2)
-$C490=round([490%s],2)
-$C491=round([491%s],2)
-$C492=round([492%s],2)*(-1)
-$C493=round([493%s],2)*(-1)
-$C50=round([50%s],2)
-$C51=round([51%s],2)
-$C52=round([52%s],2)
-$C53=round([53%s],2)
-$C54=round([54%s],2)
-$C55=round([55%s],2)
-$C56=round([56%s],2)
-$C57=round([57%s],2)
-$C58=round([58%s],2)
-$C60=round([60%s],2)
-$C61=round([61%s],2)
-$C62=round([62%s],2)
-$C63=round([63%s],2)
-$C630=round([630%s],2)
-$C631=round([631%s],2)
-$C632=round([632%s],2)
-$C633=round([633%s],2)
-$C634=round([634%s],2)
-$C635=round([635%s],2)
-$C636=round([636%s],2)
-$C637=round([637%s],2)
+$C10=round([10%-s],2)*(-1)
+$C100=round([100%-s],2)*(-1)
+$C101=round([101%-s],2)
+$C11=round([11%-s],2)*(-1)
+$C12=round([12%-s],2)*(-1)
+$C13=round([13%-s],2)*(-1)
+$C130=round([130%-s],2)*(-1)
+$C131=round([131%-s],2)*(-1)
+$C1310=round([1310%-s],2)*(-1)
+$C1311=round([1311%-s],2)*(-1)
+$C132=round([132%-s],2)*(-1)
+$C133=round([133%-s],2)*(-1)
+$C14=round([14%-s],2)*(-1)
+$C140=round([140%-s],2)*(-1)
+$C141=round([141%-s],2)
+$C15=round([15%-s],2)*(-1)
+$C16=round([16%-s],2)*(-1)
+$C160=round([160%-s],2)*(-1)
+$C161=round([161%-s],2)*(-1)
+$C162=round([162%-s],2)*(-1)
+$C163=round([163%-s],2)*(-1)
+$C164=round([164%-s],2)*(-1)
+$C165=round([165%-s],2)*(-1)
+$C168=round([168%-s],2)*(-1)
+$C17=round([17%-s],2)*(-1)
+$C170=round([170%-s],2)*(-1)
+$C171=round([171%-s],2)*(-1)
+$C172=round([172%-s],2)*(-1)
+$C173=round([173%-s],2)*(-1)
+$C174=round([174%-s],2)*(-1)
+$C175=round([175%-s],2)*(-1)
+$C176=round([176%-s],2)*(-1)
+$C178=round([178%-s],2)*(-1)
+$C179=round([179%-s],2)*(-1)
+$C19=round([19%-s],2)*(-1)
+$C2=round([2%-s],2)*(-1)
+$C20=round([20%-s],2)
+$C21=round([21%-s],2)
+$C22=round([22%-s],2)
+$C23=round([23%-s],2)
+$C24=round([24%-s],2)
+$C25=round([25%-s],2)
+$C26=round([26%-s],2)
+$C27=round([27%-s],2)
+$C28=round([28%-s],2)
+$C29=round([29%-s],2)
+$C290=round([290%-s],2)
+$C291=round([291%-s],2)
+$C3=round([3%-s],2)
+$C30=round([30%-s],2)
+$C31=round([31%-s],2)
+$C32=round([32%-s],2)
+$C33=round([33%-s],2)
+$C34=round([34%-s],2)
+$C35=round([35%-s],2)
+$C36=round([36%-s],2)
+$C37=round([37%-s],2)
+$C40=round([40%-s],2)
+$C41=round([41%-s],2)
+$C42=round([42%-s],2)*(-1)
+$C43=round([43%-s],2)*(-1)
+$C439=round([439%-s],2)*(-1)
+$C44=round([44%-s],2)*(-1)
+$C440=round([440%-s],2)*(-1)
+$C441=round([441%-s],2)*(-1)
+$C444=round([444%-s],2)*(-1)
+$C45=round([45%-s],2)*(-1)
+$C450=round([450%-s],2)*(-1)
+$C451=round([451%-s],2)*(-1)
+$C452=round([452%-s],2)*(-1)
+$C453=round([453%-s],2)*(-1)
+$C454=round([454%-s],2)*(-1)
+$C455=round([455%-s],2)*(-1)
+$C456=round([456%-s],2)*(-1)
+$C457=round([457%-s],2)*(-1)
+$C458=round([458%-s],2)*(-1)
+$C459=round([459%-s],2)*(-1)
+$C46=round([46%-s],2)
+$C47=round([47%-s],2)*(-1)
+$C48=round([48%-s],2)*(-1)
+$C49=round([49%-s],2)
+$C490=round([490%-s],2)
+$C491=round([491%-s],2)
+$C492=round([492%-s],2)*(-1)
+$C493=round([493%-s],2)*(-1)
+$C50=round([50%-s],2)
+$C51=round([51%-s],2)
+$C52=round([52%-s],2)
+$C53=round([53%-s],2)
+$C54=round([54%-s],2)
+$C55=round([55%-s],2)
+$C56=round([56%-s],2)
+$C57=round([57%-s],2)
+$C58=round([58%-s],2)
+$C60=round([60%-s],2)
+$C61=round([61%-s],2)
+$C62=round([62%-s],2)
+$C63=round([63%-s],2)
+$C630=round([630%-s],2)
+$C631=round([631%-s],2)
+$C632=round([632%-s],2)
+$C633=round([633%-s],2)
+$C634=round([634%-s],2)
+$C635=round([635%-s],2)
+$C636=round([636%-s],2)
+$C637=round([637%-s],2)
 
-$C649=round([649%s],2)*(-1)
-$C64=round([64%s],2)
+$C649=round([649%-s],2)*(-1)
+$C64=round([64%-s],2)
 
-$C65=round([65%s],2)
-$C66=round([66%s],2)
-$C67=round([67%s],2)
-$C68=round([68%s],2)
-$C680=round([680%s],2)
-$C689=round([689%s],2)
-$C69=round([69%s],2)
-$C690=round([690%s],2)
-$C691=round([691%s],2)
-$C692=round([692%s],2)
-$C6920=round([6920%s],2)
-$C6921=round([6921%s],2)
-$C693=round([693%s],2)
-$C694=round([694%s],2)
-$C695=round([695%s],2)
-$C696=round([696%s],2)
+$C65=round([65%-s],2)
+$C66=round([66%-s],2)
+$C67=round([67%-s],2)
+$C68=round([68%-s],2)
+$C680=round([680%-s],2)
+$C689=round([689%-s],2)
+$C69=round([69%-s],2)
+$C690=round([690%-s],2)
+$C691=round([691%-s],2)
+$C692=round([692%-s],2)
+$C6920=round([6920%-s],2)
+$C6921=round([6921%-s],2)
+$C693=round([693%-s],2)
+$C694=round([694%-s],2)
+$C695=round([695%-s],2)
+$C696=round([696%-s],2)
 
-$C7=round([7%s],2)*(-1)
-$C70=round([70%s],2)*(-1)
-$C71=round([71%s],2)*(-1)
-$C73=round([73%s],2)*(-1)
-$C72=round([72%s],2)*(-1)
-$C74=round([74%s],2)*(-1)
-$C75=round([75%s],2)*(-1)
-$C76=round([76%s],2)*(-1)
-$C77=round([77%s],2)*(-1)
-$C780=round([780%s],2)*(-1)
-$C789=round([789%s],2)*(-1)
-$C79=round([79%s],2)*(-1)
-$C790=round([790%s],2)*(-1)
-$C791=round([791%s],2)*(-1)
-$C792=round([792%s],2)*(-1)
-$C793=round([793%s],2)*(-1)
-$C794=round([794%s],2)*(-1)
+$C7=round([7%-s],2)*(-1)
+$C70=round([70%-s],2)*(-1)
+$C71=round([71%-s],2)*(-1)
+$C73=round([73%-s],2)*(-1)
+$C72=round([72%-s],2)*(-1)
+$C74=round([74%-s],2)*(-1)
+$C75=round([75%-s],2)*(-1)
+$C76=round([76%-s],2)*(-1)
+$C77=round([77%-s],2)*(-1)
+$C780=round([780%-s],2)*(-1)
+$C789=round([789%-s],2)*(-1)
+$C79=round([79%-s],2)*(-1)
+$C790=round([790%-s],2)*(-1)
+$C791=round([791%-s],2)*(-1)
+$C792=round([792%-s],2)*(-1)
+$C793=round([793%-s],2)*(-1)
+$C794=round([794%-s],2)*(-1)
 # Les formules (*-1)
 #
 $S1=$C20+$C21+$C22+$C23+$C24+$C25+$C26+$C27+$C28
diff --git a/html/js/scripts.js b/html/js/scripts.js
index 3961372..46f92b0 100644
--- a/html/js/scripts.js
+++ b/html/js/scripts.js
@@ -4059,3 +4059,33 @@ function download_document_form(p_form_id)
    remove_waiting_box();
    return false;
 }
+/**
+ * Search an account or an analytic account or a card, used in REPORT
+ * @param {json} p_obj , 
+ *          property : - op for ajax_misc  , 
+ *                     - gDossier, 
+ *                     - target DOM element to update with the result
+ *                     - query  for the search
+ * @returns {void}
+ */
+function search_account_card(p_obj)
+{
+    p_obj['op']=p_obj['op']||"search_account_card";
+    var query=p_obj;
+    if (p_obj.tagName && p_obj.tagName=='FORM') {
+        query=p_obj.serialize(true);
+    }
+    
+    waiting_box();
+    new Ajax.Request("ajax_misc.php",{method:"get",parameters:query,
+        onSuccess: function (req){
+            
+            var pos=calcy(50);
+            var 
obj={id:"search_account_div",cssclass:"inner_box",style:"top:"+pos+"px",
+            html:req.responseText};
+            add_div(obj);
+            remove_waiting_box();
+        }
+    });
+    return false;
+}
\ No newline at end of file
diff --git a/include/ajax/ajax_forecast_item.php 
b/include/ajax/ajax_forecast_item.php
index 5b92b78..e509b54 100644
--- a/include/ajax/ajax_forecast_item.php
+++ b/include/ajax/ajax_forecast_item.php
@@ -49,7 +49,7 @@ if ($action=="input")
     echo $forecast_item->ajax_input()->saveXML();
     return;
 }elseif ($action == "save") {
-    $forecast_item->send_header();
+   $forecast_item->send_header();
     echo $forecast_item->ajax_save()->saveXML();
     return;
 } elseif ($action == "delete") {
diff --git a/include/ajax/ajax_report_definition.php 
b/include/ajax/ajax_report_definition.php
new file mode 100644
index 0000000..3313926
--- /dev/null
+++ b/include/ajax/ajax_report_definition.php
@@ -0,0 +1,115 @@
+<?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-2021) Author Dany De Bontridder <danydb@noalyss.eu>
+
+if (!defined('ALLOWED'))
+    die('Appel direct ne sont pas permis');
+
+/**
+ * @file
+ * @brief manage the simple report definition
+ */
+$http=new HttpInput();
+$sa=$http->request('sa', "string", "acc_report_mtable");
+if ($sa =="acc_report_mtable")
+{
+
+    try
+    {
+        $ctl=$http->request('ctl');
+        $id=$http->request("p_id", "number");
+        $action=$http->request("action");
+        $form_def=$http->request("form_def", "number");
+    }
+    catch (Exception $ex)
+    {
+        die("invalid data");
+    }
+
+    require_once NOALYSS_INCLUDE."/class/acc_report_mtable.class.php";
+
+    $acc_report=Acc_Report_MTable::build($id, $form_def);
+    $acc_report->set_object_name($ctl);
+
+    if ($action=='input')
+    {
+        $acc_report->send_header();
+        echo $acc_report->ajax_input()->saveXML();
+        return;
+    }
+    elseif ($action=='save')
+    {
+        $acc_report->send_header();
+        echo $acc_report->ajax_save()->saveXML();
+        return;
+    }
+    elseif ($action=="delete")
+    {
+        $acc_report->send_header();
+        echo $acc_report->ajax_delete()->saveXML();
+        return;
+    }
+}elseif ($sa == "change_name")
+{   
+    try
+    {
+        $id=$http->request("p_id");
+        $input=$http->request("input");
+        $action=$http->request("ieaction","string","display");
+    }
+    catch (Exception $exc)
+    {
+        echo $exc->getMessage();
+        
+    }
+    if ( $action == "display" ) {
+        $iName=Inplace_Edit::build($input);
+        $iName->set_callback("ajax_misc.php");
+        $iName->add_json_param("op", "report_definition");
+        $iName->add_json_param("sa", "change_name");
+         $iName->add_json_param("gDossier", Dossier::id());
+        $iName->add_json_param("p_id", $id);
+        echo $iName->ajax_input();
+    } elseif ($action == "ok") {
+        $iName=Inplace_Edit::build($input);
+        $iName->set_callback("ajax_misc.php");
+        $iName->add_json_param("op", "report_definition");
+        $iName->add_json_param("sa", "change_name");
+        $iName->add_json_param("p_id", $id);
+        $iName->add_json_param("gDossier", Dossier::id());
+        $iName->set_value($http->request("value"));
+        echo $iName->value();
+      
+        $cn->exec_sql("update form_definition set fr_label=$1 where fr_id=$2",[
+                $http->request("value"),
+                $id]);
+    } elseif ($action == 'cancel'){
+         $iName=Inplace_Edit::build($input);
+        $iName->set_callback("ajax_misc.php");
+        $iName->add_json_param("op", "report_definition");
+        $iName->add_json_param("sa", "change_name");
+        $iName->add_json_param("p_id", $id);
+        $iName->add_json_param("gDossier", Dossier::id());
+        echo $iName->value();
+        
+    }
+
+    
+}
\ No newline at end of file
diff --git a/include/ajax/ajax_search_account_card.php 
b/include/ajax/ajax_search_account_card.php
new file mode 100644
index 0000000..60cf011
--- /dev/null
+++ b/include/ajax/ajax_search_account_card.php
@@ -0,0 +1,129 @@
+<?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-2021) Author Dany De Bontridder <danydb@noalyss.eu>
+
+if (!defined('ALLOWED'))
+    die('Appel direct ne sont pas permis');
+
+/**
+ * @file
+ * @brief search cards , accounting or analytic account
+ */
+$http=new HttpInput();
+try
+{
+    $query=$http->request("query","string","");
+    $target=$http->request("target");
+}
+catch (Exception $exc)
+{
+    die ($exc->getMessage());
+}
+
+echo HtmlInput::title_box(_("Résultat"), "search_account_div") ;
+echo '<form method="GET" onsubmit="search_account_card(this);return false;"> ';
+$search_query=new IText("query",$query);
+echo $search_query->input();
+$select_limit=new ISelect("select_limit");
+$select_limit->value=array(
+        array("label"=>"25","value"=>25),
+        array("label"=>"50","value"=>50),
+        array("label"=>"100","value"=>100),
+        array("label"=>_("Tout"),"value"=>-1)
+);
+$select_limit->selected=$http->request('select_limit',"number",25);
+echo _("Max")." ".$select_limit->input();
+echo HtmlInput::hidden("op", "search_account_card");
+echo HtmlInput::hidden("target",$target);
+echo Dossier::hidden();
+echo HtmlInput::submit(uniqid(), _("Cherche"));
+echo '</form>';
+echo '<p class="text-muted">';
+echo _("Vous pouvez faire des opérations arithmétiques entre des postes 
comptables, des comptes analytiques et des fiches")
+;
+echo '</p>';
+$array=array();
+if ($query != "") {
+   
+    $array=$cn->get_array("
+        select quick_code as s_code,vw_name||' '
+            ||coalesce(vw_first_name,'') ||' '
+            ||coalesce(vw_description,'') as s_name,'C' as s_type from 
vw_fiche_attr vfa
+        where quick_code like upper('%'||$1||'%') or lower(vw_name) like 
'%'||$1||'%'
+        union all
+        select pcm_val, pcm_lib ,'A' from tmp_pcmn tp
+        where pcm_val like  '%'||$1||'%'
+        or lower(pcm_lib) like '%'||$1||'%'
+        union all
+        select po_name ,po_description , 'N' from poste_analytique pa
+        where 
+        po_name like '%'||$1||'%'
+        or po_description like '%'||$1||'%'
+        order by 1
+     
+",[$query]);
+}
+echo '<div id="search_account_card_result_div">';
+printf("Résultat %s",count($array));
+$max=$select_limit->selected;
+$idx=0;
+echo '<ul class="">';
+$close=";document.getElementById('search_account_div').remove();";
+foreach ($array as $item) {
+    
+    if ($max <> -1 && $idx >= $max) {
+        break;
+    }
+    $idx++;
+    echo '<li class="list-group-item">';
+    switch ($item['s_type'])
+    {
+        case 'N':
+            // analytic account
+            
$js=sprintf('onclick="document.getElementById(\'%s\').value+=\'{{%s}}\' 
;%s"',$target,$item['s_code'],$close);
+
+            break;
+        case 'A':
+            // Accounting
+            
$js=sprintf('onclick="document.getElementById(\'%s\').value+=\'[%s]\' 
;%s"',$target,$item['s_code'],$close);
+                
+
+            break;
+        case 'C':
+            // card
+            
$js=sprintf('onclick="document.getElementById(\'%s\').value+=\'{%s}\' 
;%s"',$target,$item['s_code'],$close);
+
+            break;
+        default:
+            throw Exception ("Invalid result");
+    } 
+      
+      echo '<input type="checkbox" '.$js.'>';
+        echo h($item['s_code']);
+        echo "  ";
+        echo h($item['s_name']);
+    echo '</li>';
+}
+echo '</ul>';
+echo '</div>';
+?>
+<ul class="aligned-block">
+    <?=HtmlInput::button_close("search_account_div")?>
+</ul>
\ No newline at end of file
diff --git a/include/class/acc_report.class.php 
b/include/class/acc_report.class.php
index 952c40a..27ee504 100644
--- a/include/class/acc_report.class.php
+++ b/include/class/acc_report.class.php
@@ -23,8 +23,9 @@
 
 require_once NOALYSS_INCLUDE.'/lib/itext.class.php';
 require_once NOALYSS_INCLUDE.'/lib/ibutton.class.php';
-require_once NOALYSS_INCLUDE.'/class/acc_report_row.class.php';
 require_once NOALYSS_INCLUDE.'/lib/impress.class.php';
+require_once NOALYSS_INCLUDE.'/database/form_detail_sql.class.php';
+require_once NOALYSS_INCLUDE.'/database/form_definition_sql.class.php';
 
 /*!
  * \brief Class rapport  Create, view, modify and parse report
@@ -33,28 +34,29 @@ require_once NOALYSS_INCLUDE.'/lib/impress.class.php';
 class Acc_Report
 {
 
-    var $db;    /*!< $db database connx */
-    var $id;    /*!< $id formdef.fr_id */
-    var $name;  /*!< $name report's name */
-    var $aAcc_Report_row;              /*!< array of rapport_row */
+    private $form_definition; /*!< form_definition_sql
+  
     var $nb;
     /*!\brief  Constructor */
-    function __construct($p_cn,$p_id=0)
+    function __construct($p_cn,$p_id=-1)
     {
-        $this->db=$p_cn;
-        $this->id=$p_id;
-        $this->name='Nouveau';
-        $this->aAcc_Report_row=null;
+        $this->form_definition=new Form_Definition_SQL($p_cn,$p_id);
     }
-    /*!\brief Return the report's name
+    public function get_form_definition()
+    {
+        return $this->form_definition;
+    }
+
+    public function set_form_definition($form_definition): void
+    {
+        $this->form_definition=$form_definition;
+    }
+
+        /*!\brief Return the report's name
      */
     function get_name()
     {
-        $ret=$this->db->exec_sql("select fr_label from formdef where 
fr_id=".$this->id);
-        if (Database::num_row($ret) == 0) return $this->name;
-        $a=Database::fetch_array($ret,0);
-        $this->name=$a['fr_label'];
-        return $this->name;
+        return $this->form_definition->getp("fr_label");
     }
     /*!\brief return all the row and parse formula
      *        from a report
@@ -65,15 +67,15 @@ class Acc_Report
     function get_row($p_start,$p_end,$p_type_date)
     {
 
-        $Res=$this->db->exec_sql("select fo_id ,
+        $Res=$this->form_definition->cn->exec_sql("select fo_id ,
                                  fo_fr_id,
                                  fo_pos,
                                  fo_label,
                                  fo_formula,
-                                 fr_label from form
-                                 inner join formdef on fr_id=fo_fr_id
-                                 where fr_id =".$this->id.
-                                 "order by fo_pos");
+                                 fr_label from form_detail
+                                 inner join form_definition on fr_id=fo_fr_id
+                                 where fr_id =$1
+                                 order by 
fo_pos",array($this->form_definition->getp("fr_id")));
         $Max=Database::num_row($Res);
         if ($Max==0)
         {
@@ -84,7 +86,7 @@ class Acc_Report
         for ($i=0;$i<$Max;$i++)
         {
             $l_line=Database::fetch_array($Res,$i);
-            $col[]=Impress::parse_formula($this->db,
+            $col[]=Impress::parse_formula($this->form_definition->cn,
                                 $l_line['fo_label'],
                                 $l_line['fo_formula'],
                                 $p_start,
@@ -97,248 +99,40 @@ class Acc_Report
         $this->row=$col;
         return $col;
     }
-    /*!
-     * \brief  Display a form for encoding a new report or update one
-     *
-     * \param $p_line number of line
-     *
-     */
-    function form($p_line=0)
-    {
-
-        $r="";
-        if ($p_line == 0 ) $p_line=count($this->aAcc_Report_row);
-        $r.= dossier::hidden();
-        $r.= HtmlInput::hidden('line',$p_line);
-        $r.= HtmlInput::hidden('fr_id',$this->id);
-        $wForm=new IText();
-        $r.=_("Nom du rapport")." : ";
-        $r.=$wForm->input('form_nom',$this->name);
-
-        $r.= '<TABLE id="rap1" width="100%">';
-        $r.= "<TR>";
-        $r.= "<TH> Position </TH>";
-        $r.= "<TH> Texte </TH>";
-        $r.= "<TH> Formule</TH>";
-
-        $r.= '</TR>';
-        $wName=new IText();
-        $wName->size=40;
-        $wPos=new IText();
-        $wPos->size=3;
-        $wForm=new IText();
-        $wForm->size=35;
-        for ( $i =0 ; $i < $p_line;$i++)
-        {
-
-            $r.= "<TR>";
-
-            $r.= "<TD>";
-            $wPos->value=( 
isset($this->aAcc_Report_row[$i]->fo_pos))?$this->aAcc_Report_row[$i]->fo_pos:$i+1;
-            $r.=$wPos->input("pos".$i);
-            $r.= '</TD>';
-
-
-            $r.= "<TD>";
-            $wName->value=( 
isset($this->aAcc_Report_row[$i]->fo_label))?$this->aAcc_Report_row[$i]->fo_label:"";
-            $r.=$wName->input("text".$i);
-            $r.= '</TD>';
-
-            $r.='<td>';
-            $search=new IPoste("form".$i);
-            $search->size=50;
-            $search->value=( 
isset($this->aAcc_Report_row[$i]->fo_formula))?$this->aAcc_Report_row[$i]->fo_formula:"";
-            $search->label=_("Recherche poste");
-            $search->set_attribute('gDossier',dossier::id());
-            $search->set_attribute('bracket',1);
-            $search->set_attribute('no_overwrite',1);
-            $search->set_attribute('noquery',1);
-            $search->set_attribute('account',$search->name);
-            $search->set_attribute('ipopup','ipop_card');
-
-            $r.=$search->input();
-            $r.='</td>';
-
-
-            $r.= "</TR>";
-        }
-
-        $r.= "</TABLE>";
-        $wButton=new IButton();
-        $wButton->javascript=" rapport_add_row('".dossier::id()."')";
-        $wButton->label="Ajout d'une ligne";
-        $r.=$wButton->input();
-        return $r;
-
-    }
+   
     /*!\brief save into form and form_def
      */
     function save()
     {
-
-        if ( strlen(trim($this->name)) == 0 )
-            return;
-        if ( $this->id == 0 )
-            $this->insert();
-        else
-            $this->update();
-
-    }
-    function insert()
-    {
-        try
-        {
-            $this->db->start();
-            $ret_sql=$this->db->exec_sql(
-                         "insert into formdef (fr_label) values($1) returning 
fr_id",
-                         array($this->name)
-                     );
-            $this->id=Database::fetch_result($ret_sql,0,0);
-            $ix=1;
-            foreach ( $this->aAcc_Report_row as $row)
-            {
-                if ( strlen(trim($row->get_parameter("name"))) != 0 &&
-                        strlen(trim($row->get_parameter("formula"))) != 0 )
-                {
-                    
$ix=($row->get_parameter("position")!="")?$row->get_parameter("position"):$ix;
-                    $row->set_parameter("position",$ix);
-                    $ret_sql=$this->db->exec_sql(
-                                 "insert into form 
(fo_fr_id,fo_pos,fo_label,fo_formula)".
-                                 " values($1,$2,$3,$4)",
-                                 array($this->id,
-                                       $row->fo_pos,
-                                       $row->fo_label,
-                                       $row->fo_formula)
-                             );
-                }
-            }
-
-        }
-        catch (Exception $e)
-        {
-              record_log($e);
-            $this->db->rollback();
-            echo $e->getMessage();
-        }
-        $this->db->commit();
-
-    }
-    function update()
-    {
-        try
-        {
-            $this->db->start();
-            $ret_sql=$this->db->exec_sql(
-                         "update formdef set fr_label=$1 where fr_id=$2",
-                         array($this->name,$this->id));
-            $ret_sql=$this->db->exec_sql(
-                         "delete from form where fo_fr_id=$1",
-                         array($this->id));
-            $ix=0;
-
-            foreach ( $this->aAcc_Report_row as $row)
-            {
-                if ( strlen(trim($row->get_parameter("name"))) != 0 &&
-                        strlen(trim($row->get_parameter("formula"))) != 0 )
-                {
-                    
$ix=($row->get_parameter("position")!="")?$row->get_parameter("position"):$ix;
-                    $row->set_parameter("position",$ix);
-                    $ret_sql=$this->db->exec_sql(
-                                 "insert into form 
(fo_fr_id,fo_pos,fo_label,fo_formula)".
-                                 " values($1,$2,$3,$4)",
-                                 array($this->id,
-                                       $row->fo_pos,
-                                       $row->fo_label,
-                                       $row->fo_formula)
-                             );
-                }
-            }
-
-
-        }
-        catch (Exception $e)
-        {
-              record_log($e);
-            $this->db->rollback();
-            echo $e->getMessage();
-        }
-        $this->db->commit();
-    }
-    /*!\brief fill a form thanks an array, usually it is $_POST
-     *\param $p_array keys = fr_id, form_nom,textXX, formXX, posXX where
-        XX is an number
-     */
-    function from_array($p_array)
-    {
-        $this->id=(isset($p_array['fr_id']))?$p_array['fr_id']:0;
-        $this->name=(isset($p_array['form_nom']))?$p_array['form_nom']:"";
-        $ix=0;
-
-        $rr=new Acc_Report_Row();
-        $rr->set_parameter("form_id",$this->id);
-        $rr->set_parameter('database',$this->db);
-
-        $this->aAcc_Report_row=$rr->from_array($p_array);
-
-
+        $this->form_definition->save();
     }
+  
     /*!\brief the fr_id MUST be set before calling
      */
-
-
     function load()
     {
-        $sql=$this->db->exec_sql(
-                 "select fr_label from formdef where fr_id=$1",
-                 array($this->id));
-        if ( Database::num_row($sql) == 0 ) return;
-        $this->name=Database::fetch_result($sql,0,0);
-        $sql=$this->db->exec_sql(
-                 "select fo_id,fo_pos,fo_label,fo_formula ".
-                 " from form ".
-                 " where fo_fr_id=$1 order by fo_pos",
-                 array($this->id));
-        $f=Database::fetch_all($sql);
-        $array=array();
-        if ( ! empty($f) )
-        {
-            foreach ($f as $r)
-            {
-                $obj=new Acc_Report_Row();
-                $obj->set_parameter("name",$r['fo_label']);
-                $obj->set_parameter("id",$r['fo_id']);
-                $obj->set_parameter("position",$r['fo_pos']);
-                $obj->set_parameter("formula",$r['fo_formula']);
-                $obj->set_parameter('database',$this->db);
-                $obj->set_parameter('form_id',$this->id);
-                $array[]=clone $obj;
-            }
-        }
-        $this->aAcc_Report_row=$array;
+       $this->form_definition->load();
 
     }
     function delete()
     {
-        $ret=$this->db->exec_sql(
-                 "delete from formdef where fr_id=$1",
-                 array($this->id)
-             );
+       $this->form_definition->delete();
     }
-    /*!\brief get a list from formdef of all defined form
+    /*!\brief get a list from form_definition of all defined form
      *
      *\return array of object rapport
      *
      */
     function get_list()
     {
-        $sql="select fr_id,fr_label from formdef order by fr_label";
-        $ret=$this->db->exec_sql($sql);
+        $sql="select fr_id,fr_label from form_definition order by fr_label";
+        $ret=$this->form_definition->cn->exec_sql($sql);
         if ( Database::num_row($ret) == 0 ) return array();
         $array=Database::fetch_all($ret);
         $obj=array();
         foreach ($array as $row)
         {
-            $tmp=new Acc_Report($this->db);
+            $tmp=new Acc_Report($this->form_definition->cn);
             $tmp->id=$row['fr_id'];
             $tmp->name=$row['fr_label'];
             $obj[]=clone $tmp;
@@ -351,7 +145,7 @@ class Acc_Report
      */
     function make_array()
     {
-        $sql=$this->db->make_array("select fr_id,fr_label from formdef order 
by fr_label");
+        $sql=$this->form_definition->cn->make_array("select fr_id,fr_label 
from form_definition order by fr_label");
         return $sql;
     }
 
@@ -362,14 +156,20 @@ class Acc_Report
     function export_csv($p_file)
     {
         $this->load();
-
-        fputcsv($p_file,array($this->name));
-
-        foreach ($this->aAcc_Report_row as $row)
+        
+        fputcsv($p_file,array($this->form_definition->getp("fr_label")));
+        $array=$this->form_definition->get_cn()->get_array("select 
fo_label,fo_pos,fo_formula 
+                        from form_detail
+                        where fo_fr_id=$1
+                        order by fo_pos"
+                ,array($this->form_definition->getp("fr_id"))
+                );
+        
+        foreach ($array as $row)
         {
-            fputcsv($p_file,array($row->get_parameter("name"),
-                                  $row->get_parameter('position'),
-                                  $row->get_parameter('formula'))
+            fputcsv($p_file,array($row["fo_label"],
+                                  $row["fo_pos"],
+                                  $row["fo_formula"])
                    );
         }
 
@@ -392,21 +192,18 @@ class Acc_Report
             $file=fopen($file_report,'r');
             $data=fgetcsv($file);
             if ( empty($data) ) return;
-            $this->name=$data[0];
             $array=array();
+            $cn=$this->form_definition->cn;
+            $id=$this->form_definition->getp("fr_id");
             while($data=fgetcsv($file))
             {
-                $obj=new Acc_Report_Row();
-                $obj->set_parameter("name",$data[0]);
-                $obj->set_parameter("id",0);
-                $obj->set_parameter("position",$data[1]);
-                $obj->set_parameter("formula",$data[2]);
-                $obj->set_parameter('database',$this->db);
-                $obj->set_parameter('form_id',0);
-                $array[]=clone $obj;
+                $obj=new Form_Detail_SQL($cn);
+                $obj->setp("fo_label",$data[0]);
+                $obj->setp("fo_pos",$data[1]);
+                $obj->set("fo_formula",$data[2]);
+                $obj->setp("fo_fr_id",$id);
+                $obj->insert();
             }
-            $this->aAcc_Report_row=$array;
-            $this->insert();
         }
     }
     /**
@@ -416,42 +213,35 @@ class Acc_Report
      */
     function exist($p_id=0)
     {
-        $c=$this->id;
+        $c=$this->form_definition->getp("fr_id");
         if ( $p_id != 0 ) $c=$p_id;
-        $ret=$this->db->exec_sql("select fr_label from formdef where 
fr_id=$1",array($c));
+        $ret=$this->form_definition->cn->exec_sql("select fr_label from 
form_definition where fr_id=$1",array($c));
         if (Database::num_row($ret) == 0) return false;
         return true;
     }
-    static function test_me()
+    /**
+     * @brief display a form for creating a new report by importing it or set 
manually
+     */
+    function create()
     {
-        $cn=Dossier::connect();
-        $a=new Acc_Report($cn);
-        print_r($a->get_list());
-        $array=array("text0"=>"test1",
-                     "form0"=>"7%",
-                     "text1"=>"test2",
-                     "form1"=>"6%",
-                     "fr_id"=>110,
-                     "form_nom"=>"Tableau"
-                    );
-        $a->from_array($array);
-        print_r($a);
-        echo '<form method="post">';
-        echo $a->form(10);
-
-        echo HtmlInput::submit('update','Enregistre');
-        /* Add a line should be a javascript see comptanalytic */
-        //  $r.= '<INPUT TYPE="submit" value="Ajoute une ligne" 
name="add_line">';
-        echo HtmlInput::submit('del_form','Efface ce rapport');
-        echo HtmlInput::hidden('test_select',$_REQUEST['test_select']);
-        echo "</FORM>";
-        if ( isset ($_POST['update']))
-        {
-            $b=new Acc_Report($cn);
-            $b->from_array($_POST);
-            echo '<hr>';
-            print_r($b);
-        }
+        require_once NOALYSS_INCLUDE."/template/acc_report-create.php";
+    }
+    /**
+     * @brief 
+     * @param IText $name
+     */
+    function input_name($name)
+    {
+        $name=new IText("fr_name",$name);
+        $name->id="fr_name_inplace";
+        
+        $iName=new Inplace_Edit($name);
+        $iName->set_callback("ajax_misc.php");
+        $iName->add_json_param("op", "report_definition");
+        $iName->add_json_param("sa", "change_name");
+        $iName->add_json_param("gDossier", Dossier::id());
+        $iName->add_json_param("p_id", $this->form_definition->getp("fr_id"));
+        return $iName;
     }
 }
 
diff --git a/include/class/acc_report_mtable.class.php 
b/include/class/acc_report_mtable.class.php
new file mode 100644
index 0000000..29ab91a
--- /dev/null
+++ b/include/class/acc_report_mtable.class.php
@@ -0,0 +1,129 @@
+<?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-2021) Author Dany De Bontridder <danydb@noalyss.eu>
+
+require_once NOALYSS_INCLUDE."/lib/manage_table_sql.class.php";
+require_once NOALYSS_INCLUDE.'/database/form_detail_sql.class.php';
+require_once NOALYSS_INCLUDE."/lib/impress.class.php";
+/**
+ * @file
+ * @brief  manage simple report 
+ */
+class Acc_Report_MTable extends Manage_Table_SQL
+{
+
+    private $form_definition_id;
+
+    function __construct(\Data_SQL $p_table)
+    {
+        parent::__construct($p_table);
+    }
+
+    static function build($p_id, $p_form_def_id)
+    {
+        $cn=Dossier::connect();
+        $form_detail=new Form_Detail_SQL($cn, $p_id);
+        if ( $p_id == -1) {
+            $max=$cn->get_value("select coalesce(max(fo_pos),0) +10 from 
form_detail where fo_fr_id=$1",
+                     [$p_form_def_id]);
+            $form_detail->setp("fo_pos",$max);
+        }
+        $acc_report_mtable=new Acc_Report_MTable($form_detail);
+        $acc_report_mtable->set_order(['fo_pos', 'fo_label', 'fo_formula']);
+
+        $acc_report_mtable->set_col_label("fo_pos", _("Position"));
+        $acc_report_mtable->set_col_label("fo_label", _("Libellé"));
+        $acc_report_mtable->set_col_label("fo_formula", _("Formula"));
+        $acc_report_mtable->set_form_definition_id($p_form_def_id);
+
+        $acc_report_mtable->set_sort_column("fo_pos");
+
+        $acc_report_mtable->set_col_type("fo_pos", "numeric");
+        $acc_report_mtable->set_col_type("fo_formula", "custom");
+        $acc_report_mtable->set_col_tips("fo_formula", 79);
+
+        $acc_report_mtable->add_json_param("form_def", $p_form_def_id);
+        $acc_report_mtable->add_json_param("op", "report_definition");
+        $acc_report_mtable->set_callback("ajax_misc.php");
+
+        return $acc_report_mtable;
+    }
+
+    public function get_form_definition_id()
+    {
+        return $this->form_definition_id;
+    }
+
+    public function set_form_definition_id($form_definition_id): void
+    {
+        $this->form_definition_id=$form_definition_id;
+    }
+
+    function input_custom($p_key, $p_value)
+    {
+        if ($p_key=='fo_formula')
+        {
+            $formula=new ITextarea('fo_formula');
+            $formula->id='fo_formula';
+            $formula->value=$p_value;
+            echo $formula->input();
+            
+            echo HtmlInput::button_action(_("Cherche poste, fiche , 
analytique"), 
+                                
sprintf('search_account_card({gDossier:%s,target:\'%s\'})',Dossier::id(),
+                                        "fo_formula")
+                    );
+            echo HtmlInput::hidden("form_def",$this->form_definition_id);
+        }
+    }
+
+    function display_row_custom($p_key, $p_value, $p_id=0)
+    {
+        if ($p_key=='fo_formula')
+        {
+
+            return td($p_value);
+        }
+    }
+
+    function display_table($p_order="", $p_array=NULL)
+    {
+
+        return parent::display_table(" where fo_fr_id = $1 order by fo_pos", 
[$this->get_form_definition_id()]);
+    }
+    function check()
+    {
+        $obj=$this->get_table();
+        $obj->setp("fo_fr_id",$this->form_definition_id);
+        $n=0;
+        if ( ! Impress::check_formula($obj->getp("fo_formula"))) {
+            $this->set_error("fo_formula", _("Formule invalide"));
+            $n++;
+            
+        }
+        if ( trim($obj->getp("fo_label")) == "") {
+            $n++;
+            $this->set_error("fo_label",_("Nom est vide"));
+        }
+               
+        if ($n == 0 ) { return true; }
+        return false;
+    }
+
+}
diff --git a/include/class/acc_report_row.class.php 
b/include/class/acc_report_row.class.php
deleted file mode 100644
index d74dea1..0000000
--- a/include/class/acc_report_row.class.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-/*
- *   This file is part of NOALYSS.
- *
- *   NOALYSS 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.
- *
- *   NOALYSS 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 NOALYSS; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// Copyright Author Dany De Bontridder danydb@aevalys.eu
-
-/*!\file
- * \brief this class  maps the table form, which is a child table for formdef
- */
-
-/*!\brief  manipulate the form_def's child table (form) */
-class  Acc_Report_Row
-{
-    private static $variable=array(
-                                 "name"=>"fo_label",
-                                 "formula"=>"fo_formula",
-                                 "id"=>"fo_id",
-                                 "position"=>"fo_pos",
-                                 "form_id"=>"fo_fr_id",
-                                 "database"=>"db"
-                             );
-    function __construct ($p_name=null,$p_formula=null)
-    {
-        $this->set_parameter("id",0);
-
-        $this->set_parameter("name",$p_name);
-        $this->set_parameter("formula",$p_formula);
-    }
-    public function get_parameter($p_string)
-    {
-        if ( array_key_exists($p_string,self::$variable) )
-        {
-            $idx=self::$variable[$p_string];
-            return $this->$idx;
-        }
-        else
-            throw new Exception("Attribut inexistant $p_string");
-    }
-    public function set_parameter($p_string,$p_value)
-    {
-        if ( array_key_exists($p_string,self::$variable) )
-        {
-            $idx=self::$variable[$p_string];
-            $this->$idx=$p_value;
-        }
-        else
-            throw new Exception("Attribut inexistant $p_string");
-
-
-    }
-    public function get_info()
-    {
-        return var_export(self::$variable,true);
-    }
-    /*!\brief Convert an array into an array of row_rapport object
-     *        the fo_id is 0, position = 0, the fo_frd_id (form_id) is
-     *  the one of the current object, the db is also the current one
-     *\param $p_array contains the value
-     *\return an array of Acc_Report_Row object
-     */
-    public function from_array($p_array)
-    {
-        extract ($p_array, EXTR_SKIP);
-        $ret=array();
-        $ix=0;
-        $found=0;
-        foreach ( $p_array as $r)
-        {
-
-            if ( isset(${'form'.$ix}) && isset ( ${'text'.$ix} ))
-            {
-                $obj=new Acc_Report_Row( ${'text'.$ix},${'form'.$ix});
-
-                if ( isset(${'pos'.$ix}) &&  isNumber(${'pos'.$ix})==1 )
-                    $obj->set_parameter("position",${'pos'.$ix});
-                else
-                {
-                    $obj->set_parameter("position",$found);
-                    $found++;
-                }
-
-                $obj->fo_id=0;
-                $obj->fo_fr_id=$this->fo_fr_id;
-                $obj->db=$this->db;
-
-                $ret[]=clone $obj;
-            }
-            $ix++;
-
-        }
-        return $ret;
-    }
-    static function test_me()
-    {
-        $cn=Dossier::connect();
-        $a=new Acc_Report_Row();
-        $array=array("text0"=>"test1",
-                     "form0"=>"7%",
-                     "text1"=>"test2",
-                     "form1"=>"6%"
-                    );
-        $a->db=$cn;
-        $b=$a->from_array($array);
-        print_r($b);
-        echo $a->get_info();
-    }
-}
diff --git a/include/class/anc_account.class.php 
b/include/class/anc_account.class.php
new file mode 100644
index 0000000..9975b61
--- /dev/null
+++ b/include/class/anc_account.class.php
@@ -0,0 +1,99 @@
+<?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-2021) Author Dany De Bontridder <danydb@noalyss.eu>
+
+/**
+ * @file
+ * @brief Analytic account
+ */
+class Anc_Account
+{
+
+    private $poste_analytique_sql;
+
+    public function __construct($p_cn, $p_id=-1)
+    {
+        $this->poste_analytique_sql=new Poste_analytique_SQL($p_cn, $p_id);
+    }
+
+    public function get_poste_analytique_sql()
+    {
+        return $this->poste_analytique_sql;
+    }
+
+    public function set_poste_analytique_sql($poste_analytique_sql): void
+    {
+        $this->poste_analytique_sql=$poste_analytique_sql;
+    }
+    /**
+     * @brief Get the balance of an Analytic account 
+     * @param string $p_cond_sql SQL condition to filter , usually the period
+     * @see Impress::compute_amount
+     * @return array key = credit , debit , solde
+     */
+    public function get_balance($p_cond_sql)
+    {
+        if ( DEBUGNOALYSS > 1) 
+          {
+              tracedebug("impress.debug.log", "$p_cond_sql", 
'Anc_Account->get_balance \$p_cond_sql');
+          }
+        $cn=$this->poste_analytique_sql->cn;
+        $detail=$cn->get_row("
+              select  ( select coalesce (sum(oa1.oa_amount),0) 
+              from operation_analytique oa1  
+              where oa1.po_id=$1 
+                and oa1.oa_debit='t' 
+                $p_cond_sql 
+                    )  as debit,
+                ( select coalesce (sum(oa2.oa_amount),0)  
+                from operation_analytique oa2  
+                    where oa2.po_id=$1 
+                    and oa2.oa_debit='f'
+                    $p_cond_sql 
+                 ) as credit
+                 ",[$this->poste_analytique_sql->getp("po_id")]);
+         if ( DEBUGNOALYSS > 1) 
+          {
+              tracedebug("impress.debug.log", $cn->sql, 
'Anc_Account->get_balance SQL executed');
+          }
+        $tdetail['credit']=$detail['credit'];
+        $tdetail['debit']=$detail['debit'];
+        $tdetail['solde']=abs(bcsub($detail['debit'],$detail['credit']));
+        return $tdetail;
+        
+        
+    }
+    /**
+     * @brief retrieve the Analytic account thanks its code
+     * @param type $p_code
+     * @return type
+     */
+    public function load_by_code($p_code)
+    {
+        $cn=$this->poste_analytique_sql->cn;
+        $p_id= $cn->get_value("select po_id from poste_analytique where 
po_name=$1",
+                [ trim(strtoupper($p_code))]);
+        $p_id=(empty($p_id))?-1:$p_id;
+        $this->poste_analytique_sql->setp('po_id',$p_id);
+        $this->poste_analytique_sql->load();
+        return $this->poste_analytique_sql;
+    }
+
+}
diff --git a/include/class/anticipation.class.php 
b/include/class/anticipation.class.php
index a8abf88..694543b 100644
--- a/include/class/anticipation.class.php
+++ b/include/class/anticipation.class.php
@@ -211,22 +211,22 @@ EOF;
         $aItem = array();
         $aReal = array();
         $poste = new Acc_Account_Ledger($this->cn, 0);
-        $fiche = new Fiche($this->cn);
+
         $aPeriode = $this->cn->get_array("select 
p_id,to_char(p_start,'MM.YYYY') as myear from parm_periode
-                                        where p_start >= (select p_start from 
parm_periode where p_id=$start)
-                                         and p_end <= (select p_end from 
parm_periode where p_id=$end)
-                                        order by p_start;");
+                                        where p_start >= (select p_start from 
parm_periode where p_id=$1)
+                                         and p_end <= (select p_end from 
parm_periode where p_id=$2)
+                                        order by p_start",[$start,$end]);
         $error = array();
         for ($j = 0; $j < count($aCat); $j++) {
             
-            // Item of the category, estimation for a specific month
-            $aItem[$j] = $this->cn->get_array('select 
fi_card,fi_account,fi_text,fi_amount,fi_debit ,
+            // Item of the category,montly estimation
+            $aItem[$j] = $this->cn->get_array('select 
fi_account,fi_text,fi_amount,
                 fi_amount_initial
                    from forecast_item where fc_id=$1  and fi_pid=0 order by 
fi_order ', 
                     array($aCat[$j]['fc_id']));
             
-            // Item of the category, montly estimation
-            $aPerMonth[$j] = $this->cn->get_array('select 
fi_pid,fi_card,fi_account,fi_text,fi_amount,fi_debit 
+            // Item of the category,  estimation for a specific month
+            $aPerMonth[$j] = $this->cn->get_array('select 
fi_pid,fi_account,fi_text,fi_amount
                     from forecast_item where fc_id=$1 and fi_pid !=0 order by 
fi_order ', 
                     array($aCat[$j]['fc_id']));
 
@@ -234,20 +234,8 @@ EOF;
             for ($k = 0; $k < count($aItem[$j]); $k++) {
                 /* for each periode */
                 for ($l = 0; $l < count($aPeriode); $l++) {
-                    if ($aItem[$j][$k]['fi_account'] == '') {
-                        $fiche->id = $aItem[$j][$k]['fi_card'];
-                        $amount = $fiche->get_solde_detail("j_tech_per = " . 
$aPeriode[$l]['p_id']);
-                        
-                        if ($aItem[$j][$k]['fi_debit'] == 'C' && 
$amount['debit'] > $amount['credit']) 
-                        {
-                            $amount['solde'] = $amount["solde"] * (-1);
-                        }
-                        if ($aItem[$j][$k]['fi_debit'] == 'D' && 
$amount['debit'] < $amount['credit']) 
-                        {
-                            $amount['solde'] = $amount["solde"] * (-1);
-                        }
-
-                    } else {
+                    if ($aItem[$j][$k]['fi_account'] != '') {
+                       
                         $poste->id = $aItem[$j][$k]['fi_account'];
                         $aresult = Impress::parse_formula($this->cn, "OK", 
$poste->id, $aPeriode[$l]['p_id'], $aPeriode[$l]['p_id']);
                         $tmp_label = $aresult['desc'];
@@ -299,9 +287,9 @@ EOF;
         $old = $this->cn->get_array("select fc_id from forecast_category where 
f_id=$1", array($this->forecast_id));
         /* save into forecast_item */
         for ($i = 0; $i < count($array); $i++) {
-            $this->cn->exec_sql("insert into forecast_item 
(fi_text,fi_account,fi_card,fi_order,fc_id,
-                           fi_amount,fi_debit,fi_pid) " .
-                " select 
fi_text,fi_account,fi_card,fi_order,$1,fi_amount,fi_debit,fi_pid " .
+            $this->cn->exec_sql("insert into forecast_item 
(fi_text,fi_account,fi_order,fc_id,
+                           fi_amount,fi_pid) " .
+                " select fi_text,fi_account,fi_order,$1,fi_amount,fi_pid " .
                 " from forecast_item where fc_id=$2", 
array($array[$i]['fc_id'], $old[$i]['fc_id']));
         }
         $this->cn->commit();
diff --git a/include/class/document.class.php b/include/class/document.class.php
index b5f2d6e..dfddcc6 100644
--- a/include/class/document.class.php
+++ b/include/class/document.class.php
@@ -25,25 +25,25 @@ require_once NOALYSS_INCLUDE.'/class/acc_tva.class.php';
 require_once NOALYSS_INCLUDE.'/class/user.class.php';
 require_once NOALYSS_INCLUDE.'/lib/zip_extended.class.php';
 
-/* ! \file
+/*! \file
  * \brief Class Document corresponds to the table document
  */
-/* ! \brief Class Document corresponds to the table document
+/*! \brief Class Document corresponds to the table document
  */
 
 class Document
 {
 
-    var $db;          /* !< $db Database connexion */
-    var $d_id;        /* !< $d_id Document id */
-    var $ag_id;       /* !< $ag_id action_gestion.ag_id (pk) */
-    var $d_mimetype;  /* !< $d_mimetype  */
-    var $d_filename;  /* !< $d_filename */
-    var $d_lob;       /* !< $d_lob the oid of the lob */
-    var $d_description;       /* !< Description of the file */
-    var $d_number;    /* !< $d_number number of the document */
-    var $md_id;       /* !< $md_id document's template */
-    private $counter; /* !< counter for the items ( goods ) */
+    var $db;          /*!< $db Database connexion */
+    var $d_id;        /*!< $d_id Document id */
+    var $ag_id;       /*!< $ag_id action_gestion.ag_id (pk) */
+    var $d_mimetype;  /*!< $d_mimetype  */
+    var $d_filename;  /*!< $d_filename */
+    var $d_lob;       /*!< $d_lob the oid of the lob */
+    var $d_description;       /*!< Description of the file */
+    var $d_number;    /*!< $d_number number of the document */
+    var $md_id;       /*!< $md_id document's template */
+    private $counter; /*!< counter for the items ( goods ) */
 
     /* Constructor
      * \param $p_cn Database connection
@@ -98,7 +98,7 @@ class Document
         return $new_filename;
     }
 
-    /* !
+    /*!
      * \brief Generate the document, Call $this-\>replace to replace
      *        tag by value
      * @param p_array contains the data normally it is the $_POST
@@ -208,7 +208,7 @@ class Document
         }
     }
 
-    /* ! parseDocument
+    /*! parseDocument
      * \brief This function parse a document and replace all
      *        the predefined tags by a value. This functions
      *        generate diffent documents (invoice, order, letter)
@@ -223,7 +223,7 @@ class Document
     function parseDocument($p_dir, $p_file, $p_type, $p_array)
     {
 
-        /* !\note replace in the doc the tags by their values.
+        /*!\note replace in the doc the tags by their values.
          *  - MY_*   table parameter
          *  - ART_VEN* table quant_sold for invoice
          *  - CUST_* table quant_sold and fiche for invoice
@@ -323,7 +323,7 @@ class Document
         }
     }
 
-    /* ! saveGenerated
+    /*! saveGenerated
      * \brief Save the generated Document
      * \param $p_file is the generated file
      *
@@ -506,7 +506,7 @@ class Document
         $cn->exec_sql($sql, array($p_ag_id, $p_lob, $p_filename, $p_mimetype, 
1, $p_description));
     }
 
-    /* ! 
+    /*! 
      * \brief create and compute a string for reference the doc <A ...>
      *
      * \return a string
@@ -565,7 +565,7 @@ class Document
         $this->db->commit();
     }
 
-    /* !\brief get all the document of a given action
+    /*!\brief get all the document of a given action
      * \param $ag_id the ag_id from action::ag_id (primary key)
      * \return an array of objects document or an empty array if nothing found
      */
@@ -591,7 +591,7 @@ class Document
     }
     
 
-    /* !\brief Get  complete all the data member thx info from the database
+    /*!\brief Get  complete all the data member thx info from the database
      */
 
     function get()
@@ -611,7 +611,7 @@ class Document
         $this->d_description=$row['d_description'];
     }
 
-    /* !
+    /*!
      * \brief replace the TAG by the real value, this value can be into
      * the database or in $_POST
      * The possible tags are
@@ -1686,7 +1686,7 @@ class Document
         return $r;
     }
 
-    /* !\brief remove a row from the table document, the lob object is not 
deleted
+    /*!\brief remove a row from the table document, the lob object is not 
deleted
      *        because can be linked elsewhere
      */
 
@@ -1699,7 +1699,7 @@ class Document
             $this->db->lo_unlink($d_lob);
     }
 
-    /* !\brief Move a document from the table document into the concerned row
+    /*!\brief Move a document from the table document into the concerned row
      *        the document is not copied : it is only a link
      *
      * \param $p_internal internal code
diff --git a/include/class/forecast.class.php b/include/class/forecast.class.php
index 3383d84..166dac1 100644
--- a/include/class/forecast.class.php
+++ b/include/class/forecast.class.php
@@ -153,8 +153,8 @@ class Forecast
       /* save into forecast_item */
       for ($i=0;$i<count($array);$i++)
        {
-         $this->cn->exec_sql("insert into forecast_item 
(fi_text,fi_account,fi_card,fi_order,fc_id,fi_amount,fi_debit,fi_pid) ".
-                             " select 
fi_text,fi_account,fi_card,fi_order,$1,fi_amount,fi_debit,fi_pid ".
+         $this->cn->exec_sql("insert into forecast_item 
(fi_text,fi_account,fi_order,fc_id,fi_amount,fi_pid) ".
+                             " select 
fi_text,fi_account,fi_order,$1,fi_amount,fi_pid ".
                              " from forecast_item where 
fc_id=$2",array($array[$i]['fc_id'],$old[$i]['fc_id']));
        }
     }
diff --git a/include/class/forecast_item_mtable.class.php 
b/include/class/forecast_item_mtable.class.php
index aaa3fbd..170cad6 100644
--- a/include/class/forecast_item_mtable.class.php
+++ b/include/class/forecast_item_mtable.class.php
@@ -33,6 +33,7 @@
 require_once NOALYSS_INCLUDE . "/lib/manage_table_sql.class.php";
 require_once NOALYSS_INCLUDE . "/database/forecast_item_sql.class.php";
 require_once NOALYSS_INCLUDE . "/database/forecast_sql.class.php";
+require_once NOALYSS_INCLUDE . "/lib/impress.class.php";
 
 class Forecast_Item_MTable extends Manage_Table_SQL
 {
@@ -96,10 +97,8 @@ class Forecast_Item_MTable extends Manage_Table_SQL
     {
         
         $sql = "select fi_id,fi_text,fi_account,
-                case when fi_card is null then fi_account 
-                    else  (select ad_value from fiche_detail where ad_id=23 
and f_id=fi_card) end str_account_card,
+                fi_account str_account_card,
                 fc_desc,
-                fi_card,
                 fi.fi_amount ,
                 (select p_start from parm_periode pp where pp.p_id=fi.fi_pid) 
as str_periode
                 from forecast_item fi join forecast_category fc on 
(fi.fc_id=fc.fc_id)
@@ -114,10 +113,8 @@ class Forecast_Item_MTable extends Manage_Table_SQL
         if ( ! isset($p_row['fc_desc'])) {
             $cn=$this->get_table()->cn;
          $sql=   "select fi_id,fi_text,fi_account,
-                case when fi_card is null then fi_account 
-                    else  (select ad_value from fiche_detail where ad_id=23 
and f_id=fi_card) end str_account_card,
+                fi_account                 str_account_card,
                 fc_desc,
-                fi_card,
                 fi.fi_amount ,
                 (select p_start from parm_periode pp where pp.p_id=fi.fi_pid) 
as str_periode
                 from forecast_item fi join forecast_category fc on 
(fi.fc_id=fc.fc_id)
@@ -177,7 +174,6 @@ class Forecast_Item_MTable extends Manage_Table_SQL
     ctl: tbl6058da883ded6
     fc_id: 88
     fi_text: Gérant
-    fi_card:
     fi_account: [4160%]-[4890%]
     fi_amount: 3000.0000
     fi_pid: 0
@@ -192,17 +188,27 @@ class Forecast_Item_MTable extends Manage_Table_SQL
         $object_sql->setp("fi_account",$http->post('fi_account'));
         $object_sql->setp("fi_amount",$http->post('fi_amount',"number"));
         $object_sql->setp("fi_pid",$http->post('fi_pid',"number"));
-        $object_sql->setp("fi_debit",$http->post('fi_debit'));
         
$object_sql->setp("fi_amount_initial",$http->post("fi_amount_initial","number"));
         
-        $card=trim($http->post("fi_card"));
-        if ( $card !="") {
-            $f_id=$object_sql->cn->get_value("select f_id from fiche_detail 
where ad_value=upper($1) and ad_id=23",[$card]);
-            if ( $f_id !="") {
-                $object_sql->setp("fi_card",$f_id);
-            }
-        }
+        
 
     }
-
+    function check()
+    {
+        $object=$this->get_table();
+        if ( trim($object->getp("fi_text") ) == "") {
+            $this->set_error("fi_text", _("Intitulé est vide"));
+        }
+        if ( trim ($object->getp("fi_account"))=="") {
+            $this->set_error("fi_account", _("Formule est vide"));
+        }
+        if ( trim ($object->getp("fi_account"))=="") {
+            $this->set_error("fi_account", _("Formule est vide"));
+        }
+         if ( ! Impress::check_formula($object->getp("fi_account"))) {
+            $this->set_error("fi_account", _("Formule invalide"));
+        }
+        if ( $this->count_error()==0) return true;
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/include/class/user.class.php b/include/class/user.class.php
index edc607d..fcf4799 100644
--- a/include/class/user.class.php
+++ b/include/class/user.class.php
@@ -668,7 +668,7 @@ class User
        /**
          * 
          * \brief return the mini rapport to display on the welcome page
-        * \return 0 if nothing if found or the report to display 
(formdef.fr_id)
+        * \return 0 if nothing if found or the report to display 
(form_definition.fr_id)
         */
 
        function get_mini_report()
diff --git a/include/constant.php b/include/constant.php
index ef088ff..3699045 100644
--- a/include/constant.php
+++ b/include/constant.php
@@ -116,7 +116,7 @@ if ( !defined ("NOALYSS_PACKAGE_REPOSITORY")) {
 if ( ! defined ("SYSINFO_DISPLAY")) {
     define ("SYSINFO_DISPLAY",TRUE);
 }
-define ("DBVERSION",160);
+define ("DBVERSION",161);
 define ("MONO_DATABASE",25);
 define ("DBVERSIONREPO",19);
 define ('NOTFOUND','--not found--');
diff --git a/include/database/forecast_item_sql.class.php 
b/include/database/forecast_item_sql.class.php
index 4af85ae..ec8f938 100644
--- a/include/database/forecast_item_sql.class.php
+++ b/include/database/forecast_item_sql.class.php
@@ -41,11 +41,9 @@ class Forecast_Item_SQL extends Table_Data_SQL
             "fi_id"=>"fi_id"
             , "fi_text"=>"fi_text"
             , "fi_account"=>"fi_account"
-            , "fi_card"=>"fi_card"
             , "fi_order"=>"fi_order"
             , "fc_id"=>"fc_id"
             , "fi_amount"=>"fi_amount"
-            , "fi_debit"=>"fi_debit"
             , "fi_pid"=>"fi_pid"
             , "fi_amount_initial"=>"fi_amount_initial"
         );
@@ -56,11 +54,9 @@ class Forecast_Item_SQL extends Table_Data_SQL
             "fi_id"=>"numeric"
             , "fi_text"=>"text"
             , "fi_account"=>"text"
-            , "fi_card"=>"numeric"
             , "fi_order"=>"numeric"
             , "fc_id"=>"numeric"
             , "fi_amount"=>"numeric"
-            , "fi_debit"=>"char"
             , "fi_pid"=>"numeric"
             , "fi_amount_initial"=>"numeric"
         );
diff --git a/include/database/forecast_item_sql.class.php 
b/include/database/form_definition_sql.class.php
similarity index 53%
copy from include/database/forecast_item_sql.class.php
copy to include/database/form_definition_sql.class.php
index 4af85ae..f2c0446 100644
--- a/include/database/forecast_item_sql.class.php
+++ b/include/database/form_definition_sql.class.php
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * Autogenerated file
+ * Autogenerated file 
  *   This file is part of NOALYSS.
  *
  *   NOALYSS is free software; you can redistribute it and/or modify
@@ -18,56 +18,39 @@
  *   along with NOALYSS; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-require_once NOALYSS_INCLUDE.'/lib/table_data_sql.class.php';
+require_once NOALYSS_INCLUDE.'/lib/data_sql.class.php';
 require_once NOALYSS_INCLUDE.'/class/database.class.php';
 
 /**
- * class_forecast_item_sql.php
+ * class_form_detail_sql.php
  *
  * @file
- * @brief abstract of the table public.forecast_item
- */
-class Forecast_Item_SQL extends Table_Data_SQL
+ * @brief abstract of the table public.form_definition */
+
+class Form_Definition_SQL extends \Table_Data_SQL
 {
 
     function __construct(DatabaseCore $p_cn, $p_id=-1)
     {
-        $this->table="public.forecast_item";
-        $this->primary_key="fi_id";
+        $this->table="public.form_definition";
+        $this->primary_key="fr_id";
         /*
          * List of columns
          */
         $this->name=array(
-            "fi_id"=>"fi_id"
-            , "fi_text"=>"fi_text"
-            , "fi_account"=>"fi_account"
-            , "fi_card"=>"fi_card"
-            , "fi_order"=>"fi_order"
-            , "fc_id"=>"fc_id"
-            , "fi_amount"=>"fi_amount"
-            , "fi_debit"=>"fi_debit"
-            , "fi_pid"=>"fi_pid"
-            , "fi_amount_initial"=>"fi_amount_initial"
+            "fr_id"=>"fr_id"
+            , "fr_label"=>"fr_label"
         );
         /*
          * Type of columns
          */
         $this->type=array(
-            "fi_id"=>"numeric"
-            , "fi_text"=>"text"
-            , "fi_account"=>"text"
-            , "fi_card"=>"numeric"
-            , "fi_order"=>"numeric"
-            , "fc_id"=>"numeric"
-            , "fi_amount"=>"numeric"
-            , "fi_debit"=>"char"
-            , "fi_pid"=>"numeric"
-            , "fi_amount_initial"=>"numeric"
+            "fr_id"=>"numeric"
+            , "fr_label"=>"text"
         );
 
-
         $this->default=array(
-            "fi_id"=>"auto"
+            "fr_id"=>"auto"
         );
 
         $this->date_format="DD.MM.YYYY";
diff --git a/include/database/forecast_item_sql.class.php 
b/include/database/form_detail_sql.class.php
similarity index 53%
copy from include/database/forecast_item_sql.class.php
copy to include/database/form_detail_sql.class.php
index 4af85ae..3040147 100644
--- a/include/database/forecast_item_sql.class.php
+++ b/include/database/form_detail_sql.class.php
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * Autogenerated file
+ * Autogenerated file 
  *   This file is part of NOALYSS.
  *
  *   NOALYSS is free software; you can redistribute it and/or modify
@@ -18,56 +18,44 @@
  *   along with NOALYSS; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-require_once NOALYSS_INCLUDE.'/lib/table_data_sql.class.php';
+require_once NOALYSS_INCLUDE.'/lib/data_sql.class.php';
 require_once NOALYSS_INCLUDE.'/class/database.class.php';
 
 /**
- * class_forecast_item_sql.php
+ * class_form_detail_sql.php
  *
  * @file
- * @brief abstract of the table public.forecast_item
- */
-class Forecast_Item_SQL extends Table_Data_SQL
+ * @brief abstract of the table public.form_detail */
+class Form_Detail_SQL extends \Table_Data_SQL
 {
 
     function __construct(DatabaseCore $p_cn, $p_id=-1)
     {
-        $this->table="public.forecast_item";
-        $this->primary_key="fi_id";
+        $this->table="public.form_detail";
+        $this->primary_key="fo_id";
         /*
          * List of columns
          */
         $this->name=array(
-            "fi_id"=>"fi_id"
-            , "fi_text"=>"fi_text"
-            , "fi_account"=>"fi_account"
-            , "fi_card"=>"fi_card"
-            , "fi_order"=>"fi_order"
-            , "fc_id"=>"fc_id"
-            , "fi_amount"=>"fi_amount"
-            , "fi_debit"=>"fi_debit"
-            , "fi_pid"=>"fi_pid"
-            , "fi_amount_initial"=>"fi_amount_initial"
+            "fo_id"=>"fo_id"
+            , "fo_fr_id"=>"fo_fr_id"
+            , "fo_pos"=>"fo_pos"
+            , "fo_label"=>"fo_label"
+            , "fo_formula"=>"fo_formula"
         );
         /*
          * Type of columns
          */
         $this->type=array(
-            "fi_id"=>"numeric"
-            , "fi_text"=>"text"
-            , "fi_account"=>"text"
-            , "fi_card"=>"numeric"
-            , "fi_order"=>"numeric"
-            , "fc_id"=>"numeric"
-            , "fi_amount"=>"numeric"
-            , "fi_debit"=>"char"
-            , "fi_pid"=>"numeric"
-            , "fi_amount_initial"=>"numeric"
+            "fo_id"=>"numeric"
+            , "fo_fr_id"=>"numeric"
+            , "fo_pos"=>"numeric"
+            , "fo_label"=>"text"
+            , "fo_formula"=>"text"
         );
 
-
         $this->default=array(
-            "fi_id"=>"auto"
+            "pk composé"=>"auto"
         );
 
         $this->date_format="DD.MM.YYYY";
diff --git a/include/export/export_reportinit_csv.php 
b/include/export/export_reportinit_csv.php
index 8ec7951..851053e 100644
--- a/include/export/export_reportinit_csv.php
+++ b/include/export/export_reportinit_csv.php
@@ -46,7 +46,8 @@ if ( ! is_dir('tmp') )
 }
 
 $cn=Dossier::connect();
-$rap=new Acc_Report($cn,$_GET['f']);
+$http=new HttpInput();
+$rap=new Acc_Report($cn,$http->get('f',"number"));
 
 $file= fopen('php://output',"a+");
 header('Pragma: public');
diff --git a/include/impress_rapport.inc.php b/include/impress_rapport.inc.php
index a426db6..e07ad7f 100644
--- a/include/impress_rapport.inc.php
+++ b/include/impress_rapport.inc.php
@@ -29,6 +29,7 @@ require_once NOALYSS_INCLUDE.'/lib/idate.class.php';
 require_once NOALYSS_INCLUDE.'/class/acc_report.class.php';
 require_once NOALYSS_INCLUDE.'/class/exercice.class.php';
 global $g_user,$http;
+$access_code=$http->request('ac');
 //-----------------------------------------------------
 // If print is asked
 // First time in html
@@ -93,17 +94,22 @@ if ( isset( $_GET['bt_html'] ) )
 
     $hid=new IHidden();
     echo '<div class="content">';
+    $form_id=$Form->get_form_definition()->getp("fr_id");
+    $form_label=h($Form->get_form_definition()->getp("fr_label"));
+    
     if ($type_periode == 0)
     {
+        
         $t=($from_periode==$to_periode)?"":" -> 
".getPeriodeName($cn,$to_periode,'p_end');
-        echo '<h2 class="info">'.$Form->id." ".$Form->name.
-        " - ".getPeriodeName($cn,$from_periode,'p_start').
-        " ".$t.
-        '</h2>';
+        echo '<h2 class="info">'.$form_id
+                ." ".$form_label
+                ." - ".getPeriodeName($cn,$from_periode,'p_start')
+                ." ".$t
+                .'</h2>';
     }
     else
     {
-        echo '<h2 class="info">'.$Form->id." ".$Form->name.
+        echo '<h2 class="info">'.$form_id." ".$form_label.
         ' Date :'.
         $from_date.
         " au ".
@@ -115,15 +121,15 @@ if ( isset( $_GET['bt_html'] ) )
     echo '<TD><form method="GET" ACTION="?">'.
     dossier::hidden().
     HtmlInput::submit('bt_other',"Autre Rapport").
-    $hid->input("type","rapport").$hid->input("ac",$_GET['ac'])."</form></TD>";
+    
$hid->input("type","rapport").$hid->input("ac",$access_code)."</form></TD>";
 
     echo '<TD><form method="GET" ACTION="export.php">'.
     HtmlInput::submit('bt_pdf',"Export PDF").
       HtmlInput::hidden('act','PDF:report').
     dossier::hidden().
     $hid->input("type","rapport").
-    $hid->input("ac",$_GET['ac']).
-    $hid->input("form_id",$Form->id);
+    $hid->input("ac",$access_code).
+    $hid->input("form_id",$form_id);
     if ( isset($from_periode)) echo $hid->input("from_periode",$from_periode);
     if ( isset($to_periode)) echo $hid->input("to_periode",$to_periode);
     if (isset($p_step)) echo $hid->input("p_step",$p_step);
@@ -140,8 +146,8 @@ if ( isset( $_GET['bt_html'] ) )
     HtmlInput::submit('bt_csv',"Export CSV").
     dossier::hidden().
     $hid->input("type","form").
-    $hid->input("ac",$_GET['ac']).
-    $hid->input("form_id",$Form->id);
+    $hid->input("ac",$access_code).
+    $hid->input("form_id",$form_id);
     if ( isset($from_periode)) echo $hid->input("from_periode",$from_periode);
     if ( isset($to_periode)) echo $hid->input("to_periode",$to_periode);
     if (isset($p_step)) echo $hid->input("p_step",$p_step);
@@ -155,21 +161,22 @@ if ( isset( $_GET['bt_html'] ) )
     echo "</TR>";
 
     echo "</table>";
-    if ( count($Form->row ) == 0 )
+    
+    if ( empty($array)  )
         exit;
     if ( $type_periode== 0 )
     {
         if ( $p_step == 0)
         { // check the step
             // show tables
-            ShowReportResult($Form->row);
+            ShowReportResult($array);
         }
         else
         {
             $a=0;
             foreach ( $array as $e)
             {
-                echo '<h2 class="info">Periode : '.$periode_name[$a]."</h2>";
+                printf( '<h2 class="info">%s</h2> ',$periode_name[$a]);
                 $a++;
                 ShowReportResult($e);
             }
@@ -177,7 +184,7 @@ if ( isset( $_GET['bt_html'] ) )
     }
     else
     {
-        ShowReportResult($Form->row);
+        ShowReportResult($array);
     }
     echo "</div>";
     exit;
@@ -188,7 +195,7 @@ if ( isset( $_GET['bt_html'] ) )
 //-----------------------------------------------------
 require_once NOALYSS_INCLUDE.'/class/database.class.php';
 $ret=$cn->make_array("select fr_id,fr_label
-                     from formdef
+                     from form_definition
                      order by fr_label");
 if ( sizeof($ret) == 0 )
 {
@@ -199,8 +206,7 @@ if ( sizeof($ret) == 0 )
 // Form
 //-----------------------------------------------------
 echo '<div class="content">';
-$exercice=(isset($_GET['exercice']))?$_GET['exercice']:$g_user->get_exercice();
-
+$exercice=$http->get("exercice","number",$g_user->get_exercice());
 /*
  * Let you change the exercice
  */
diff --git a/include/lib/ac_common.php b/include/lib/ac_common.php
index 544b152..5a870b8 100644
--- a/include/lib/ac_common.php
+++ b/include/lib/ac_common.php
@@ -346,8 +346,8 @@ function html_page_start($p_theme="", $p_script="", 
$p_script2="")
     <TITLE>$title</TITLE>
        <link rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\" />
     <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
-    <LINK id=\"pagestyle\" REL=\"stylesheet\" type=\"text/css\" 
href=\"css/bootstrap.min.css\" media=\"screen\"/>
-    <LINK id=\"pagestyle\" REL=\"stylesheet\" type=\"text/css\" 
href=\"css/font/fontello/css/fontello.css\" media=\"screen\"/>
+    <LINK id=\"bootstrap\" REL=\"stylesheet\" type=\"text/css\" 
href=\"css/bootstrap.min.css\" media=\"screen\"/>
+    <LINK id=\"fontello\" REL=\"stylesheet\" type=\"text/css\" 
href=\"css/font/fontello/css/fontello.css\" media=\"screen\"/>
     <LINK id=\"pagestyle\" REL=\"stylesheet\" type=\"text/css\" 
href=\"css/".$style."?version=".SVNINFO."\" media=\"screen\"/>
     <link rel=\"stylesheet\" type=\"text/css\" 
href=\"css/style-print.css?version=".SVNINFO."\" media=\"print\"/>" .
     $p_script2 . "
@@ -648,7 +648,22 @@ function Decode($p_html)
     $p_html = urldecode($p_html);
     return $p_html;
 }
-
+/**
+ * @brief transform the SQL for ANALYTIC table operation_analytique
+ * @see sql_filter_per
+ * @param string $p_sql
+ */
+function transform_sql_filter_per($p_sql)
+{
+    $result=str_replace("j_tech_per in (select p_id from parm_periode  
where","",$p_sql);
+    $result=str_replace("jr_tech_per in (select p_id from parm_periode  
where","",$result);
+    $result=str_replace("j_tech_per = (select p_id from parm_periode  where  
p_start "," oa_date ",$result);
+    $result=str_replace("p_start >= to_date","oa_date >= to_date",$result);
+    $result=str_replace("p_end <= to_date","oa_date <= to_date",$result);
+ 
+    $result="( $result";
+    return $result;
+}
 /**\brief Create the condition to filter on the j_tech_per
  *        thanks a from and to date.
  * \param $p_cn database conx
@@ -673,7 +688,7 @@ function sql_filter_per($p_cn, $p_from, $p_to, 
$p_form='p_id', $p_field='jr_tech
     if ($p_form == 'p_id')
     {
         if ( isNUmber($p_from)==0 || isNUmber($p_to)==0){
-            throw new Exception("SFP1"._("Nombre invalide"));
+            throw new Exception("SFP1"._("Nombre invalide")."\$p_from=$p_from 
\$p_to=$p_to");
         }
        // retrieve the date
        $pPeriode = new Periode($p_cn);
@@ -690,7 +705,7 @@ function sql_filter_per($p_cn, $p_from, $p_to, 
$p_form='p_id', $p_field='jr_tech
        $p_to = $a_end['p_end'];
     }else {
         if ( isDate($p_from)==NULL || isDate($p_to)==NULL){
-            throw new Exception("SFP2"._("Date invalide"));
+            throw new Exception("SFP2"._("Date invalide")."\$p_from=$p_from 
\$p_to=$p_to");
         }
     }
     if ($p_from==$p_to)
diff --git a/include/lib/impress.class.php b/include/lib/impress.class.php
index 81505e5..6ba857a 100644
--- a/include/lib/impress.class.php
+++ b/include/lib/impress.class.php
@@ -1,4 +1,5 @@
 <?php
+
 /*
  *   This file is part of NOALYSS.
  *
@@ -15,15 +16,16 @@
  *   You should have received a copy of the GNU General Public License
  *   along with NOALYSS; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
+ */
 
 // Copyright Author Dany De Bontridder danydb@aevalys.eu
-/*!
+/* !
  * \file
  * \brief contains function for the parsing and computing formulae. Test are 
in scenario/test_parse_formula.php
  */
 require_once NOALYSS_INCLUDE.'/class/periode.class.php';
 require_once NOALYSS_INCLUDE.'/lib/noalyss_csv.class.php';
+require_once NOALYSS_INCLUDE.'/class/anc_account.class.php';
 
 /**
  * @class
@@ -31,7 +33,10 @@ require_once NOALYSS_INCLUDE.'/lib/noalyss_csv.class.php';
  */
 class Impress
 {
-    /*! 
+    //!< string pattern to use
+    const 
STR_PATTERN="([\[\{]{1,2}[[:alnum:]]*%*(-[c,d,s,S]){0,1}[\]\}]{1,2})";
+    
+    /* ! 
      * 
      * \brief   Purpose Parse a formula 
      *
@@ -42,152 +47,106 @@ class Impress
      *                 a string which must be evaluated
      * \param $p_type_date : type of the date 0 for accountant period or 1
      * for calendar
-     * \return array
+     * \return array key [ desc , montant ]
      *
      *
      */
-    static function 
parse_formula($p_cn,$p_label,$p_formula,$p_start,$p_end,$p_eval=true,$p_type_date=0,$p_sql="")
+
+    static function parse_formula($p_cn, $p_label, $p_formula, $p_start, 
$p_end, $p_eval=true, $p_type_date=0, $p_sql="")
     {
         global $g_user;
-        if ( Impress::check_formula($p_formula) == false)
+        if (Impress::check_formula($p_formula)==false)
         {
-            if ( $p_eval == true)
+            if ($p_eval==true)
                 return array('desc'=>$p_label.'  Erreur Formule!',
-                             'montant'=>0);
+                    'montant'=>0);
             else
                 return $p_formula;
-
         }
-        if ( $p_type_date == 0 )
-            $cond=sql_filter_per($p_cn,$p_start,$p_end,'p_id','j_tech_per');
-        else
+        if ($p_type_date==0)
+        {
+            $cond=sql_filter_per($p_cn, $p_start, $p_end, 'p_id', 
'j_tech_per');
+            $cond_anc= "and ".transform_sql_filter_per($cond);
+        }
+        else {
             $cond="( j_date >= to_date('$p_start','DD.MM.YYYY') and j_date <= 
to_date('$p_end','DD.MM.YYYY'))";
+            $cond_anc="and ( oa_date >= to_date('$p_start','DD.MM.YYYY') and 
oa_date <= to_date('$p_end','DD.MM.YYYY'))";
+        }
 
-        while (preg_match_all("(\[[0-9]*[A-Z]*%*c*d*s*S*\])",$p_formula,$e) == 
true)
-          {
-            // remove the [ ]
+        // ------------------- for accounting , analytic or 
card-------------------------------------
+        if ( DEBUGNOALYSS > 1) 
+        {
+            tracedebug("impress.debug.log", "$p_formula ", 'parse_formula-71 
$formula to parse' );
+            tracedebug("impress.debug.log", "$p_label ", 'parse_formula-72 
$p_label' );
+            tracedebug("impress.debug.log", $p_start,'parse_formula-73 
$p_start' );
+            tracedebug("impress.debug.log", $p_end,'parse_formula-74 $p_end ' 
);
+            tracedebug("impress.debug.log", $p_type_date,'parse_formula-75 
$p_type_date' );
+            tracedebug("impress.debug.log", $p_sql,'parse_formula-76 $p_sql' );
+            tracedebug("impress.debug.log", $cond ,'parse_formula-77 $cond SQL 
accountancy' );
+            tracedebug("impress.debug.log", $cond_anc,'parse_formula-78 
$cond_anc SQL Analytic Acc' );
+        }
+        while (preg_match_all(Impress::STR_PATTERN, $p_formula, $e)==true)
+        {
             $x=$e[0];
             foreach ($x as $line)
-              {
-                $compute='all';
-                if ( strpos($line,'d') != 0 )
-                  $compute='deb';
-                if ( strpos($line,'c') != 0 )
-                  $compute='cred';
-                if ( strpos($line,'s') != 0 )
-                  $compute='signed';
-                if ( strpos($line,'S') != 0 )
-                  $compute='cdsigned';
-                $line=str_replace ("[","",$line);
-                $line=str_replace ("]","",$line);
-                $line=str_replace ("d","",$line);
-                $line=str_replace ("c","",$line);
-                $line=str_replace ("s","",$line);
-                $line=str_replace ("S","",$line);
+            {
+                  tracedebug("impress.debug.log", "$line", 'parse_formula-93 
$line ' );
+               
                 // If there is a FROM clause we must recompute
                 // the time cond
 
-                if ($p_type_date == 0 && preg_match ("/FROM=[0-9]+\.[0-9]+/", 
$p_formula,$afrom) == 1 )
-                  {
-                    // There is a FROM clause
-                    // then we must modify the cond for the periode
-                    $from=str_replace("FROM=","",$afrom[0]);
-
-                    // Get the periode
-                    /*! \note special value for the clause FROM=00.0000
-                     */
-                    if ( $from == '00.0000' )
-                      {
-
-                        // retrieve the first month of this periode
-                        $user_periode=$g_user->get_periode();
-                        $oPeriode=new Periode($p_cn);
-                        $periode=$oPeriode->get_exercice($user_periode);
-                        list($first,$last)=$oPeriode->get_limit($periode);
-                        $ret=$first->get_date_limit();
-                        $end_date=$oPeriode->get_date_limit($p_end);
-                        if ($ret == null ) throw new Exception ('Pas de limite 
à cette période',1);
-                        
$cond=sql_filter_per($p_cn,$ret['p_start'],$end_date['p_end'],'date','j_tech_per');
-
-
-                      }
-                    else
-                      {
-                        $oPeriode=new Periode($p_cn);
-                        try
-                          {
-                            $pfrom=$oPeriode->find_periode('01.'.$from);
-                            $cond=  sql_filter_per($p_cn, $pfrom, 
$p_end,'p_id','j_tech_per');
-                          }
-                        catch (Exception $exp)
-                          {
-                            /* if none periode is found
-                               then we take the first periode of the year
-                            */
-                            $user_periode=$g_user->get_periode();
-
-                            $year=$oPeriode->get_exercice($user_periode);
-                            list($first,$last)=$oPeriode->get_limit($year);
-                            $ret=$first->get_date_limit();
-                            $end_date=$oPeriode->get_date_limit($p_end);
-                            if ($ret == null ) throw new Exception ('Pas de 
limite à cette période',1);
-                            
$cond=sql_filter_per($p_cn,$ret['p_start'],$end_date['p_end'],'date','j_tech_per');
-                          }
-                      }
-                  }
-
-                if ( strpos($p_formula,"FROM") != 0)
-                  {
+                if ($p_type_date==0&&preg_match("/FROM=[0-9]+\.[0-9]+/", 
$p_formula, $afrom)==1)
+                {
+                    $from=str_replace('FROM=','',$afrom[0]);
+                    $cond = \Impress::compute_periode($p_cn,$from,$p_end);
+                    $cond_anc=" and ".transform_sql_filter_per($cond);
                     // We remove FROM out of the p_formula
-                    
$p_formula=substr_replace($p_formula,"",strpos($p_formula,"FROM"));
-                  }
-
-                // Get sum of account
-                $P=new Acc_Account_Ledger($p_cn,$line);
-                $detail=$P->get_solde_detail($cond.$p_sql);
-
+                    $p_formula=substr_replace($p_formula, "", 
strpos($p_formula, "FROM"));
+                }
+                  if ($p_type_date==1&&preg_match("/FROM=[0-9]+\.[0-9]+/", 
$p_formula, $afrom)==1)
+                {
+                    // We remove FROM out of the p_formula
+                    $p_formula=substr_replace($p_formula, "", 
strpos($p_formula, "FROM"));
+                }
+                $amount=\Impress::compute_amount($p_cn,$line,$cond." 
".$p_sql,$cond_anc." ".$p_sql);
+      
 
-                if ( $compute=='all')
-                  $i=$detail['solde'];
-                if ( $compute=='deb')
-                  $i=$detail['debit'];
-                if ( $compute=='cred')
-                  $i=$detail['credit'];
-                if ( $compute=='signed')
-                  $i=bcsub($detail['debit'],$detail['credit'],4);
-                if ( $compute=='cdsigned')
-                  $i=bcsub($detail['credit'],$detail['debit'],4);
-                $p_formula=str_replace($x[0],$i,$p_formula);
-              }
-          }
+                $p_formula=str_replace($x[0], $amount, $p_formula);
+            }
+        }
 
         // $p_eval is true then we eval and returns result
-        if ( $p_eval == true)
+        if ($p_eval==true)
         {
-            /*-------------------------------------
+            /* -------------------------------------
              * Protect againt division by zero 
              */
             $p_formula=remove_divide_zero($p_formula);
             $p_formula="\$result=".$p_formula.";";
+            tracedebug("impress.debug.log",$p_formula,"formula to evaluate 
+103");
+            
             eval("$p_formula");
 
-            while (preg_match("/\[([0-9]+)([Tt]*)\]/",trim($p_label),$e) == 1)
+            while (preg_match("/\[([0-9]+)(-[Tt]*)\]/", trim($p_label), $e)==1)
             {
-                $nom = "!!".$e[1]."!!";
+                $nom="!!".$e[1]."!!";
                 if (Impress::check_formula($e[0]))
                 {
-                    $nom = $p_cn->get_value ( "SELECT pcm_lib AS acct_name 
FROM tmp_pcmn WHERE pcm_val::text LIKE $1||'%' ORDER BY pcm_val ASC LIMIT 
1",array($e[1]));
-                    if($nom)
+                    $nom=$p_cn->get_value("SELECT pcm_lib AS acct_name FROM 
tmp_pcmn WHERE pcm_val::text LIKE $1||'%' ORDER BY pcm_val ASC LIMIT 1",
+                            array($e[1]));
+                    if ($nom)
                     {
-                        if($e[2] == 'T') $nom = strtoupper($nom);
-                        if($e[2] == 't') $nom = strtolower($nom);
+                        if ($e[2]=='-T')
+                            $nom=strtoupper($nom);
+                        if ($e[2]=='-t')
+                            $nom=strtolower($nom);
                     }
                 }
-                $p_label = str_replace($e[0], $nom, $p_label);
+                $p_label=str_replace($e[0], $nom, $p_label);
             }
 
             $aret=array('desc'=>$p_label,
-                        'montant'=>$result);
+                'montant'=>$result);
             return $aret;
         }
         else
@@ -196,59 +155,70 @@ class Impress
             return $p_formula;
         }
     }
-    /*!
+
+    /* !
      * \brief  Check if formula doesn't contain
      *           php injection
      * \param string
      *
      * \return true if the formula is good otherwise false
      */
+
     static function check_formula($p_string)
     {
         // the preg_match gets too complex if we want to add a test
         // for parenthesis, math function...
         // So I prefer remove them before testing
-        $p_string=str_replace("round","",$p_string);
-        $p_string=str_replace("abs","",$p_string);
-        $p_string=str_replace("(","",$p_string);
-        $p_string=str_replace(")","",$p_string);
+
+
+
+        $p_string=str_replace("round", "", $p_string);
+        $p_string=str_replace("abs", "", $p_string);
+        $p_string=str_replace("(", "", $p_string);
+        $p_string=str_replace(")", "", $p_string);
         // for  the inline test like $a=(cond)?value:other;
-        $p_string=str_replace("?","+",$p_string);
-        $p_string=str_replace(":","+",$p_string);
-        $p_string=str_replace(">=","+",$p_string);
-        $p_string=str_replace("<=","+",$p_string);
-        $p_string=str_replace(">","+",$p_string);
-        $p_string=str_replace("<","+",$p_string);
+        $p_string=str_replace("?", "+", $p_string);
+        $p_string=str_replace(":", "+", $p_string);
+        $p_string=str_replace(">=", "+", $p_string);
+        $p_string=str_replace("<=", "+", $p_string);
+        $p_string=str_replace(">", "+", $p_string);
+        $p_string=str_replace("<", "+", $p_string);
         // eat Space + comma
-        $p_string=str_replace(" ","",$p_string);
-        $p_string=str_replace(",","",$p_string);
+        $p_string=str_replace(" ", "", $p_string);
+        $p_string=str_replace(",", "", $p_string);
         // Remove D/C/S
-        $p_string=str_replace("c","",$p_string);
-        $p_string=str_replace("d","",$p_string);
-        $p_string=str_replace("s","",$p_string);
-        $p_string=str_replace("S","",$p_string);
+        $p_string=str_replace("-c", "", $p_string);
+        $p_string=str_replace("-d", "", $p_string);
+        $p_string=str_replace("-s", "", $p_string);
+        $p_string=str_replace("-S", "", $p_string);
         // Remove T,t
-        $p_string=str_replace("t","",$p_string);
+        $p_string=str_replace("-t", "", $p_string);
+
+        // analytic accountancy (between {} )
+        $p_string=preg_replace("/\{\{[[:alnum:]]*\}\}/", "", $p_string);
+
+        // card (between {} )
+        $p_string=preg_replace("/\{[[:alnum:]]*\}/", "", $p_string);
 
         // remove date
-        $p_string=  preg_replace("/FROM*=*[0-9]+/", "", $p_string);
+        $p_string=preg_replace("/FROM*=*[0-9]+/", "", $p_string);
         // remove comment
-        $p_string=  preg_replace("/#.*/", "", $p_string);
-        // remove $C=
-        $p_string=  preg_replace('/\$[a-z]*[A-Z]*[0-9]*[A-Z]*[a-z]*/', "", 
$p_string);
-        $p_string=  preg_replace('/=/', "", $p_string);
+        $p_string=preg_replace("/#.*/", "", $p_string);
+        // remove php variable $C=
+        $p_string=preg_replace('/\$[a-z]*[A-Z]*[0-9]*[A-Z]*[a-z]*/', "", 
$p_string);
+        $p_string=preg_replace('/=/', "", $p_string);
 
         // remove account
-        $p_string=  preg_replace("/\[[0-9]*[A-Z]*%*\]/", "", $p_string);
+        $p_string=preg_replace("/\[[0-9]*[A-Z]*%*\]/", "", $p_string);
 
-        $p_string=  preg_replace("/\+|-|\/|\*/", "", $p_string);
-        $p_string=  preg_replace("/[0-9]*\.*[0-9]/", "", $p_string);
+        $p_string=preg_replace("/\+|-|\/|\*/", "", $p_string);
+        $p_string=preg_replace("/[0-9]*\.*[0-9]/", "", $p_string);
 
         
//************************************************************************************************************
         // If the string is empty then formula should be good
         //
         
//************************************************************************************************************
-        if ($p_string == '')
+        if ($p_string=='')
         {
             return true;
         }
@@ -257,7 +227,8 @@ class Impress
             return false;
         }
     }
-     /**
+
+    /**
      * with the handle of a successull query, echo each row into CSV and
      * send it directly
      * @param type $array of data
@@ -305,4 +276,183 @@ class Impress
         }
     }
 
-}
\ No newline at end of file
+    /**
+     * return what to consider 
+     *    - "deb" for the total of the debit , 
+     *    - "cred" for total of credit, 
+     *    - "signed" for tot. debit - tot. credit 
+     *    -  "cdsigned" for  tot.credit - tot.debit
+     *    - "all" is the balance of accounting in absolute value
+     * 
+     * @param string $p_formula
+     * @return "all", "deb","cred","signed" or "cdsigned"
+     */
+    static function find_computing_mode($p_formula)
+    {
+        if (strpos($p_formula, '-d')!=0)
+        {
+            return 'deb';
+        }
+        elseif (strpos($p_formula, '-c')!=0)
+        {
+            return 'cred';
+        }
+        elseif (strpos($p_formula, '-s')!=0)
+        {
+            return 'signed';
+        }
+        elseif (strpos($p_formula, '-S')!=0)
+        {
+            return 'cdsigned';
+        }
+        return 'all';
+    }
+    /**
+     * @brief make the condition SQL for filtering on the period
+     * @param \DatabaseCore $p_cn 
+     * @param int $p_from periode id
+     * @param int $p_end until periode id
+     * @throws Exception
+     */
+    static public function compute_periode($p_cn, $p_from,$p_end)
+    {
+        global $g_user;
+        // There is a FROM clause
+        // then we must modify the cond for the periode
+        
+
+        // Get the periode
+        /* ! \note special value for the clause FROM=00.0000
+         */
+        if ($p_from=='00.0000')
+        {
+
+            // retrieve the first month of this periode
+            $user_periode=$g_user->get_periode();
+            $oPeriode=new Periode($p_cn);
+            $periode=$oPeriode->get_exercice($user_periode);
+            list($first, $last)=$oPeriode->get_limit($periode);
+            $ret=$first->get_date_limit();
+            $end_date=$oPeriode->get_date_limit($p_end);
+            if ($ret==null)
+                throw new Exception('Pas de limite à cette période', 1);
+            $cond=sql_filter_per($p_cn, $ret['p_start'], $end_date['p_end'], 
'date', 'j_tech_per');
+        }
+        else
+        {
+            $oPeriode=new Periode($p_cn);
+            try
+            {
+                $pfrom=$oPeriode->find_periode('01.'.$p_from);
+                $cond=sql_filter_per($p_cn, $pfrom, $p_end, 'p_id', 
'j_tech_per');
+            }
+            catch (Exception $exp)
+            {
+                /* if none periode is found
+                  then we take the first periode of the year
+                 */
+                $user_periode=$g_user->get_periode();
+
+                $year=$oPeriode->get_exercice($user_periode);
+                list($first, $last)=$oPeriode->get_limit($year);
+                $ret=$first->get_date_limit();
+                $end_date=$oPeriode->get_date_limit($p_end);
+                if ($ret==null)
+                {
+                    throw new Exception('Pas de limite à cette période', 1);
+                }
+                $cond=sql_filter_per($p_cn, $ret['p_start'], 
$end_date['p_end'], 'date', 'j_tech_per');
+            }
+        }
+        return $cond;
+    }
+    /**
+     * @brief compute the amount of the accounting ,analytic accounting or a 
card, the SQL condition
+     * from sql_filter_per must be transformed for ANALYTIC ACCOUNT
+     * @see  sql_filter_per
+     * @param DatabaseCore $p_cn
+     * @param string $p_expression part of a formula
+     * @param string $p_cond_sql SQL cond  for accountancy 
+     * @param string $p_cond_sql SQL cond  for analytic accountancy
+     */
+    static function compute_amount($p_cn, $p_expression, 
$p_cond_sql,$p_cond_anc_sql)
+    {
+        if ( DEBUGNOALYSS > 1) 
+        {
+            tracedebug("impress.debug.log", "$p_expression", '$p_expression' );
+            tracedebug("impress.debug.log", "$p_cond_sql", '$p_cond_sql' );
+        }
+        $compute=\Impress::find_computing_mode($p_expression);
+        // remove char for the mode
+        $p_expression=str_replace("-d", "", $p_expression);
+        $p_expression=str_replace("-c", "", $p_expression);
+        $p_expression=str_replace("-s", "", $p_expression);
+        $p_expression=str_replace("-S", "", $p_expression);
+        // we have an account
+        if (preg_match("/\[.*\]/", $p_expression)) {
+            $p_expression=str_replace("[", "", $p_expression);
+            $p_expression=str_replace("]", "", $p_expression);
+            $P=new Acc_Account_Ledger($p_cn, $p_expression);
+            $detail=$P->get_solde_detail($p_cond_sql);
+        } elseif (preg_match("/\{\{.*\}\}/", $p_expression))
+        { 
+            $p_expression=str_replace("{", "", $p_expression);
+            $p_expression=str_replace("}", "", $p_expression);
+            $anc_account= new Anc_Account($p_cn);
+            $anc_account->load_by_code($p_expression);
+          
+             if ( DEBUGNOALYSS > 1) 
+            {
+                tracedebug("impress.debug.log", $p_expression, 'code analytic 
account');
+                tracedebug("impress.debug.log", $p_cond_anc_sql, 'condition 
SQL ');
+            }
+            /// Transform the $p_cond_sql , it comes from sql_filter_per
+            // and looks like j_tech_per in (select p_id from parm_periode  
where 
+            
+            $detail=$anc_account->get_balance($p_cond_anc_sql);
+        
+        } elseif (preg_match("/\{.*\}/", $p_expression))
+        { // we have a card
+            // remove useless char
+            $p_expression=str_replace("{", "", $p_expression);
+            $p_expression=str_replace("}", "", $p_expression);
+            $fiche=new Fiche($p_cn);
+            if ( DEBUGNOALYSS > 1) 
+            {
+                tracedebug("impress.debug.log", "$p_expression", 'search_card 
qcode =');
+            }
+            $fiche->get_by_qcode(strtoupper(trim($p_expression)));
+            $detail=$fiche->get_solde_detail($p_cond_sql);
+        } else {
+            throw new \Exception ("Impress::compute_amount383.".
+                    " Unknown expression \$p_expression [$p_expression]".
+                    " \$p_cond_sql $p_cond_sql");
+        }
+        
+        
+        
+      
+        // Get sum of account
+
+        switch ($compute)
+        {
+            case "all":
+                $res=$detail['solde'];
+                break;
+            case 'deb':
+                $res=$detail['debit'];
+                break;
+            case 'cred':
+                $res=$detail['credit'];
+                break;
+            case 'signed':
+                $res=bcsub($detail['debit'], $detail['credit'], 4);
+                break;
+            case 'cdsigned':
+                $res=bcsub($detail['credit'], $detail['debit'], 4);
+                break;
+        }
+        return $res;
+    }
+
+}
diff --git a/include/lib/manage_table_sql.class.php 
b/include/lib/manage_table_sql.class.php
index 7d88293..2734566 100644
--- a/include/lib/manage_table_sql.class.php
+++ b/include/lib/manage_table_sql.class.php
@@ -463,7 +463,12 @@ function check()
 
        ";
     }
-
+    function show_error($p_col)
+    {
+        $error=$this->get_error($p_col);
+        if ($error == "") { return "";}
+        return HtmlInput::errorbulle($error);
+    }
     /**
      * Set the object_name 
      * @param string $p_object_name name of the JS var, used in ajax 
response,id
@@ -1250,7 +1255,7 @@ function check()
             ob_start();
 
             echo HtmlInput::title_box($this->getTitle(), 
$this->dialog_box,"close","","y","y");
-            printf('<form id="frm%s_%s" method="POST" 
onsubmit="%s.save(\'frm%s_%s\');return false;">',
+            printf('<form id="frm%s_%s"  method="POST" 
onsubmit="%s.save(\'frm%s_%s\');return false;">',
                     $this->object_name, $this->table->get_pk_value(),
                     $this->object_name, $this->object_name,
                     $this->table->get_pk_value());
diff --git a/include/lib/message_javascript.php 
b/include/lib/message_javascript.php
index 75dd82d..68e6241 100644
--- a/include/lib/message_javascript.php
+++ b/include/lib/message_javascript.php
@@ -111,4 +111,7 @@ content[76]="<?php echo htmlspecialchars(_('Il est 
conseillé d\'avoir un quickc
 content[77]="<?php echo htmlspecialchars(_("Permet de chercher dans le suivi 
pour les contacts multiples"),ENT_QUOTES)?>";
 <?php $file_too_large=sprintf("Fichier trop grand , taille max = %s 
mb",(round(MAX_FILE_SIZE/1024/1024,2)));?>
 content[78]="<?php echo htmlspecialchars($file_too_large,ENT_QUOTES)?>";
+
+content[79]="<?php echo htmlspecialchars(_("Les postes comptables sont entre 
[] , les fiches entre {} et les postes analytiques entre {{ }}"))?>";
+    
 </script>
diff --git a/include/report.inc.php b/include/report.inc.php
index fc52126..ff6535f 100644
--- a/include/report.inc.php
+++ b/include/report.inc.php
@@ -28,6 +28,8 @@ require_once  NOALYSS_INCLUDE.'/lib/user_menu.php';
 require_once NOALYSS_INCLUDE.'/lib/ifile.class.php';
 require_once NOALYSS_INCLUDE.'/lib/ibutton.class.php';
 require_once NOALYSS_INCLUDE.'/class/acc_report.class.php';
+require_once NOALYSS_INCLUDE.'/class/acc_report_mtable.class.php';
+
 require_once NOALYSS_INCLUDE.'/class/dossier.class.php';
 require_once NOALYSS_INCLUDE.'/class/database.class.php';
 require_once  NOALYSS_INCLUDE.'/class/user.class.php';
@@ -36,6 +38,7 @@ global $http;
 
 $gDossier=dossier::id();
 $str_dossier=dossier::get();
+$http=new HttpInput();
 
 /* Admin. Dossier */
 $rep=Dossier::connect();
@@ -47,33 +50,18 @@ $rap=new Acc_Report($cn);
 $menu=0;
 if (isset($_POST["del_form"]))
 {
-    $rap->id=$http->post("fr_id","number");
+    $rap=$rap=new Acc_Report($cn,$http->post("fr_id","number"));
     $rap->delete();
     $menu=1;
 }
-if (isset($_POST["record"]))
-{
-    $rap->from_array($_POST);
-    $rap->save();
-    $menu=1;
-}
-if (isset($_POST['update']))
-{
-    $rap->from_array($_POST);
-    $rap->save($_POST);
-    $menu=0;
-}
-if (isset($_POST['upload']))
-{
-    $rap->upload();
-    $menu=1;
-}
+
+
 
 if (isset($_REQUEST["action"]) && $menu == 0)
 {
 
-    $action=$_REQUEST ["action"];
-    $rap->id=(isset($_REQUEST ['fr_id']))?$_REQUEST['fr_id']:0;
+    $action=$http->request("action");
+    $rap->id=$http->request('fr_id',"number",0);
 
     if ($action=="add"&&!isset($_REQUEST['fr_id']))
     {
@@ -82,67 +70,80 @@ if (isset($_REQUEST["action"]) && $menu == 0)
         echo '<h1>'._('Définition').'</h1>';
         echo '<form method="post" >';
         echo dossier::hidden();
-        $rap->id=0;
-        echo $rap->form(15);
-
-        echo HtmlInput::submit("record", _("Sauve"));
-        echo '</form>';
-        echo '<span class="notice">'._("Les lignes vides seront 
effacées").'</span>';
-        echo "</DIV>";
+        $form_definition=new Form_Definition_SQL($cn);
+        /* name cannot be empty */
+        $name=$http->post("fr_name");
+        $name=(trim($name==""))?"auto-".date('d.m.Y H:I'):$name;
+        $form_definition->setp("fr_label",$name);
+        
+        $form_definition->save();
+        /** if there is file ($_FILES['report']) then import first */
+        $rap=new Acc_Report($cn);
+        $rap->set_form_definition($form_definition);
+        $rap->upload();
+        
         echo '<DIV class="content">';
-
-        echo '<form method="post" enctype="multipart/form-data">';
-        echo '<h1> Importation</h1>';
-        echo dossier::hidden();
-        $rap->id=0;
-        $wUpload=new IFile();
-        $wUpload->name='report';
-        $wUpload->value='report_value';
-        echo _('Importer ce rapport').' ';
-        echo $wUpload->input();
-        echo HtmlInput::submit("upload", _("Sauve"));
-        echo '</form>';
-        echo '<span class="notice">'._("Les lignes vides seront 
effacées").'</span>';
+        $iName=$rap->input_name($name);
+        echo '<h3>';
+        echo $iName->input();
+         echo '</h3>';
+        
+        $acc_report_mtable=Acc_Report_MTable::build(0, 
$form_definition->getp("fr_id"));
+        $acc_report_mtable->create_js_script();
+        echo $acc_report_mtable->display_table();
+        
+        
         echo "</DIV>";
     }
     if ($action=="view" || $action == "record")
     {
         echo '<DIV class="content">';
-        $rap->id=$http->request("fr_id","number");
-        echo '<form method="post" style="display:inline">';
-        $rap->load();
-        echo h1($rap->name);
-        echo $rap->form();
-        echo HtmlInput::hidden("fr_id", $rap->id);
-        echo HtmlInput::hidden("action", "record");
-        echo HtmlInput::submit("update", _("Mise a jour"));
-        echo HtmlInput::submit("del_form", _("Effacement"));
-
-        echo '</form>';
-        echo '<form method="get" action="export.php" style="display:inline">';
+        $id=$http->request("fr_id","number");
+        $form_definition=new Form_Definition_SQL($cn,$id);
+        $name=$form_definition->getp("fr_label");
+        $rap=new Acc_Report($cn);
+        $rap->set_form_definition($form_definition);
+        $iName=$rap->input_name($name);
+        echo '<h3>';
+        echo  $iName->input();
+        echo '</h3>';
+        
+        $acc_report_mtable=Acc_Report_MTable::build(0, $id);
+        $acc_report_mtable->create_js_script();
+        echo $acc_report_mtable->display_table();
+        
+        echo '<form method="get"  action="export.php" style="display:inline" 
>';
         echo dossier::hidden();
         echo HtmlInput::hidden("act", "CSV:reportinit");
-        echo HtmlInput::hidden('f', $rap->id);
+        echo HtmlInput::hidden('f',$id);
         echo HtmlInput::submit('bt_csv', "Export CSV");
         echo HtmlInput::request_to_hidden(array('ac', 'action', 'p_action', 
'fr_id'));
-        
$href=http_build_query(array('ac'=>$_REQUEST['ac'],'gDossier'=>$_REQUEST['gDossier']));
-        echo '<a style="display:inline" class="smallbutton" 
href="do.php?'.$href.'">'._('Retour').'</a>';
+        
$href=http_build_query(array('ac'=>$http->request('ac'),'gDossier'=>$gDossier));
+        
+        echo '</form>';
+        echo '<form style="display:inline" method="post" id="del_form_frm" 
onsubmit="return confirm_box(\'del_form_frm\',content[47])">';
+        echo HtmlInput::request_to_hidden(array('ac',  'fr_id'));
+        echo HtmlInput::hidden("del_form","1");
+        echo HtmlInput::submit(uniqid(), _('Efface'));
         echo '</form>';
-        echo '<span class="notice">'._("Les lignes vides seront 
effacées").'</span>';
+        echo '<a style="display:inline" class="button" 
href="do.php?'.$href.'">'._('Retour').'</a>';  
         echo "</DIV>";
     }
 }
 else
 {
-
+    $rap->create();
     $lis=$rap->get_list();
-    $ac="&ac=".$_REQUEST['ac'];
+    $ac="&ac=".$http->request('ac');
     $p_action='p_action=defreport';
     echo '<div class="content">';
    echo _('Cherche')." ".HtmlInput::filter_table("rapport_table_id", '0', 1);
 
     echo '<TABLE id="rapport_table_id" class="vert_mtitle">';
-    echo '<TR><TD class="first"><A 
HREF="?'.$p_action.$ac.'&action=add&'.$str_dossier.'">Ajout</A></TD></TR>';
+    echo '<TR><TD class="first">';
+    echo '<a href="#" 
onclick="document.getElementById(\'acc_report_create_div\').style.display=\'block\'">'
+            ._("Ajout")
+            .'</A></TD></TR>';
 
     foreach ($lis as $row)
     {
@@ -153,3 +154,4 @@ else
 }
 html_page_stop();
 ?>
+
diff --git a/sql/upgrade.sql b/include/sql/patch/upgrade160.sql
similarity index 62%
copy from sql/upgrade.sql
copy to include/sql/patch/upgrade160.sql
index 51bb51b..5604d59 100644
--- a/sql/upgrade.sql
+++ b/include/sql/patch/upgrade160.sql
@@ -1,3 +1,5 @@
+begin;
+
 update menu_ref set me_menu = 'Dépôt' where me_code='CFGSTOCK';
 update menu_ref set me_menu = 'Extension' where me_code='CFGPLUGIN';
 update menu_ref set me_menu = 'Etiquette' where me_code='CFGTAG';
@@ -31,3 +33,30 @@ update profile_menu set me_code_dep='MACC',pm_id_dep=(select 
pm_id from profile_
 update profile_menu set me_code_dep='MACC',pm_id_dep=(select pm_id from 
profile_menu where me_code='MACC') where  p_id=1 and me_code_dep ='DIVPARM' and 
me_code in ('CFGPAY','CFGTVA','CFGACC');
 
 delete from profile_menu where p_id=1 and me_code='DIVPARM' and me_code_dep 
='PARAM';
+
+-- adapt formula for report
+update form set fo_formula = replace(fo_formula,'s]','-s]') where fo_formula 
not like '%-s]';
+update form set fo_formula = replace(fo_formula,'S]','-S]') where fo_formula 
not like '%-S]';;
+update form set fo_formula = replace(fo_formula,'c]','-c]') where fo_formula 
not like '%-c]';
+update form set fo_formula = replace(fo_formula,'d]','-d]') where fo_formula 
not like '%-d]';
+
+
+alter table formdef rename to form_definition; 
+alter table form rename to form_detail;
+COMMENT ON TABLE public.form_detail IS 'Simple report details with formula';
+
+alter table form_detail alter column fo_fr_id set not null;
+update forecast_item set fi_account =replace(fi_account,'s]','-s]')  where 
fi_account like '%s]%';
+update forecast_item set fi_account =replace(fi_account,'S]','-S]')  where 
fi_account like '%S]%';
+
+with qcode as (select quick_code,f_id from vw_fiche_attr vfa)
+update forecast_item set fi_account='{'||quick_code||'-s}' from qcode where 
f_id=fi_card and  fi_debit='D';
+
+with qcode as (select quick_code,f_id from vw_fiche_attr vfa)
+update forecast_item set fi_account='{'||quick_code||'-S}' from qcode where 
f_id=fi_card and  fi_debit='C';
+alter table forecast_item drop column fi_debit;
+alter table forecast_item drop column fi_card;
+update forecast_item set fi_amount_initial=0 where fi_amount_initial is null;
+
+insert into version (val,v_description) values (161,'rewriting of Impress 
(Formula), reorganize menu');
+commit ;
\ No newline at end of file
diff --git a/include/template/acc_report-create.php 
b/include/template/acc_report-create.php
new file mode 100644
index 0000000..cc27c44
--- /dev/null
+++ b/include/template/acc_report-create.php
@@ -0,0 +1,52 @@
+<?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-2021) Author Dany De Bontridder <danydb@noalyss.eu>
+
+if (!defined('ALLOWED'))
+    die('Appel direct ne sont pas permis');
+
+/**
+ * @file
+ * @brief display a form to enter a new Report definition
+ */
+$http=new HttpInput();
+?>
+<div id="acc_report_create_div" class="inner_box" style="display:none">
+<?=HtmlInput::title_box(_("Nouveau rapport"), "acc_report_create_div","hide")?>
+<form method="POST" enctype="multipart/form-data" >
+    <?=HtmlInput::hidden("ac", $http->request("ac"))?>
+    <?=HtmlInput::hidden("action", "add")?>
+    <?=Dossier::hidden()?>
+    <label for="fr_name"><?=_("Nom")?></label>
+    <input type="text" name="fr_name" autofocus class="input_text" required>
+    <?php
+        echo '<h3> Importation</h3>';
+         $wUpload=new IFile();
+        $wUpload->name='report';
+        $wUpload->value='report_value';
+        echo _('Importer ce rapport').' ';
+        echo $wUpload->input();
+    ?>
+    <ul class="aligned-block">
+        <li><?=HtmlInput::submit(uniqid(),_("Sauver"))?></li>
+        <li><?=HtmlInput::button_hide("acc_report_create_div")?></li>
+    </ul>
+</form>
+</div>
\ No newline at end of file
diff --git a/include/template/anticipation-display.php 
b/include/template/anticipation-display.php
index 8c8458e..573d9f9 100644
--- a/include/template/anticipation-display.php
+++ b/include/template/anticipation-display.php
@@ -51,8 +51,7 @@ if (count($aPerMonth[$i]) != 0 ){
                 echo  p("\$aPeriode[$h]['p_id']==\$aPerMonth[$i][$x]['fi_pid'] 
".
                         
$aPeriode[$h]['p_id']."==".$aPerMonth[$i][$x]['fi_pid'] );
                 
-               echo p("        
\$aItem[$i][$e]['fi_card']==\$aPerMonth[$i][$x]['fi_card'] ".
-                               
$aItem[$i][$e]['fi_card']."==".$aPerMonth[$i][$x]['fi_card'] );
+
                 echo p( "      
\$aItem[$i][$e]['fi_account']==\$aPerMonth[$i][$x]['fi_account']".
                         
$aItem[$i][$e]['fi_account']."==".$aPerMonth[$i][$x]['fi_account']);
                 if ($aPeriode[$h]['p_id']==$aPerMonth[$i][$x]['fi_pid']) {
@@ -60,12 +59,7 @@ if (count($aPerMonth[$i]) != 0 ){
                 } else {
                     echo 
p("\$aPeriode[$h]['p_id']==\$aPerMonth[$i][$x]['fi_pid'] NO");
                 }
-                if ( $aItem[$i][$e]['fi_card']==$aPerMonth[$i][$x]['fi_card']){
-                    echo 
"\$aItem[$i][$e]['fi_card']==\$aPerMonth[$i][$x]['fi_card'] YES";
-                } else {
-                    echo 
"\$aItem[$i][$e]['fi_card']==\$aPerMonth[$i][$x]['fi_card'] NO";
-                    
-                }
+               
                 if 
($aItem[$i][$e]['fi_account']==$aPerMonth[$i][$x]['fi_account']) {
                     echo 
p("\$aItem[$i][$e]['fi_account']==\$aPerMonth[$i][$x]['fi_account']YES");
                 } else {
@@ -77,7 +71,6 @@ if (count($aPerMonth[$i]) != 0 ){
             $amount=$aItem[$i][$e]['fi_amount'];
             if (
                 $aPeriode[$h]['p_id']==$aPerMonth[$i][$x]['fi_pid'] &&
-                
trim($aItem[$i][$e]['fi_card'])==trim($aPerMonth[$i][$x]['fi_card']) &&
                 
trim($aItem[$i][$e]['fi_account'])==trim($aPerMonth[$i][$x]['fi_account'])
                 )
                 {
@@ -163,12 +156,7 @@ $tot_cat_estm=bcadd($amount,$tot_cat_estm);
 
     <?php
  $diff= bcsub( $aReal[$i][$e][$h],$estm[$i][$e][$h]);
-if (       ( $aItem[$i][$e]['fi_card']!="" && $aItem[$i][$e]['fi_debit'] == 
'C' && $diff < 0) 
-        || ($aItem[$i][$e]['fi_card'] && $aItem[$i][$e]['fi_debit'] == 'D' && 
$diff > 0))
-  {
-    echo '<td style="text-align:right;background-color:red;color:white">';
-  }
-else if ($diff==0)
+ if ($diff==0)
   {
     echo '<td style="text-align:right;">';
   }
@@ -199,11 +187,7 @@ echo nbm( $diff);
 <?php
     $diff= bcsub($aReal[$i][$e][$h],$estm[$i][$e][$h]);
 $cum=bcadd($diff,$cum);
-if ( ($aItem[$i][$e]['fi_debit'] == 'C' && $cum < 0) || 
($aItem[$i][$e]['fi_debit'] == 'D' && $cum > 0))
-  {
-    echo '<td style="text-align:right;background-color:red;color:white">';
-  }
-else if ($cum ==0)
+if ($cum ==0)
   {
     echo '<td style="text-align:right;">';
   }
@@ -218,14 +202,8 @@ echo nbm( $cum);
 </td>
 <?php endfor;?>
 <?php
-if ( ($aItem[$i][$e]['fi_debit'] == 'C' && $cum < 0) || 
($aItem[$i][$e]['fi_debit'] == 'D' && $cum > 0))
-  {
-    echo '<td style="text-align:right;background-color:red;color:white">';
-  }
-else
-  {
+
     echo '<td style="text-align:right;background-color:green;color:white">';
-  }
  echo nbm(  $cum);
 ?>
 </td>
diff --git a/include/template/dashboard.php b/include/template/dashboard.php
index c6f438e..81282ea 100644
--- a/include/template/dashboard.php
+++ b/include/template/dashboard.php
@@ -140,8 +140,8 @@ if ( ! empty ($array) )  {
  */
 $report=$g_user->get_mini_report();
 
-$rapport=new Acc_Report($cn);
-$rapport->id=$report;
+$rapport=new Acc_Report($cn,$report);
+
 if ( $rapport->exist() == false ) {
   $g_user->set_mini_report(0);
   $report=0;
diff --git a/include/template/forecast_item_mtable-input.php 
b/include/template/forecast_item_mtable-input.php
index e1474a5..b54d106 100644
--- a/include/template/forecast_item_mtable-input.php
+++ b/include/template/forecast_item_mtable-input.php
@@ -52,44 +52,12 @@ $forecast_text = new IText("fi_text");
 $forecast_text->value = $object->getp("fi_text");
 
 /* Accounting*/
-$account = new IPoste('fi_account');
+$account = new ITextarea('fi_account');
+$account->value=$object->getp("fi_account");
+$account->id=uniqid("fi_account");
 $account->nb_row=3;
 $account->extra=' style = "margin-left:0px;width:100%;" class="input_text"';
-$account->set_attribute('account', 'fi_account');
-$account->set_attribute('bracket', 1);
-$account->set_attribute('no_overwrite', 1);
-$account->set_attribute('noquery', 1);
-$account->value = $object->getp("fi_account");
 $account->size="80rem";
-/*Quick Code */
-$qc = new ICard("fi_card");
-// If double click call the javascript fill_ipopcard
-$qc->set_dblclick("fill_ipopcard(this);");
-
-// name of the field to update with the name of the card
-$qc->set_attribute('label', 'an_label');
-
-// Type of card : all
-$qc->set_attribute('typecard', 'all');
-$qc->set_attribute('jrn', 0);
-$qc->extra = 'all';
-
-// when value selected in the autcomplete
-$qc->set_function('fill_data');
-if ($object->getp("fi_card") != "") {
-
-    $qc->value = $cn->get_value("select ad_value 
-    from fiche_detail 
-    where
-          ad_id=23 and f_id = $1", [$object->getp("fi_card")]);
-}
-
-$isDebit=new ISelect("fi_debit");
-$isDebit->value=array(
-        array("label"=>_("Crédit"),"value"=>'C'),
-        array("label"=>_("Débit"),"value"=>'D')
-    );
-$isDebit->selected=$object->getp("fi_debit");
 
 $isPeriode = new ISelect('fi_pid');
 $isPeriode->value = $aPeriode;
@@ -116,24 +84,13 @@ 
$amount_initial->value=($amount_initial->value=='')?0:$amount_initial->value;
     </tr>
     
     <tr>
-        <td><?= _("Intitulé") ?></td>
+        <td><?=$this->show_error("fi_text")?> <?= _("Intitulé") ?></td>
         <td><?= $forecast_text->input(); ?></td>
     </tr>
+    
     <tr>
         <td>
-            <?= _("Fiche") ?>
-        </td>
-        <td>
-            <?= $qc->input(); ?><?=$qc->search()?>
-            <span id="an_label"></span>
-        </td>
-    </tr>  
-    <tr>
-        <td><?= _("Positif") ?><?= Icon_Action::tips(_("Ne concerne que les 
fiches"))?></td>
-        <td><?=$isDebit->input(); ?></td>
-    </tr>
-    <tr>
-        <td>
+            <?=$this->show_error("fi_account")?> 
             <?= _("Formule") ?>
            ( <a 
href="https://wiki.noalyss.eu/doku.php?id=tutoriaux:les_rapports#un_mot_d_explication";
 target="_blank">
                 Aide</a> )
@@ -141,6 +98,10 @@ 
$amount_initial->value=($amount_initial->value=='')?0:$amount_initial->value;
         </td>
         <td>
             <?= $account->input() ?>
+            <?= HtmlInput::button_action(_("Cherche poste, fiche , 
analytique"), 
+                                
sprintf('search_account_card({gDossier:%s,target:\'%s\'})',Dossier::id(),
+                                        $account->id))
+            ?>
         </td>
     </tr>
     <tr>
diff --git a/scenario/test_parse_formula.php b/scenario/test_parse_formula.php
deleted file mode 100644
index 52663b1..0000000
--- a/scenario/test_parse_formula.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-//@description:Impress::check_formula test 
-/*
-# check the Impress::check_formula and the parse_formula
-# This file is a part of NOALYSS under GPL
-# Author Dany WM DE BONTRIDDER danydb@aevalys.eu
-*/
-
-include_once NOALYSS_INCLUDE.'/lib/impress.class.php';
-
-echo '<hr>';
-foreach ( array('1',
-               '(45+5)',
-           'round([45])',
-               '$A=9',
-               '$S30=($F1 >=0)?$F1:0',
-
-           '[45%]',
-           '[50]*[51%]',
-           '$A1=[50]*[51%]',
-           '[50]*9',
-           '[50]*9.0',
-           '[50%]*9',
-           '$C1111=[50%]*9',
-           '$C1111=[50%]*9*$D1',
-           '$C10=[10%]',
-           '[50%]*9.0',
-           '[50%]*9.0 FROM=01.2004',
-           '[50%]*9.0FROM=01.2004',
-               'system',
-               'unlink',
-               'ls -1',
-    '<script>document.location="https://yahoo.fr";;</script>',
-    "[45ABC]*1",
-    
-    
-    )
-       as $a ) {
-  echo "Testing :".h($a);
-  echo (Impress::check_formula($a)==false)?'Non valide ':'ok';
-
-  echo '<br>';
-  
-  foreach (array('+','-','/') as $b ) {
-    $ee=str_replace('*',$b,$a);
-    echo "Testing :".h($ee);
-    echo (Impress::check_formula($ee)==false)?'Non valide ':'ok';
-    echo '<br>';
-
-  }
-  for($e=0;$e<3;$e++) {
-    $a.="*".$a;
-  echo "Testing :".h($a);
-  echo (Impress::check_formula($a)==false)?'Non valide ':'ok';
-  echo '<br>';
-
-  }
- }
-
-?>
diff --git a/sql/upgrade.sql b/sql/upgrade.sql
index 51bb51b..e69de29 100644
--- a/sql/upgrade.sql
+++ b/sql/upgrade.sql
@@ -1,33 +0,0 @@
-update menu_ref set me_menu = 'Dépôt' where me_code='CFGSTOCK';
-update menu_ref set me_menu = 'Extension' where me_code='CFGPLUGIN';
-update menu_ref set me_menu = 'Etiquette' where me_code='CFGTAG';
-
-insert into menu_ref 
(me_code,me_description,me_description_etendue,me_type,me_menu) 
-       values ('MCARD','Paramètrage des fiches','Menu regroupant ce qui 
concerne les fiches','E','Fiche'),
-        ('MDOC','Paramètrage des documents','Meu regroupant ce qui concene les 
documents ','E','Document'),
-        ('MACC','Paramètrage comptabilité','Menu regroupant ce qui concerne la 
comptabilité','E','Comptabilité');
-
-insert into 
profile_menu(me_code,me_code_dep,p_id,p_order,p_type_display,pm_id_dep) 
-select 'MCARD','PARAM',1,20,'E',(select min(pm_id) from profile_menu where 
me_code='PARAM' and p_id=1) ;
-
-
-insert into 
profile_menu(me_code,me_code_dep,p_id,p_order,p_type_display,pm_id_dep) 
-select 'MDOC','PARAM',1,30,'E',(select min(pm_id) from profile_menu where 
me_code='PARAM' and p_id=1) ;
-
-insert into 
profile_menu(me_code,me_code_dep,p_id,p_order,p_type_display,pm_id_dep) 
-select 'MACC','PARAM',1,50,'E',(select min(pm_id) from profile_menu where 
me_code='PARAM' and p_id=1) ;
-
-update profile_menu set me_code_dep='MCARD',pm_id_dep=(select pm_id from 
profile_menu where me_code='MCARD') where  p_id=1 and me_code_dep ='PARAM' and 
me_code in ('CFGCARD');
-
-update profile_menu set me_code_dep='MCARD',pm_id_dep=(select pm_id from 
profile_menu where me_code='MCARD') where  p_id=1 and me_code_dep ='DIVPARM' 
and me_code in ('CFGOPT1','CFGATCARD','CFGCARDCAT');
-
-
-update profile_menu set me_code_dep='MDOC',pm_id_dep=(select pm_id from 
profile_menu where me_code='MDOC') where  p_id=1 and me_code_dep ='PARAM' and 
me_code in ('CFGDOC');
-
-update profile_menu set me_code_dep='MDOC',pm_id_dep=(select pm_id from 
profile_menu where me_code='MDOC') where  p_id=1 and me_code_dep ='DIVPARM' and 
me_code in ('CFGDOCST','CFGACTION');
-
-update profile_menu set me_code_dep='MACC',pm_id_dep=(select pm_id from 
profile_menu where me_code='MACC') where  p_id=1 and me_code_dep ='PARAM' and 
me_code in ('CFGPCMN','CFGCURRENCY','PERIODE','CFGLED','PREDOP');
-
-update profile_menu set me_code_dep='MACC',pm_id_dep=(select pm_id from 
profile_menu where me_code='MACC') where  p_id=1 and me_code_dep ='DIVPARM' and 
me_code in ('CFGPAY','CFGTVA','CFGACC');
-
-delete from profile_menu where p_id=1 and me_code='DIVPARM' and me_code_dep 
='PARAM';
diff --git a/unit-test/create-dossier-test.sh b/unit-test/create-dossier-test.sh
index aab6eb6..7ef9f2d 100755
--- a/unit-test/create-dossier-test.sh
+++ b/unit-test/create-dossier-test.sh
@@ -2,7 +2,7 @@
 
 export PGCLUSTER=10/main
 DOSSIER_TEST=rel70dossier25
-FILE_TEST=dossiertest210516-1503.sql
+FILE_TEST=dossiertest210517-1111.sql
 
 dropdb $DOSSIER_TEST
 createdb $DOSSIER_TEST
diff --git a/unit-test/include/class/impressTest.class.php 
b/unit-test/include/class/impressTest.class.php
index f444866..1c66045 100644
--- a/unit-test/include/class/impressTest.class.php
+++ b/unit-test/include/class/impressTest.class.php
@@ -52,7 +52,23 @@ class ImpressTest extends TestCase
     {
         
     }
-
+    private function setData()
+    {
+        global $g_connection;
+        $g_connection->exec_sql("delete from operation_analytique where oa_id 
> 48 and oa_id < 57");
+       $sql="INSERT INTO operation_analytique 
+           
(oa_id,po_id,oa_amount,oa_description,oa_debit,j_id,oa_date,oa_row,oa_jrnx_id_source,oa_positive,f_id)
 
+         VALUES
+        (49,3,90.0000,'',true,18,'2018-02-24',0,NULL,'Y',NULL),
+        (50,4,93.0000,'',true,18,'2018-02-24',1,NULL,'Y',NULL),
+        (51,3,10.0000,'Déplacement',false,4,'2018-02-24',0,NULL,'Y',NULL),
+        (52,1,30.0000,'Déplacement',false,4,'2018-02-24',1,NULL,'Y',NULL),
+        (53,3,25.0000,'Vente de 
marchandises',false,7,'2018-02-24',0,NULL,'Y',NULL),
+        (54,3,91.0000,'Eau',true,371,'2018-04-24',0,NULL,'Y',NULL),
+        (55,3,80.0000,'Eau',true,371,'2018-04-24',1,NULL,'Y',NULL)";
+        $g_connection->exec_sql($sql);
+       
+    }
     /**
      * 
      * @covers Impress::check_formula
@@ -118,7 +134,7 @@ class ImpressTest extends TestCase
         global $g_connection;
         // filter on period
         $sql_periode="j_date >= '2018-01-01' and j_date <= '2018-12-31'";
-        
+         $and_sql_periode="oa_date >= '2018-01-01' and oa_date <= 
'2018-12-31'";
         // 0 = formula , 1 is the expected value
         $aFormula=array(
             ["[70%-s]", -456.8000],
@@ -128,7 +144,8 @@ class ImpressTest extends TestCase
             ["[61%-c]", 100.00]
         );
         foreach ($aFormula as $formula) {
-            
$this->assertEquals($formula[1],\Impress::compute_amount($g_connection,$formula[0],$sql_periode),
+            
$this->assertEquals($formula[1],\Impress::compute_amount($g_connection,$formula[0],
+                    $sql_periode,$and_sql_periode),
                     " {$formula[0]} = {$formula[1]}");
         }
     }
@@ -173,18 +190,52 @@ class ImpressTest extends TestCase
         
 
     }
+    /**
+     * @covers Impress::parse_formula
+     * @global type $g_connection
+     * @global type $g_user
+     */
     function test_parse_formula()
     {
         global $g_connection,$g_user;
+        $this->setData();
         $a_formula=array(
-            array("sum 70% (credit is negative)", "[70%-s]",-456.80),
-            array("sum 70% (credit is negative)", "0-round([70%-s],2)",456.80),
+            0=>array("sum 70% (credit is negative)", "[70%-s]",-456.80),
+            1=>array("sum 70% (debit is negative)", 
"0-round([70%-s],2)",456.80),
+            2=>array("sum 70% (debit is negative)", 
"0-round([70%-s],2)+150",606.80),
+            3=>array("sum 70% (debit is negative)", 
"0-round([70%-s],2)*0.2+150",241.36),
+            4=>array("sum FOURNI1 ", "{FOURNI1}",1496.34),
+            5=>array("sum FOURNI1 ", "{FOURNI1}+1",1497.34),
+            6=>array("sum FOURNI1 ", "round({FOURNI1}/3,2)",498.78),
+            7=>array("sum FOURNI1 ", "round({FOURNI1-s}/3,2)",-498.78),
+            8=>array("sum FOURNI1 + 70% ", 
"[70%-S]+round({FOURNI1-s}/3,2)",-41.98),
+            9=>array("Analytic DEVELOPPEMENT","{{DEVELOPPEMENT}}",226),
+            10=>array("Analytic DEVELOPPEMENT","{{DEVELOPPEMENT-S}}",-226),
+            11=>array("Analytic DEVELOPPEMENT","{{DEVELOPPEMENT-S}}+10",-216),
+            12=>array("Analytic DEVELOPPEMENT FROM","{{DEVELOPPEMENT}} 
FROM=04.2018",171),
+            13=>array("Analytic DEVELOPPEMENT 
Credit","{{DEVELOPPEMENT-c}}",35),
+            13=>array("Analytic DEVELOPPEMENT Débit","{{DEVELOPPEMENT-d}} 
",261),
+             array("sum 70% Crédit", "[70%-c]",456.80),
+             array("sum 70% Débit", "[70%-d]",0),
+             array("sum FOURNI1 Crédit", "{FOURNI1-c}",1717.77),
+             array("sum FOURNI1 Débit", "{FOURNI1-d}",221.43),
         );
+        // ------ Periode ----------
         foreach ($a_formula as $formula) 
         {
             $result=\Impress::parse_formula($g_connection,$formula[0], 
$formula[1], 92, 103);
             $this->assertEquals($formula[2],$result['montant'],$formula[0]);
             
         }
+        //-----------Calendar -----------
+        // if there is a FROM clause, it will be skipped silently, so the 
amount is 316 and not 171
+        $a_formula[12][2]=226;
+        foreach ($a_formula as $formula) 
+        {
+            
+            $result=\Impress::parse_formula($g_connection,$formula[0], 
$formula[1], '01.01.2018', '31.12.2018',true,1);
+            $this->assertEquals($formula[2],$result['montant'],$formula[0]);
+            
+        }   
     }
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]