#include <QTreeWidgetItem>
#include <QSqlDatabase>
#include <QProgressBar>
#include <QSqlQuery>
#include <QSqlError>
#include <QApplication>
#include <QDebug>
#include <QDateTime>
#include <QCursor>
#include <QLabel>
#include <QTimer>
#include <QObject>
#include "../../MedinTuxTools-QT4/medicabase/C_BDM_Api.h"
#include "../../MedinTuxTools-QT4/medicabase/C_BDM_ApiVar.h"
#include "../../MedinTuxTools-QT4/CGestIni.h"

//=================== C_PosologieGrammar ===================================
/*! \class C_PosologieGrammar
 *  \brief Class to set and interpret posologie grammar.
 */
//---------------------------- C_PosologieGrammar ----------------------------------------------
C_PosologieGrammar::C_PosologieGrammar(const QString &grammar_expression /* ="" */, int must_be_literal /* = C_PosologieGrammar::NOT_LITERAL */)
{m_grammar_expression = grammar_expression;
 m_must_be_literal    = must_be_literal;
}
//---------------------------- setGrammar ----------------------------------------------
void C_PosologieGrammar::setGrammar(const QString &grammar_expression)
{m_grammar_expression = grammar_expression;
}
//---------------------------- setLiteral ----------------------------------------------
void C_PosologieGrammar::setLiteral(int must_be_literal    /* = C_PosologieGrammar::ALL_LITERAL */)
{m_must_be_literal = must_be_literal;
}
//---------------------------- isLiteral ----------------------------------------------
int C_PosologieGrammar::isLiteral()
{return m_must_be_literal;
}
//---------------------------- get_cip_pk [static] ------------------------------------------------
/*! \brief return cip code string from posologie grammar. If not present return ""
 *  \param const QString &grammar_expression :     grammar input string as
 *  "345687/123!ALL_LITERAL=comprimé[1;m|2;M|4;s]/8\n[0.5;m|1;M15r|2;sr30|3;h10-13]/4\n[0.5;m|1;s]/3".
 *  where cip code is 345687 and if present facultative pk code 123 after '/' symbol.
 *  \param QString *pk :  if not zero pk code will be returned in the contents of this QString pointer.
 *  \return cip code if present.
*/
QString C_PosologieGrammar::get_cip_pk(const QString &grammar_expression, QString *pk /* = 0 */)
{int pos = grammar_expression.indexOf('!');  // zero si pas de mention ou pointe apres les mentions de cip/pk!
 if (pos == -1)
    { if (pk) *pk = "";
      return "";
    }
 QString str    = grammar_expression.left(pos);
 pos            = str.indexOf('/');
 if (pos == -1)
    {if (pk) *pk = "";
     return str;
    }
 if (pk) *pk = str.mid(pos+1);
 return str.left(pos);
}
//---------------------------- toString ------------------------------------------------
QString C_PosologieGrammar::toString(const QString &_up_forme /* = "" */)
{return toString(m_grammar_expression,  _up_forme, m_must_be_literal);
}
//---------------------------- toString [static] ------------------------------------------------
//  "301546/123!ALL_LITERAL=comprimé\n        // header facultatif indique cip/hitpk! literal flags =prise unit
//  "[1;m|2;M|4;s]/8\n"                       // premiere  sequence
//  "[0.5;m|1;M15r|2;sr30|3;h10-13]/4\n"      // deuxieme  sequence
//  "[0.5;m|1;s]/3"                           // troisieme sequence
/*! \brief return human readable string from posologie grammar.
 *  \param const QString &grammar_expression     grammar input string as
 *  "345687/123!ALL_LITERAL=comprimé\n[1;m|2;M|4;s]/8\n[0.5;m|1;M15r|2;sr30|3;h10-13]/4\n[0.5;m|1;s]/3".
 *  \param int must_be_literal  undefined if -1 (the grammar string try to be used for this and if not possible it's defined to C_PosologieGrammar::NOT_LITERAL)
 *         otherwise it's must be a combination of : C_PosologieGrammar::UP_QUANTITE
 *                                                   C_PosologieGrammar::UP_JUST_FRACTION   //  conversion uniquement de 0.25 en un quart 0.5 en un demi 0.75 en trois quart
 *                                                   C_PosologieGrammar::DURATION
 *                                                   C_PosologieGrammar::SEQUENCE_HOUR
 *                                                   C_PosologieGrammar::MOMENT_MEAL
 *                                                   C_PosologieGrammar::INDICATION_LIST   indications list must be showed
 *                                                   C_PosologieGrammar::INDICATION_CODE   indications code must be showed
 *                                                   C_PosologieGrammar::INDICATION_TYPE   indications code typ (CIP CISP etc.) must be showed
 *         this parameter define how numerics values must be converted in literal string.
 *  \param QString &_up_forme      if == "" the grammar string try to be used to define, this parameter is the drug unit form.
 *  \return a french human readable string (for other langs the source code is there after ...)
 */

QString C_PosologieGrammar::toString(const QString &grammar_expression, const QString &_up_forme, int must_be_literal /* = -1 */  )
{

 int pos_end_pk = grammar_expression.indexOf('!')+1;  // zero si pas de mention ou pointe apres les mentions de cip/pk!
 int pos        = grammar_expression.indexOf('[');
 if (pos==-1)               return QString("");
 if (grammar_expression.length() && grammar_expression[pos -1]=='\n') ++pos;
 //........ traiter le cas ou la definition de literalite est donnee dans la grammaire avant le signe = .........
 QString literal_def  = "";                           // definition de la literalite
 QString up_forme     = grammar_expression.mid(pos_end_pk, pos-pos_end_pk); // (_up_forme.length())?_up_forme:grammar_expression.left(pos);
 int pos_literal      = up_forme.indexOf('=');
 if (pos_literal!=-1)          // .......... si literalite definie dans grammaire l'utiliser que si parametre d'entree non defini ..............
    {literal_def = up_forme.left(pos_literal);
     up_forme    = up_forme.mid (pos_literal+1).remove('\n');      // on retaille up_forme aux bonnes donnes
     if (must_be_literal==-1)                                      // si parametre indefini en entree alors utiliser la definition de la grammaire
        {must_be_literal = 0;
         if (literal_def.contains("UP_QUANTITE"))        must_be_literal |= C_PosologieGrammar::UP_QUANTITE;
         if (literal_def.contains("DURATION"))           must_be_literal |= C_PosologieGrammar::DURATION;
         if (literal_def.contains("SEQUENCE_HOUR"))      must_be_literal |= C_PosologieGrammar::SEQUENCE_HOUR;
         if (literal_def.contains("MOMENT_MEAL"))        must_be_literal |= C_PosologieGrammar::MOMENT_MEAL;
         if (literal_def.contains("ALL_LITERAL"))        must_be_literal  = C_PosologieGrammar::ALL_LITERAL;
         if (literal_def.contains("NOT_LITERAL"))        must_be_literal  = C_PosologieGrammar::UP_JUST_FRACTION;
         if (literal_def.contains("INDICATION_LIST"))    must_be_literal |= C_PosologieGrammar::INDICATION_LIST;
         if (literal_def.contains("INDICATION_CODE"))    must_be_literal |= C_PosologieGrammar::INDICATION_CODE;
         if (literal_def.contains("INDICATION_TYPE"))    must_be_literal |= C_PosologieGrammar::INDICATION_TYPE;
        }
    }
 if (must_be_literal==-1)
   {  must_be_literal = C_PosologieGrammar::NOT_LITERAL;
   }
 //............. si forme definie en entree on l'utilise .....................................
 //              sinon on tente d'utiliser celle définie dans la grammaire
 up_forme = (_up_forme.length())?_up_forme:up_forme;
 QString gram_exp     = grammar_expression.mid(pos);  // retailler au signe '['
 QString joinStr      = QObject::tr(", \npuis ");
 QString ret          = "";
 QStringList seqList  = gram_exp.split('\n');
 for (int i=0; i<seqList.count(); ++i)
     {ret  += sequenceToString(seqList[i], must_be_literal, up_forme); ret += joinStr;
     }
 ret = ret.left(ret.length()-joinStr.length());  // on enleve le dernier "\npuis "
 return ret;
}
//---------------------------- sequenceToString ------------------------------------------------
QString C_PosologieGrammar::sequenceToString(const QString &sequence, int must_be_literal /* = C_PosologieGrammar::NOT_LITERAL */, const QString &up_forme)
{int pos = sequence.indexOf(']');
 if (pos==-1)              return QString("");
 QString ret       = "";
 QString seq_days  = sequence.mid(pos + 1);
 QString seq_time  = sequence.left(pos).remove("[").trimmed();
 ret              += sequence_timeToString(seq_time, must_be_literal, up_forme);
 ret              += sequence_daysToString(seq_days, must_be_literal );
 return ret;
}

//---------------------------- sequence_daysToString ------------------------------------------------
//  /8
QString C_PosologieGrammar::sequence_daysToString(const QString &seq_days, int must_be_literal /* = C_PosologieGrammar::NOT_LITERAL */)
{QString       t = seq_days.at(0);
 QString     ret = seq_days;
 if (t=="/")
    {QString str_nb = ret.mid(1);
     int         nb = str_nb.toInt();
     ret            = QObject::tr("pendant ") + ( (must_be_literal&C_PosologieGrammar::DURATION)?numberToLiteral(nb):str_nb) + QObject::tr(" jour")+ ((nb>1)?"s ":" ");
    }
 return ret;
}
//---------------------------- sequence_timeToString ------------------------------------------------
// 0.5;m|1;M15r|2;sr30|3;h10-13
QString C_PosologieGrammar::sequence_timeToString(const QString &seq_time, int must_be_literal /* = C_PosologieGrammar::NOT_LITERAL */, const QString &_up_forme /* = "" */)
{QString     up_forme = "";
 QStringList  seqList = seq_time.split('|');
 QString          ret = "";
 QString          str = "";
 QString          qu  = "";
 QString       qu_lit = "";
 QString           t  = "";
 QString before       = "";
 QString after        = "";
 int     before_n     = 0;
 int     after_n      = 0;
 int              pos = 0;
 int               nb = 0;
 for (int i=0; i<seqList.count(); ++i)
    {up_forme   = _up_forme;   // ne pas accorder sexe nombre plusieurs fois donc reinitialiser
     str        = seqList[i];
     pos        = str.indexOf(';');
     if (pos   != -1)
        {//.......... C_PosologieGrammar::UP_QUANTITE la quantite d'unite de prise .....................
         //           ici est traite le mode literal ou numerique
         qu     = str.left(pos);
         if      (must_be_literal & C_PosologieGrammar::UP_QUANTITE)       // tout doit etre converti en lettre quelque soit le flag C_PosologieGrammar::UP_JUST_FRACTION
                 {qu_lit = numberToLiteral(qu, up_forme, 0);               // cet appel est toujours necessaire meme si pas de literal car met a jour orthographe et pluriel de up_forme
                  ret   += qu_lit;
                 }
         else if (must_be_literal & C_PosologieGrammar::UP_JUST_FRACTION)  // seules les parties fractionnaires 0.25 0.30 0.75 --> un quart un demi  trois quart
                 {qu_lit = numberToLiteral(qu, up_forme, 1);               // cet appel est toujours necessaire meme si pas de literal car met a jour orthographe et pluriel de up_forme
                  ret   += qu_lit;
                 }
         else                                                              // tout doit rester en numerique
                 {qu_lit = numberToLiteral(qu, up_forme, 0);               // cet appel est toujours necessaire meme si pas de literal car met a jour orthographe et pluriel de up_forme
                  ret   += qu;
                 }
         //.......... la forme (precedemment ajustee grammaticalement par l'appel numberToLiteral(qu, up_forme);) ..............
         ret   += " " + up_forme+" "; // + ((qu.toFloat()>1.0)?"s ":" ");
         //........... C_PosologieGrammar::SEQUENCE_HOUR  le moment ou prendre les medocs dans la journee .......................
         //            si specifie en heures, le mode literal
         //            ou numerique sera traite ici
         str    = str.mid(pos+1);
           t    = str.at(0);    // relever le m M a s c n h
         str    = str.mid(1);
              if ( t=="m") ret += QObject::tr("le matin");
         else if ( t=="M") ret += QObject::tr("à midi");
         else if ( t=="a") ret += QObject::tr("l'après-midi");
         else if ( t=="s") ret += QObject::tr("le soir");
         else if ( t=="c") ret += QObject::tr("au coucher");
         else if ( t=="n") ret += QObject::tr("la nuit");
         else if ( t=="h")  // mode horaire
                 {pos  = str.indexOf('-');
                  nb   = 0;                   // sera utilise pour le pluriel des heures
                  if (pos != -1)
                     {      before   = str.left(pos);
                            after    = str.mid(pos+1);
                            before_n = before.toInt();
                            after_n  = after.toInt();
                            nb       = qMax(before_n,after_n);  // reperer si le pluriel doit etre applique
                            if (must_be_literal & C_PosologieGrammar::SEQUENCE_HOUR)
                               {before  =  numberToLiteral(before_n);
                                after   =  numberToLiteral(after_n);
                               }
                            ret   += QObject::tr("de ")+ before + QObject::tr(" à ") + after;
                     }
                  else
                     {      nb = str.toInt();
                            if (must_be_literal & C_PosologieGrammar::SEQUENCE_HOUR)
                               { str = numberToLiteral(nb);
                               }
                            ret   += QObject::tr("à ") + str;
                     }
                  ret += QObject::tr(" heure") + ((nb>1)?"s":"");
                 }
         //............ C_PosologieGrammar::MOMENT_MEAL le moment par rapport au repas .........................
         //             en minutes, le mode literal numerique sera traite ici
         pos  = str.indexOf('r');
         if  (pos != -1)
             { before   = str.left(pos);
               after    = str.mid(pos+1);
               before_n = before.toInt();
               after_n  = after.toInt();
               //if (before_n||after_n)
                  {
                   if (must_be_literal & C_PosologieGrammar::MOMENT_MEAL)
                      { before = numberToLiteral(before.toInt());
                        after  = numberToLiteral(after.toInt());
                      }
                   if      (before.length()) ret += " " + before + QObject::tr(" minutes avant le repas");
                   else if (after.length() ) ret += " " + after  + QObject::tr(" minutes après le repas");
                   else                      ret += " " + QObject::tr("au cours du repas");
                  }
             }
         ret += ", ";
        }
    }  // end for (int i=0; i<seqList.count(); ++i)
 return ret;
}
//---------------------------- numberToLiteral ------------------------------------------------
QString C_PosologieGrammar::numberToLiteral(QString number, QString &up_forme , int justOneFraction /* = false */)
{number.replace(',','.');
 QString       str  = "";
 int left_part_int  = 0;
 QString left_part  = "";
 QString right_part = "";
 char          sexe = 'm';
 int pos            = number.indexOf(".");
 if (pos != -1)               // UP_QUANTITE et UP_JUST_FRACTION ==>
    {//  0.75 1.75 789.75
     left_part         = number.left(pos);
     right_part        = number.mid (pos+1);
     left_part_int     = left_part.toInt();
     up_forme          = adjustPlurielUpForme(left_part_int, up_forme, sexe);
     if (left_part_int==0)  left_part  = "";
     else                   left_part  = numberToLiteral(left_part.toInt(), sexe);
     if      (right_part=="25")
             { if (left_part_int)
                  {if (justOneFraction ) return number;
                   else                  return left_part + "et un quart de";
                  }
               else                      return QString("un quart de");
             }
     else if (right_part=="50" || right_part=="5")
             { str = (sexe=='f')?"une demi":"un demi";
               if (left_part_int)
                  {if (justOneFraction) return number;
                   else                 return left_part + "et "+ str;
                  }
               else                     return str;
             }
     else if (right_part=="75")
             { if (left_part_int)
                  {if (justOneFraction) return number;
                   else                 return left_part + "et trois quarts de";
                  }
               else                     return QString("trois quarts de");
             }
     else    { if (justOneFraction)     return number;
               else  right_part = numberToLiteral(right_part.toInt(),sexe);
             }
     if (left_part_int==0) return QString("zéro virgule ") + right_part;
     else                  return left_part + " virgule "  + right_part;
    }
 left_part_int     = number.toInt();
 up_forme          = adjustPlurielUpForme(left_part_int, up_forme, sexe);
 if (justOneFraction) return number;   // toujours executer adjustPlurielUpForme() car ajuste la forme au pluriel
 else                 return numberToLiteral(left_part_int,sexe);
}
//---------------------------- adjustPlurielUpForme ------------------------------------------------
QString C_PosologieGrammar::adjustPlurielUpForme(int nb, const QString &_up_forme, char &sexe)
{QString up_forme = _up_forme;
 sexe = 'm';
 if (up_forme.contains("cuillere"))
 {sexe = 'f';
  return up_forme.replace("cuillere",(nb>1)?"cuillères":"cuillère").replace(" a "," à ");
 }
 if (up_forme.contains("cuillère"))
 {sexe = 'f';
  return up_forme.replace("cuillère",(nb>1)?"cuillères":"cuillère").replace(" a "," à ");
 }
 else if(up_forme.contains("application"))
 {sexe = 'f';
  return up_forme.replace("application",(nb>1)?"applications":"application");
 }
 else if(up_forme.contains("goutte"))
 {sexe = 'f';
  return up_forme.replace("goutte",(nb>1)?"gouttes":"goutte");
 }
 else if(up_forme.contains("injection"))
 {sexe = 'f';
  return up_forme.replace("injection",(nb>1)?"injections":"injection");
 }
 else if(up_forme.contains("inhalation"))
 {sexe = 'f';
  return up_forme.replace("inhalation",(nb>1)?"inhalations":"inhalation");
 }
 else if(up_forme.contains("gelule"))
 {sexe = 'f';
  return up_forme.replace("gelule",(nb>1)?"gélules":"gélule");
 }
 else if(up_forme.contains("gélule"))
 {sexe = 'f';
  return up_forme.replace("gélule",(nb>1)?"gélules":"gélule");
 }
 else if(up_forme.contains("pulverisation"))
 {sexe = 'f';
  return up_forme.replace("pulverisation",(nb>1)?"pulvérisations":"pulvérisation");
 }
 else if(up_forme.contains("pulvérisation"))
 {sexe = 'f';
  return up_forme.replace("pulvérisation",(nb>1)?"pulvérisations":"pulvérisation");
 }
 else if(up_forme.contains("ampoule"))
 {sexe = 'f';
  return up_forme.replace("ampoule",(nb>1)?"ampoules":"ampoule");
 }
 else if(up_forme.contains("capsule"))
 {sexe = 'f';
  return up_forme.replace("capsule",(nb>1)?"capsules":"capsule");
 }
 else if(up_forme.contains("ml"))
 {sexe = 'm';
  return up_forme;
 }
 else if(up_forme.contains("mg"))
 {sexe = 'm';
  return up_forme;
 }
 else if(up_forme.contains("ui"))
 {sexe = 'f';
  return up_forme;
 }
 else if(up_forme.contains("comprime"))
 {sexe = 'm';
  return up_forme.replace("comprime",(nb>1)?"comprimés":"comprimé");
 }
 else if(up_forme.contains("comprimé"))
 {sexe = 'm';
  return up_forme.replace("comprimé",(nb>1)?"comprimés":"comprimé");
 }

 return ((nb>1)?up_forme+"s":up_forme);
}

//---------------------------- numberToLiteral ------------------------------------------------
QString C_PosologieGrammar::numberToLiteral(int nb, char sexe /* = 'm' */)
{
 QString ret = "";
 char nompart[10][10]={"dix","onze","douze","treize","quatorze","quinze","seize","dix-sept","dix-huit","dix-neuf"};
 char nomunite[10][10]={"","un","deux","trois","quatre","cinq","six","sept","huit","neuf"};
 char nomdizaine[8][17]={"vingt","trente","quarante","cinquante","soixante","soixante-","quatre-vingt","quatre-vingt-"};
 char nomspe[3][7]={"cent","-et-un","mille"};
 int milliers  = nb/1000;
     nb        = nb%1000;
 int centaines = nb/100;
 int unites    = nb%100;
 int dizaines  = unites/10;
 unites=unites%10;
 if (milliers>1 && milliers<10)       ret += adjustUniteToSexe(nomunite[milliers],sexe)  +" " + QString(nomspe[2])+" ";
 if (milliers==1)                     ret += QString(nomspe[2]) + " ";
 if (centaines>1)
    {                                 ret += adjustUniteToSexe(nomunite[centaines],sexe) +" " + QString(nomspe[0])+" ";
     if ( unites==0 && dizaines==0 )  ret  = ret.left(ret.length()-1);

    }
 if ( centaines==1 )                  ret += QString(nomspe[0]) + " ";
 if ( dizaines>1 && dizaines!=7 && dizaines!=9 )
    {                                 ret += QString(nomdizaine[dizaines-2]);
     if ( dizaines==8 && unites==0 )  ret += QString("s");
     if ( unites>1 )
        {                             ret += "-" + adjustUniteToSexe(nomunite[unites],sexe);
          unites=0;
        }
     if ( unites==1 )
        { unites=0;                   ret += adjustUniteToSexe(nomspe[1],sexe);
        }
    }
 if ( dizaines==1 || dizaines==7 || dizaines==9 )
    {
     if (dizaines==7 || dizaines==9)  ret += QString(nomdizaine[dizaines-2]);
     if (dizaines==7 && unites==1)
        {ret.left(ret.length()-1);    ret += adjustUniteToSexe(nomspe[1],sexe);
         ret.left(ret.length()-2);
        }
                                      ret += QString(nompart[unites]);
     unites=0;
    }
 if (dizaines!=0 && centaines!=0)     ret += " ";
                                      ret += adjustUniteToSexe(nomunite[unites],sexe);
 return ret.trimmed();
}
//---------------------------- adjustUniteToSexe ------------------------------------------------
QString C_PosologieGrammar::adjustUniteToSexe(const QString &unite, char sexe )
{if (unite.contains("un") && sexe=='f') return QString(unite).replace("un","une");
 return unite;
}

//=================== C_BDM_DrugListRecord ===============================================
//---------------------------- serialize ------------------------------------------------
QString C_BDM_DrugListRecord::serialize() const
{return serialize(this);
}

//---------------------------- serialize ------------------------------------------------
QString C_BDM_DrugListRecord::serialize(const C_BDM_DrugListRecord *pC_BDM_DrugListRecord)
{QString modeleXML =
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 "<!-- Projet    : MedinTux                              -->\n"
 "<!-- Module    : medicabase                            -->\n"
 "<!-- Objet     : C_BDM_DrugListRecord                  -->\n"
 "<!-- guru mail : sevin-roland@medintux.org             -->\n"
 "<!-- Copyright : (C) 2004-to-2013 and for the eternity -->\n"
 "<C_BDM_DrugListRecord>\n"
 "   <version>1</version>\n";
      //............................. C_BDM_DrugListRecord ..............................
      CGestIni::addXmlData("m_id",              QByteArray().append(pC_BDM_DrugListRecord->m_id),                         modeleXML,false); //pC_RendezVous->m_date.toString(Qt::ISODate), modeleXML,0);
      CGestIni::addXmlData("m_id_type",         QByteArray().append(pC_BDM_DrugListRecord->m_id_type),                    modeleXML,false);
      CGestIni::addXmlData("m_commercialName",  QByteArray().append(pC_BDM_DrugListRecord->m_commercialName),             modeleXML,false);
      CGestIni::addXmlData("m_dci_1Name",       QByteArray().append(pC_BDM_DrugListRecord->m_dci_1Name),                  modeleXML,false);
      CGestIni::addXmlData("m_dci_2Name",       QByteArray().append(pC_BDM_DrugListRecord->m_dci_2Name),                  modeleXML,false);
      CGestIni::addXmlData("m_dci_3Name",       QByteArray().append(pC_BDM_DrugListRecord->m_dci_3Name),                  modeleXML,false);
      CGestIni::addXmlData("m_owner",           QByteArray().append(pC_BDM_DrugListRecord->m_owner),                      modeleXML,false);
      CGestIni::addXmlData("m_lang",            QByteArray().append(pC_BDM_DrugListRecord->m_lang),                       modeleXML,false);
      CGestIni::addXmlData("m_ucd",             QByteArray().append(pC_BDM_DrugListRecord->m_ucd),                        modeleXML,false);
      CGestIni::addXmlData("m_ucd_price",       QByteArray().append(pC_BDM_DrugListRecord->m_ucd_price),                  modeleXML,false);
      CGestIni::addXmlData("m_generique",       QByteArray().append(pC_BDM_DrugListRecord->m_generique),                  modeleXML,false);
      CGestIni::addXmlData("m_statut",          QByteArray().append(pC_BDM_DrugListRecord->m_statut),                     modeleXML,false);
 modeleXML +=
 "</C_BDM_DrugListRecord>\n";
 return modeleXML;
}
//---------------------------- unSerialize ------------------------------------------------
C_BDM_DrugListRecord *C_BDM_DrugListRecord::unSerialize(const QString & data, C_BDM_DrugListRecord *obj)
{   int nextPos=0;
    //............................. C_BDM_DrugListRecord ..............................
    obj->m_id              = CGestIni::getXmlData("m_id",                 data, &nextPos);
    obj->m_id_type         = CGestIni::getXmlData("m_id_type",            data, &nextPos);
    obj->m_commercialName  = CGestIni::getXmlData("m_commercialName",     data, &nextPos);
    obj->m_dci_1Name       = CGestIni::getXmlData("m_dci_1Name",          data, &nextPos);
    obj->m_dci_2Name       = CGestIni::getXmlData("m_dci_2Name",          data, &nextPos);
    obj->m_dci_3Name       = CGestIni::getXmlData("m_dci_3Name",          data, &nextPos);
    obj->m_owner           = CGestIni::getXmlData("m_owner",              data, &nextPos);
    obj->m_lang            = CGestIni::getXmlData("m_lang",               data, &nextPos);
    obj->m_ucd             = CGestIni::getXmlData("m_ucd",                data, &nextPos);
    obj->m_ucd_price       = CGestIni::getXmlData("m_ucd_price",          data, &nextPos);
    obj->m_generique       = CGestIni::getXmlData("m_generique",          data, &nextPos);
    obj->m_statut          = CGestIni::getXmlData("m_statut",             data, &nextPos);
    return obj;
}

//---------------------------- unSerialize ------------------------------------------------
C_BDM_DrugListRecord C_BDM_DrugListRecord::unSerialize(const QString & data)
{C_BDM_DrugListRecord obj;
 unSerialize(data, &obj);
 return obj;
}

//=================== C_OrdoLineRecord ===============================================================
//---------------------------- serialize ------------------------------------------------
QString C_OrdoLineRecord::serialize() const
{return serialize(this);
}
//---------------------------- serialize ------------------------------------------------
QString C_OrdoLineRecord::serialize(const C_OrdoLineRecord *pC_OrdoLineRecord)
{QString modeleXML =
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 "<!-- Projet    : MedinTux                              -->\n"
 "<!-- Module    : medicabase                            -->\n"
 "<!-- Objet     : C_OrdoLineRecord                      -->\n"
 "<!-- guru mail : sevin-roland@medintux.org             -->\n"
 "<!-- Copyright : (C) 2004-to-2013 and for the eternity -->\n"
 "<C_OrdoLineRecord>\n"
 "   <version>1</version>\n";
      //............................. C_BDM_DrugListRecord ..............................
      CGestIni::addXmlData("m_id",              QByteArray().append(pC_OrdoLineRecord->m_id),                         modeleXML,0); //pC_RendezVous->m_date.toString(Qt::ISODate), modeleXML,0);
      CGestIni::addXmlData("m_id_type",         QByteArray().append(pC_OrdoLineRecord->m_id_type),                    modeleXML,0);
      CGestIni::addXmlData("m_commercialName",  QByteArray().append(pC_OrdoLineRecord->m_commercialName),             modeleXML,0);
      CGestIni::addXmlData("m_dci_1Name",       QByteArray().append(pC_OrdoLineRecord->m_dci_1Name),                  modeleXML,0);
      CGestIni::addXmlData("m_dci_2Name",       QByteArray().append(pC_OrdoLineRecord->m_dci_2Name),                  modeleXML,0);
      CGestIni::addXmlData("m_dci_3Name",       QByteArray().append(pC_OrdoLineRecord->m_dci_3Name),                  modeleXML,0);
      CGestIni::addXmlData("m_owner",           QByteArray().append(pC_OrdoLineRecord->m_owner),                      modeleXML,0);
      CGestIni::addXmlData("m_lang",            QByteArray().append(pC_OrdoLineRecord->m_lang),                       modeleXML,0);
      CGestIni::addXmlData("m_ucd",             QByteArray().append(pC_OrdoLineRecord->m_ucd),                        modeleXML,0);
      CGestIni::addXmlData("m_ucd_price",       QByteArray().append(pC_OrdoLineRecord->m_ucd_price),                  modeleXML,0);
      CGestIni::addXmlData("m_generique",       QByteArray().append(pC_OrdoLineRecord->m_generique),                  modeleXML,0);
      CGestIni::addXmlData("m_statut",          QByteArray().append(pC_OrdoLineRecord->m_statut),                     modeleXML,0);
      //............................. C_OrdoLineRecord ..................................
      CGestIni::addXmlData("m_ordo_key",             QByteArray().append(pC_OrdoLineRecord->m_ordo_key),                         modeleXML,0);
      CGestIni::addXmlData("m_numOrdre",             QByteArray().append(pC_OrdoLineRecord->m_numOrdre),                         modeleXML,0);
      CGestIni::addXmlData("m_secureState",          QByteArray().append(pC_OrdoLineRecord->m_secureState),                      modeleXML,0);
      CGestIni::addXmlData("m_date_debut",           QByteArray().append(pC_OrdoLineRecord->m_date_debut.toString(Qt::ISODate)), modeleXML,0);
      CGestIni::addXmlData("m_date_fin",             QByteArray().append(pC_OrdoLineRecord->m_date_fin.toString(Qt::ISODate)),   modeleXML,0);
      CGestIni::addXmlData("m_pk_patient",           QByteArray().append(pC_OrdoLineRecord->m_pk_patient),                       modeleXML,0);
      CGestIni::addXmlData("m_guid_patient",         QByteArray().append(pC_OrdoLineRecord->m_guid_patient),                     modeleXML,0);
      CGestIni::addXmlData("m_code_indication",      QByteArray().append(pC_OrdoLineRecord->m_code_indication),                  modeleXML,0);
      CGestIni::addXmlData("m_type_code_indication", QByteArray().append(pC_OrdoLineRecord->m_type_code_indication),             modeleXML,0);
      CGestIni::addXmlData("m_smr",                  QByteArray().append(pC_OrdoLineRecord->m_smr),                              modeleXML,0);
      CGestIni::addXmlData("m_smr_indication",       QByteArray().append(pC_OrdoLineRecord->m_smr_indication),                   modeleXML,0);
      CGestIni::addXmlData("m_voie_admin",           QByteArray().append(pC_OrdoLineRecord->m_voie_admin),                       modeleXML,0);
      CGestIni::addXmlData("m_ald",                  QByteArray().append(pC_OrdoLineRecord->m_ald),                              modeleXML,0);
      CGestIni::addXmlData("m_substituable",         QByteArray().append(pC_OrdoLineRecord->m_substituable),                     modeleXML,0);
      CGestIni::addXmlData("m_renouvelable",         QByteArray().append(pC_OrdoLineRecord->m_renouvelable),                     modeleXML,0);
      CGestIni::addXmlData("m_quantite_totale",      QByteArray().append(pC_OrdoLineRecord->m_quantite_totale),                  modeleXML,0);
      CGestIni::addXmlData("m_forme_galenique",      QByteArray().append(pC_OrdoLineRecord->m_forme_galenique),                  modeleXML,0);
      CGestIni::addXmlData("m_unite_de_prise",       QByteArray().append(pC_OrdoLineRecord->m_unite_de_prise),                   modeleXML,0);
      CGestIni::addXmlData("m_quantite_par_up",      QByteArray().append(pC_OrdoLineRecord->m_quantite_par_up),                  modeleXML,0);
      CGestIni::addXmlData("m_unite_quantite",       QByteArray().append(pC_OrdoLineRecord->m_unite_quantite),                   modeleXML,0);
      CGestIni::addXmlData("m_note_textuelle_libre", QByteArray().append(pC_OrdoLineRecord->m_note_textuelle_libre),             modeleXML,0);
      CGestIni::addXmlData("m_schema_posologique",   QByteArray().append(pC_OrdoLineRecord->m_schema_posologique),               modeleXML,0);
 modeleXML +=
 "</C_OrdoLineRecord>\n";
 return modeleXML;
}

//---------------------------- unSerialize ------------------------------------------------
C_OrdoLineRecord *   C_OrdoLineRecord::unSerialize(const QString & data, C_OrdoLineRecord *obj)
{   int nextPos=0;
    //............................. C_BDM_DrugListRecord ..............................
    obj->m_id              = CGestIni::getXmlData("m_id",                 data, &nextPos);
    obj->m_id_type         = CGestIni::getXmlData("m_id_type",            data, &nextPos);
    obj->m_commercialName  = CGestIni::getXmlData("m_commercialName",     data, &nextPos);
    obj->m_dci_1Name       = CGestIni::getXmlData("m_dci_1Name",          data, &nextPos);
    obj->m_dci_2Name       = CGestIni::getXmlData("m_dci_2Name",          data, &nextPos);
    obj->m_dci_3Name       = CGestIni::getXmlData("m_dci_3Name",          data, &nextPos);
    obj->m_owner           = CGestIni::getXmlData("m_owner",              data, &nextPos);
    obj->m_lang            = CGestIni::getXmlData("m_lang",               data, &nextPos);
    obj->m_ucd             = CGestIni::getXmlData("m_ucd",                data, &nextPos);
    obj->m_ucd_price       = CGestIni::getXmlData("m_ucd_price",          data, &nextPos);
    obj->m_generique       = CGestIni::getXmlData("m_generique",          data, &nextPos);
    obj->m_statut          = CGestIni::getXmlData("m_statut",             data, &nextPos);
if (data.indexOf("<C_OrdoLineRecord>") != -1)    //.... si le xml est celui d'une ordonnance complete exploiter le xml
   {
    //............................. C_OrdoLineRecord ..................................
    obj->m_ordo_key             = CGestIni::getXmlData("m_ordo_key",                         data, &nextPos);
    obj->m_numOrdre             = CGestIni::getXmlData("m_numOrdre",                         data, &nextPos);
    obj->m_secureState          = CGestIni::getXmlData("m_secureState",                      data, &nextPos);
    obj->m_date_debut           = QDateTime::fromString(CGestIni::getXmlData("m_date_debut", data, &nextPos),Qt::ISODate);
    obj->m_date_fin             = QDateTime::fromString(CGestIni::getXmlData("m_date_fin",   data, &nextPos),Qt::ISODate);
    obj->m_pk_patient           = CGestIni::getXmlData("m_pk_patient",                       data, &nextPos);
    obj->m_guid_patient         = CGestIni::getXmlData("m_guid_patient",                     data, &nextPos);
    obj->m_code_indication      = CGestIni::getXmlData("m_code_indication",                  data, &nextPos);
    obj->m_type_code_indication = CGestIni::getXmlData("m_type_code_indication",             data, &nextPos);
    obj->m_smr                  = CGestIni::getXmlData("m_smr",                              data, &nextPos);
    obj->m_smr_indication       = CGestIni::getXmlData("m_smr_indication",                   data, &nextPos);
    obj->m_voie_admin           = CGestIni::getXmlData("m_voie_admin",                       data, &nextPos);
    obj->m_ald                  = CGestIni::getXmlData("m_ald",                              data, &nextPos);
    obj->m_substituable         = CGestIni::getXmlData("m_substituable",                     data, &nextPos);
    obj->m_renouvelable         = CGestIni::getXmlData("m_renouvelable",                     data, &nextPos);
    obj->m_quantite_totale      = CGestIni::getXmlData("m_quantite_totale",                  data, &nextPos);
    obj->m_forme_galenique      = CGestIni::getXmlData("m_forme_galenique",                  data, &nextPos);
    obj->m_unite_de_prise       = CGestIni::getXmlData("m_unite_de_prise",                   data, &nextPos);
    obj->m_quantite_par_up      = CGestIni::getXmlData("m_quantite_par_up",                  data, &nextPos);
    obj->m_note_textuelle_libre = CGestIni::getXmlData("m_note_textuelle_libre",             data, &nextPos);
    obj->m_schema_posologique   = CGestIni::getXmlData("m_schema_posologique",               data, &nextPos);
   }
else //.... si le xml est incomplet (celui d'une C_BDM_DrugListRecord) alors completer avec l'API exploiter le xml
   {obj->set_ordo_key("")                  ;
    obj->set_numOrdre("")                  ;
    obj->set_secureState("")               ;
    //obj->set_date_debut("")                ;
    //obj->set_date_fin( "")                 ;
    obj->set_pk_patient("")                ;
    obj->set_guid_patient("")              ;
    obj->set_code_indication("")           ;
    obj->set_type_code_indication("")      ;
    obj->set_smr("")                       ;
    obj->set_smr_indication("")            ;
    obj->set_voie_admin("")                ;
    obj->set_ald("")                       ;
    obj->set_substituable("")              ;
    obj->set_renouvelable("")              ;
    obj->set_quantite_totale("")           ;
    obj->set_forme_galenique("")           ;
    obj->set_unite_de_prise("")            ;
    obj->set_quantite_par_up("")           ;
    obj->set_unite_quantite("")            ;
    obj->set_note_textuelle_libre("")      ;
    obj->set_schema_posologique("")        ;

   }
    return obj;
}

//---------------------------- unSerialize ------------------------------------------------
C_OrdoLineRecord C_OrdoLineRecord::unSerialize(const QString & data)
{C_OrdoLineRecord obj;
 unSerialize(data, &obj);
 return obj;
}

//=================== C_BDM_PluginI ===================================
C_BDM_PluginI::C_BDM_PluginI(const QString &confData, QObject *parent /*=0 */, QTextEdit *logWidget /* =0*/)
{m_isInitialised     = 0;
}
//--------------------------------------------- ~C_BDM_PluginI -------------------------------------------------------------------
/*! \brief destructor  C_BDM_PluginI
*/
C_BDM_PluginI::~C_BDM_PluginI()
{m_isInitialised     = 0;
}

//-------------------------------- isInitialised ------------------------------------------------------
int C_BDM_PluginI::isInitialised()
{return m_isInitialised;
}

//-------------------------------- setInitialisedSate ------------------------------------------------------
void C_BDM_PluginI::setInitialisedSate(int state)
{m_isInitialised = state;
}

//================================ C_BDM_Api ==========================================================================
//-------------------------------- C_BDM_Api ------------------------------------------------------
/*! \brief constructor
 *  \param const QString   &confData: fields definitions.
 *  \param const QString   &params    connexions parameters.
 *  \param C_BDM_PluginI   *pC_BDM_PluginI pointer on drugs datas serveur.
 *  \param QObject         *parent         pointer QObject parent.
*/
C_BDM_Api::C_BDM_Api( const QString   &confData,                        // definition des champs de la base de donnée (ceux de la liste des drogues)
                      const QString   &params ,                         // parametres de connexion a la base de données
                      C_BDM_PluginI   *pC_BDM_PluginI,                  // pointeur sur le pC_BDM_PluginI serveur de donnees
                      QObject         *parent            /* = 0 */      // objet parent
                    )
: C_BaseCommon(parent), C_BDM_ApiVar( confData)
{m_pC_BDM_PluginI                = pC_BDM_PluginI;
 m_isValid                       = 0;
 m_DrugListNb                    = 0;
 m_pQSqlQuery                    = 0;
 m_firstTimeGetNextSmrInfoForCIP = TRUE;
 if ( connectBase(params)==0 )                                  {m_isValid = 0; return;}
 if ( connectToDataSource( pC_BDM_PluginI )==0)                 {m_isValid = 0; return;}
 m_isValid = 1;
}

//-------------------------------- ~C_BDM_Api ------------------------------------------------------
/*! \brief destructor  C_BDM_Api
*/
C_BDM_Api::~C_BDM_Api()
{if (m_pQSqlQuery)     delete m_pQSqlQuery;
}

//-------------------------------- connectToDataSource ------------------------------------------------------
/*! \brief connect API to source datas via C_BDM_InitPluginI interface which provides data to  C_BDM_Api
 *  \param C_BDM_InitPluginI *pC_BDM_InitPluginI: data interface which provides data to  C_BDM_Api.
 *  \return true in all is ok otherwise false (0)
 */
int C_BDM_Api::connectToDataSource( C_BDM_PluginI *pC_BDM_PluginI)
{m_DrugListNb = 0;
 if ( !pC_BDM_PluginI->isInitialised() ) return 0;
 m_pC_BDM_PluginI = pC_BDM_PluginI;
 if (pC_BDM_PluginI->dataSourceVersion() != dataSourceVersion())
    { if ( updateDrugLists(pC_BDM_PluginI)==0 )       return 0;
    }
 m_DrugListNb = drugsList_Count();
 return 1;
}

//-------------------------------- isValid ------------------------------------------------------
/*! \brief return validation state of this class. if no valid the class can't works
 */
int C_BDM_Api::isValid()
{return m_isValid;
}

//-------------------------------- drugsList_Size ------------------------------------------------------
/*! \brief return size of drugs list. This return only cache value and proceed to no SQL opération
 */
int  C_BDM_Api::drugsList_Size()
{return m_DrugListNb;
}

//-------------------------------- drugsList_Count ------------------------------------------------------
/*! \brief return size of drugs list. proceed to SQL opération and set cache list number.
 */
int C_BDM_Api::drugsList_Count()
{if (!database().isOpen() && database().open()== FALSE)
    {outMessage( tr("ERREUR : C_BDM_Api::drugsList_Count() database can not be opened"), __FILE__, __LINE__);  return 0;
    }
 return countRecords(m_BDM_DRUGLIST_TBL_NAME);
}

//------------------------ selectProductsList -----------------------------------------
/*! \brief select drugs list from user input, for a good performance response a rapid special drugs list is implemented
 *  this list is to update each news datas base source versions datas. We proceed update if
 * m_DatasSourceVersion differs from pC_BDM_PluginI->dataSourceVersion();
 *  \param const QString textSelect user text fr select drugs.
 *  \param C_BDM_Api::flags filterFlag selection filter.
 *  \return QList < C_BDM_DrugListRecord >  list of C_BDM_DrugListRecord  results
 */
const QList < C_BDM_DrugListRecord > C_BDM_Api::selectProductsList (const QString &text, C_BDM_Api::flags filterFlag  /* = C_BDM_Api::all_filter */ )
{QList < C_BDM_DrugListRecord > productsList;
 if (!database().isOpen() && database().open()== FALSE)
    {outMessage( tr("ERREUR : C_BDM_Api::selectProductsList() database can not be opened"), __FILE__, __LINE__);  return productsList;
    }
 QString requete = makeSelectProductsListQuery(text, filterFlag);
 productsList.clear();
 QSqlQuery query (requete , database() );
 outSQL_error( query, "ERREUR  : C_BDM_Api::selectProductsList()", requete, __FILE__, __LINE__);
 if (query.isActive() )
    {while (query.next())
           {productsList.append( C_BDM_DrugListRecord(query.value(2).toString(),
                                                      query.value(3).toString(),
                                                      query.value(5).toString(),
                                                      query.value(6).toString(),
                                                      query.value(7).toString(),
                                                      query.value(8).toString(),
                                                      query.value(0).toString(),
                                                      query.value(1).toString(),
                                                      query.value(9).toString(),
                                                      query.value(10).toString(),
                                                      query.value(4).toString(),
                                                      query.value(11).toString(),
                                                      query.value(12).toString())
                               );
           }    // end while (query.next())
    }  // endif (query.isActive() )
 return productsList;
}

//-------------------------------- makeSelectProductsListQuery --------------------------------------------
/*! \brief make select query to select drugs list from user input, for a good performance
 *  response a rapid special drugs list is implemented
 *  this list is to update each news datas base source versions datas. We proceed update if
 *  m_DatasSourceVersion differs from pC_BDM_PluginI->dataSourceVersion();
 *  \param const QString textSelect user text fr select drugs.
 *  \param C_BDM_Api::flags filterFlag selection filter.
 *  \return query result string
 */

QString C_BDM_Api::makeSelectProductsListQuery(const    QString &text, C_BDM_Api::flags filterFlag)
{QString        requete =         " SELECT "
                                  "`"+m_BDM_DRUGLIST_OWNER     +"`,"     // 0
                                  "`"+m_BDM_DRUGLIST_LANG      +"`,"     // 1
                                  "`"+m_BDM_DRUGLIST_ID        +"`,"     // 2
                                  "`"+m_BDM_DRUGLIST_TYPE_ID   +"`,"     // 3
                                  "`"+m_BDM_DRUGLIST_ATC       +"`,"     // 4
                                  "`"+m_BDM_DRUGLIST_LIBELLE   +"`,"     // 5
                                  "`"+m_BDM_DRUGLIST_DCI_1     +"`,"     // 6
                                  "`"+m_BDM_DRUGLIST_DCI_2     +"`,"     // 7
                                  "`"+m_BDM_DRUGLIST_DCI_3     +"`,"     // 8
                                  "`"+m_BDM_DRUGLIST_UCD       +"`,"     // 9
                                  "`"+m_BDM_DRUGLIST_UCD_PRICE +"`,"     // 10
                                  "`"+m_BDM_DRUGLIST_GENERIQUE +"`,"     // 11
                                  "`"+m_BDM_DRUGLIST_STATUT    +"`,"     // 12
                                  "`"+m_BDM_DRUGLIST_SPEC_FK   +"` "     // 13
                                  " FROM "+m_BDM_DRUGLIST_TBL_NAME;
 if (text.length())
    {requete  +=  QString(" WHERE (");
     if (filterFlag&C_BDM_Api::nom_filter)  requete  += m_BDM_DRUGLIST_LIBELLE     + " LIKE \"%1%\" OR ";
     if (filterFlag&C_BDM_Api::atc_filter)  requete  += m_BDM_DRUGLIST_ATC         + " LIKE \"%1%\" OR ";
     if (filterFlag&C_BDM_Api::dci_filter)  requete  += m_BDM_DRUGLIST_DCI_1       + " LIKE \"%1%\" OR ";
     if (filterFlag&C_BDM_Api::cip_filter)  requete  += m_BDM_DRUGLIST_ID          + " LIKE \"%1%\" OR ";
     if (filterFlag&C_BDM_Api::dc3_filter)  requete  += m_BDM_DRUGLIST_DCI_2       + " LIKE \"%1%\" OR " + m_BDM_DRUGLIST_DCI_3 + " LIKE \"%1%\" OR ";
     requete.chop(4);                                // virer le dernier " OR "
     requete  += ") ";                               // fermer la parenthese du WHERE
     requete   = requete.arg(text.toUpper());        // placer les caracteres de l'utilisateur
     if (filterFlag&C_BDM_Api::gen_filter) {requete  +=  " AND (" + m_BDM_DRUGLIST_GENERIQUE   + " IN ('G','R')) ";}
     if (filterFlag&C_BDM_Api::vil_filter && filterFlag&C_BDM_Api::hop_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'VH' OR " + m_BDM_DRUGLIST_STATUT + " = 'H') ";}
     else if (filterFlag&C_BDM_Api::vil_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'VH'         ) ";}
     else if (filterFlag&C_BDM_Api::hop_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'H'         ) ";}
     requete  += ownersSelectMention(m_BDM_DRUGLIST_TBL_NAME, C_BaseCommon::WhereAlreadyIn);  // rajouter le filtre du proprio
     if (filterFlag&C_BDM_Api::ucd_filter)  requete  +=  " ORDER BY " + m_BDM_DRUGLIST_UCD_PRICE;
    }
 else
    {
     requete  += ownersSelectMention(m_BDM_DRUGLIST_TBL_NAME, C_BaseCommon::WhereMustBeAdd);
     if (filterFlag&C_BDM_Api::gen_filter)  requete  +=  " AND (" + m_BDM_DRUGLIST_GENERIQUE   + " IN ('G','R')) ";
     if (filterFlag&C_BDM_Api::vil_filter && filterFlag&C_BDM_Api::hop_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'VH' OR " + m_BDM_DRUGLIST_STATUT + " = 'H') ";}
     else if (filterFlag&C_BDM_Api::vil_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'VH'        ) ";}
     else if (filterFlag&C_BDM_Api::hop_filter)
                                           {requete  +=  " AND (" + m_BDM_DRUGLIST_STATUT      + " = 'H'         ) ";}
     if (filterFlag&C_BDM_Api::ucd_filter)  requete  +=  " ORDER BY " + m_BDM_DRUGLIST_UCD_PRICE;
    }
  return requete;
}

//-------------------------------- selectProductsList ------------------------------------------------------
/*! \brief select drugs list from user input, for a good performance response a rapid special drugs list is implemented
 *  this list is to update each news datas base source versions datas. We proceed update if
 * m_DatasSourceVersion differs from pC_BDM_PluginI->dataSourceVersion();
 *  \param QTreeWidget *pQTreeWidget: QTreeWidget to fill with datas.
 *  \param const QString textSelect user text fr select drugs.
 *  \param C_BDM_Api::flags filterFlag selection filter.
 *  \return number products
 */
int  C_BDM_Api::selectProductsList(QTreeWidget     *pQTreeWidget,                                    // QTreeWidget graphique à renseigner avec les données
                                   const    QString text          /* = ""  */,                       // saisie partielle d'un texte pour recherche
                                   C_BDM_Api::flags filterFlag    /* = C_BDM_Api::all_filter */      // filtre de saisie
                                  )
{
    pQTreeWidget->clear();
    if (m_isValid==0) return 0;
    if (!database().isOpen() && database().open()== FALSE)
       {outMessage( tr("ERREUR : C_BDM_Api::selectProductsList() database can not be opened"), __FILE__, __LINE__);  return 0;
       }
    QTreeWidgetItem *item  = 0;
    QString        requete = makeSelectProductsListQuery(text, filterFlag);
    QSqlQuery query (requete , database() );
    outSQL_error( query, "ERREUR  : C_BDM_Api::selectProductsList()", requete, __FILE__, __LINE__);
    if (query.isActive() )
       {while (query.next())
              {item =   new QTreeWidgetItem (pQTreeWidget);
               item->setText(0,CGestIni::Utf8_Query(query, 5));   // libelle
               item->setText(1,query.value(6).toString());        // DCI_1
               item->setText(2,query.value(7).toString());        // DCI_2
               item->setText(3,query.value(8).toString());        // DCI_3
               QString prix = query.value(10).toString();
               item->setText(4,prix.insert(prix.length()-2,'.')); // Prix
               item->setText(5,query.value(4).toString());        // ATC
               item->setText(6,query.value(2).toString());        // ID CIP
               item->setText(11,query.value(11).toString());      // generique
               item->setText(12,query.value(12).toString());      // statut
              }    // end while (query.next())
       }  // endif (query.isActive() )
    return pQTreeWidget->topLevelItemCount();
}
//-------------------------------- selectPosologieHitList ------------------------------------------------------
/*! \brief select drugs posologies hits list from drug code
 *  \param const QString &drug_id : as variable name shows, it's drug identification key.
 *  \param const QString &drug_id_type : as variable name shows, it's drug identification key type.
 *  \param int limit : limit number of returns.
 *  \return QMap <int, QString> where int is order number and QString is grammar string started by 'cip/pk!' mention
 */
QStringList  C_BDM_Api::selectPosologieHitList(const QString &drug_id, const QString &drug_id_type /* = "CIP" */, int limit /* = 15  */)
{   QStringList listResult;
    if (m_isValid==0) return listResult;
    if (!database().isOpen() && database().open()== FALSE)
       {outMessage( tr("ERREUR : C_BDM_Api::selectPosologieHitList() database can not be opened"), __FILE__, __LINE__);  return listResult;
       }
    int     pos      = -1;
    int     score    = 0;
    QString grammar  = "";
    QString pk_score = "";
    QString  requete = " SELECT "
                       "`"           + m_BDM_POSO_HIT_PK            +"`,"     // 0
                       "`"           + m_BDM_POSO_HIT_SCORE         +"`,"     // 1
                       "`"           + m_BDM_POSO_HIT_GRAMMAR       +"` "     // 2
                       " FROM  "     + m_BDM_POSO_HIT_TBL_NAME      +
                       " WHERE "     + m_BDM_POSO_HIT_DRUG_ID       + " = '" + drug_id       + "' "
                       " AND   "     + m_BDM_POSO_HIT_DRUG_TYPE_ID  + " = '" + drug_id_type  + "' "
                       " ORDER BY `" + m_BDM_POSO_HIT_SCORE         + "` DESC LIMIT "        + QString::number(limit);

    QSqlQuery query (requete , database() );
    outSQL_error( query, "ERREUR  : C_BDM_Api::selectPosologieHitList()", requete, __FILE__, __LINE__);
    if (query.isActive() )
       {while (query.next())
              {pk_score = query.value(0).toString();                 // m_BDM_POSO_HIT_PK
               score    = query.value(1).toInt();                    // m_BDM_POSO_HIT_SCORE
               grammar  = CGestIni::Utf8_Query(query, 2);            // m_BDM_POSO_HIT_GRAMMAR
               //...... on coupe si besoin la mention pk/cip ...........
               pos      = grammar.indexOf('!');
               if (pos != -1) grammar = grammar.mid(pos+1);
               //....... on rajoute la mention  pk/cip .............................
               if (score<0 )  listResult.prepend( grammar.prepend(pk_score+"/"+drug_id+"!") );
               else           listResult.append(  grammar.prepend(pk_score+"/"+drug_id+"!") );
              }    // end while (query.next())
       }  // endif (query.isActive() )
    return listResult;
}
//-------------------------------- increasePosologieHit ------------------------------------------------------
/*! \brief increase a posologie drug hit parade adjusted in real time of use. Create record only if not exists.
 *  \param const QString &grammar :     grammar input string as
 *  "345687/123!ALL_LITERAL=comprimé[1;m|2;M|4;s]/8\n[0.5;m|1;M15r|2;sr30|3;h10-13]/4\n[0.5;m|1;s]/3".
 *  where cip code is 345687 and if present facultative pk code 123 after '/' symbol.
 *  \param const QString &drug_id : as variable name shows, it's drug identification key.
 *  \param const QString &drug_id_type : as variable name shows, it's drug identification key type.
 *  \param int mode  default = INCREASE_HIT/increase hit  else FIX_HIT add the posologie whith fix hit.
 *  \return true in all is ok otherwise false
 */
int C_BDM_Api::increasePosologieHit(const QString &grammar, const QString &drug_id, const QString &drug_id_type /* = "CIP" */,  int mode  /* = INCREASE_HIT */)
{
    if (m_isValid==0) return 0;
    if (!database().isOpen() && database().open()== FALSE)
       {outMessage( tr("ERREUR : C_BDM_Api::increasePosologieHit() database can not be opened"), __FILE__, __LINE__);  return 0;
       }
    QString pk      = "";  C_PosologieGrammar::get_cip_pk(grammar, &pk );   // recuperer si cette posologie n'est pas deja pourvue d'un pk auquelcas c'ent est une deja existante
    QString prepare = "";
    int     hit     = 0;
    QSqlQuery query(QString::null , database() );

    //......................... on renseigne la liste ...................................
    if (pk.length()==0)
       {  prepare  =   (" INSERT INTO "+m_BDM_POSO_HIT_TBL_NAME+"( \n"
                        "`"+m_BDM_POSO_HIT_OWNER               +"`,\n"     // 0
                        "`"+m_BDM_POSO_HIT_LANG                +"`,\n"     // 1
                        "`"+m_BDM_POSO_HIT_SCORE               +"`,\n"     // 2
                        "`"+m_BDM_POSO_HIT_GRAMMAR             +"`,\n"     // 3
                        "`"+m_BDM_POSO_HIT_ORDER               +"`,\n"     // 4
                        "`"+m_BDM_POSO_HIT_CODE_INDIC          +"`,\n"     // 5
                        "`"+m_BDM_POSO_HIT_CODE_INDIC_TYPE     +"`,\n"     // 6
                        "`"+m_BDM_POSO_HIT_LIBELLE_INDIC       +"`,\n"     // 7
                        "`"+m_BDM_POSO_HIT_DRUG_ID             +"`,\n"     // 8
                        "`"+m_BDM_POSO_HIT_DRUG_TYPE_ID        +"` \n"     // 9
                        ") VALUES (?,?,?,?,?,?,?,?,?,?)\n");
          if (mode==C_BDM_Api::INCREASE_HIT) hit =  1;
          else                               hit = -1;
       }
    else
       {
          prepare   = " UPDATE " + m_BDM_POSO_HIT_TBL_NAME    + " SET   \n"
                      " `"+m_BDM_POSO_HIT_OWNER               +"` = ? ,\n"     // 0
                      " `"+m_BDM_POSO_HIT_LANG                +"` = ? ,\n"     // 1
                      " `"+m_BDM_POSO_HIT_SCORE               +"` = ? ,\n"     // 2
                      " `"+m_BDM_POSO_HIT_GRAMMAR             +"` = ? ,\n"     // 3
                      " `"+m_BDM_POSO_HIT_ORDER               +"` = ? ,\n"     // 4
                      " `"+m_BDM_POSO_HIT_CODE_INDIC          +"` = ? ,\n"     // 5
                      " `"+m_BDM_POSO_HIT_CODE_INDIC_TYPE     +"` = ? ,\n"     // 6
                      " `"+m_BDM_POSO_HIT_LIBELLE_INDIC       +"` = ? ,\n"     // 7
                      " `"+m_BDM_POSO_HIT_DRUG_ID             +"` = ? ,\n"     // 8
                      " `"+m_BDM_POSO_HIT_DRUG_TYPE_ID        +"` = ?  \n"     // 9
                      " WHERE "   + m_BDM_POSO_HIT_PK         +"  =   '"  + pk  + "'\n";
         //......... recuperer la valeur absolue du hit .................................
         hit = qAbs(isThisValueInTable(m_BDM_POSO_HIT_TBL_NAME, m_BDM_POSO_HIT_PK, pk, m_BDM_POSO_HIT_SCORE,"NO-OWNER-FILTER").toInt()) + 1;
         //......... si mode durci on incremente quand meme et on met en negatif .....................................................
         if ( mode!=C_BDM_Api::INCREASE_HIT )
            {hit  = -hit;
            }
       }
    //...... on coupe si besoin la mention pk/cip ...........
    int pos      = grammar.indexOf('!');

    query.prepare(prepare);
    query.bindValue(0, "BDM");
    query.bindValue(1, "fr");
    query.bindValue(2, QString::number(hit));
    query.bindValue(3, (pos == -1) ? grammar : grammar.mid(pos+1));
    query.bindValue(4, "0");
    query.bindValue(5, "");
    query.bindValue(6, "");
    query.bindValue(7, drug_id);
    query.bindValue(8, drug_id_type);

    if ( !query.exec())
       { outSQL_error( query, "ERREUR  : C_BDM_Api::increasePosologieHit() queryInsert", prepare, __FILE__, __LINE__);
         return 0;
       }
    return 1;
}

//-------------------------------- createPosologieHit ------------------------------------------------------
/*! \brief this table records a posologie drug hit parade adjusted in real time of use.
 *  \param int mode  default = ONLY_IF_NOT_EXISTS/create table only if not exists, otherwise create table even if exists.
 *  \return true in all is ok otherwise false
 */
int C_BDM_Api::createPosologieHit(int mode  /* = ONLY_IF_NOT_EXISTS */)
{
    if (!database().isOpen() && database().open()== FALSE)
       {outMessage( tr("ERREUR : C_BDM_Api::createPosologieHit() database can not be open"), __FILE__, __LINE__);  return 0;
       }
    //....................... on cree la table ......................................
    if (mode == C_BDM_Api::ONLY_IF_NOT_EXISTS && isThisTableExist(m_BDM_POSO_HIT_TBL_NAME)!=-1 ) return 1; // si exite on ne fait rien
    if (dropTable  (  m_BDM_POSO_HIT_TBL_NAME )==0)                                              return 0; // on la detruit
    if (createTable("CREATE TABLE `"+m_BDM_POSO_HIT_TBL_NAME+"` ("                             // nom de la table de la table des favoris lies a un medicament
                    "`"+m_BDM_POSO_HIT_PK              +"` BIGINT  NOT NULL AUTO_INCREMENT,"   // clef primaire
                    "`"+m_BDM_POSO_HIT_OWNER           +"` VARCHAR(40)  ,"                     // Origine des donnees (AFSSAPS, Vidal, Theriaque Claude Bernard, perso...)
                    "`"+m_BDM_POSO_HIT_LANG            +"` VARCHAR(4)   ,"                     // langue de la donnee (en fr etc...)
                    "`"+m_BDM_POSO_HIT_SCORE           +"` BIGINT       ,"                     // niveau du hit (nombre d'utilisation sera utilise pour son classement)
                    "`"+m_BDM_POSO_HIT_GRAMMAR         +"` VARCHAR(512) ,"                     // grammaire de la posologie liee a ce favoris
                    "`"+m_BDM_POSO_HIT_ORDER           +"` BIGINT       ,"                     // ordre rigidifie du hit donne la position du favori quelque soit son score
                    "`"+m_BDM_POSO_HIT_CODE_INDIC      +"` VARCHAR(10)  ,"                     // codage de l'indications liees a ce hit
                    "`"+m_BDM_POSO_HIT_CODE_INDIC_TYPE +"` VARCHAR(60)  ,"                     // type de codage CIM10 etc ....
                    "`"+m_BDM_POSO_HIT_LIBELLE_INDIC   +"` VARCHAR(256) ,"                     // libelle de l'indication principale liee a ce hit
                    "`"+m_BDM_POSO_HIT_DRUG_ID         +"` VARCHAR(40)  ,"                     // identificateur unique du medicament relie à ce hit
                    "`"+m_BDM_POSO_HIT_DRUG_TYPE_ID    +"` VARCHAR(8)   ,"                     // type d'identificateur de l'id du medicament (CIP CIP7 CIS)
                    "PRIMARY KEY (`"+m_BDM_POSO_HIT_PK+"`)"
                    ")"
                    )==0) return 0;
    return 1;
}

//-------------------------------- updateDrugLists ------------------------------------------------------
/*! \brief for a good performance response a rapid special drugs list is implemented
 *  this list is to update each news datas base source versions datas. We proceed update if
 *  m_DatasSourceVersion differs from pC_BDM_PluginI->dataSourceVersion();
 *  \return true in all is ok otherwise false
 */
bool C_BDM_Api::updateDrugLists(C_BDM_PluginI *pC_BDM_PluginI)
{
    if (pC_BDM_PluginI==0)                                        return 0;
    if (pC_BDM_PluginI->getDrugList_Start()==0)                   return 0;
    if (!database().isOpen() && database().open()== FALSE)
       {outMessage( tr("ERREUR : C_BDM_Api::updateDrugLists() database can not be open"), __FILE__, __LINE__);  return 0;
       }
    //....................... on cree la table ......................................
    if (dropTable(  m_BDM_VERSION_TBL_NAME)==0) return 0;
    if (createTable("CREATE TABLE `"+m_BDM_VERSION_TBL_NAME+"` ("
                    "`"+m_BDM_VERSION_PK        +"` BIGINT  NOT NULL AUTO_INCREMENT,"
                    "`"+m_BDM_VERSION_OWNER     +"` VARCHAR(40) ,"
                    "`"+m_BDM_VERSION_LANG      +"` VARCHAR(4)  ,"
                    "`"+m_BDM_VERSION_NUMBER    +"` VARCHAR(120) ,"
                    "PRIMARY KEY (`"+m_BDM_VERSION_PK+"`)"
                    ")"
                    )==0) return 0;

    //....................... on cree la table ......................................
    if (dropTable(  m_BDM_DRUGLIST_TBL_NAME)==0) return 0;
    if (createTable("CREATE TABLE `"+m_BDM_DRUGLIST_TBL_NAME+"` ("
                    "`"+m_BDM_DRUGLIST_PK        +"` BIGINT  NOT NULL AUTO_INCREMENT,"
                    "`"+m_BDM_DRUGLIST_OWNER     +"` VARCHAR(40) ,"
                    "`"+m_BDM_DRUGLIST_LANG      +"` VARCHAR(4)  ,"
                    "`"+m_BDM_DRUGLIST_ID        +"` VARCHAR(40) ,"
                    "`"+m_BDM_DRUGLIST_TYPE_ID   +"` VARCHAR(8)  ,"
                    "`"+m_BDM_DRUGLIST_ATC       +"` VARCHAR(7)  ,"
                    "`"+m_BDM_DRUGLIST_LIBELLE   +"` VARCHAR(128),"
                    "`"+m_BDM_DRUGLIST_DCI_1     +"` VARCHAR(128),"
                    "`"+m_BDM_DRUGLIST_DCI_2     +"` VARCHAR(128),"
                    "`"+m_BDM_DRUGLIST_DCI_3     +"` VARCHAR(128),"
                    "`"+m_BDM_DRUGLIST_UCD       +"` VARCHAR(7)  ,"
                    "`"+m_BDM_DRUGLIST_UCD_PRICE +"` BIGINT      ,"
                    "`"+m_BDM_DRUGLIST_GENERIQUE +"` VARCHAR(1)  ,"
                    "`"+m_BDM_DRUGLIST_STATUT    +"` VARCHAR(100)  ,"
                    "`"+m_BDM_DRUGLIST_SPEC_FK   +"` BIGINT      ,"
                    "PRIMARY KEY (`"+m_BDM_DRUGLIST_PK+"`)"
                    ")"
                    )==0) return 0;

    long nbRecordsToParse = pC_BDM_PluginI->drugsList_Count();
    outMessage(  tr("Nb records <font color=#00c0ff>%1</font> : <font color=#00ffff>%2</font>").arg(m_BDM_DRUGLIST_TBL_NAME,QString::number(nbRecordsToParse)));
    long position         = 0;
    if (m_pQProgressBar) m_pQProgressBar->setRange(0, nbRecordsToParse/10);

    //......................... on renseigne la liste ...................................
    QString prepare  =              (" INSERT INTO "+m_BDM_DRUGLIST_TBL_NAME+"( "
                                     "`"+m_BDM_DRUGLIST_OWNER     +"`,"     // 0
                                     "`"+m_BDM_DRUGLIST_LANG      +"`,"     // 1
                                     "`"+m_BDM_DRUGLIST_ID        +"`,"     // 2
                                     "`"+m_BDM_DRUGLIST_TYPE_ID   +"`,"     // 3
                                     "`"+m_BDM_DRUGLIST_ATC       +"`,"     // 4
                                     "`"+m_BDM_DRUGLIST_LIBELLE   +"`,"     // 5
                                     "`"+m_BDM_DRUGLIST_DCI_1     +"`,"     // 6
                                     "`"+m_BDM_DRUGLIST_DCI_2     +"`,"     // 7
                                     "`"+m_BDM_DRUGLIST_DCI_3     +"`,"     // 8
                                     "`"+m_BDM_DRUGLIST_UCD       +"`,"     // 9
                                     "`"+m_BDM_DRUGLIST_UCD_PRICE +"`,"     // 10
                                     "`"+m_BDM_DRUGLIST_GENERIQUE +"`,"     // 11
                                     "`"+m_BDM_DRUGLIST_STATUT    +"`,"     // 12
                                     "`"+m_BDM_DRUGLIST_SPEC_FK   +"` "     // 13
                                     ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
    C_BDM_DrugListRecord c_bdm_druglistrecord;
    QSqlQuery queryInsert(QString::null , database() );
    while (pC_BDM_PluginI->getDrugList_NextRecord(c_bdm_druglistrecord))
        {queryInsert.prepare(prepare);
         queryInsert.bindValue(0,  c_bdm_druglistrecord.owner());
         queryInsert.bindValue(1,  c_bdm_druglistrecord.lang());
         queryInsert.bindValue(2,  c_bdm_druglistrecord.id());
         queryInsert.bindValue(3,  c_bdm_druglistrecord.id_type());
         queryInsert.bindValue(4,  c_bdm_druglistrecord.atc());
         queryInsert.bindValue(5,  c_bdm_druglistrecord.commercialName());
         queryInsert.bindValue(6,  c_bdm_druglistrecord.dci_1Name());
         queryInsert.bindValue(7,  c_bdm_druglistrecord.dci_2Name());
         queryInsert.bindValue(8,  c_bdm_druglistrecord.dci_3Name());
         queryInsert.bindValue(9,  c_bdm_druglistrecord.ucd());
         queryInsert.bindValue(10, c_bdm_druglistrecord.ucd_price());
         queryInsert.bindValue(11, c_bdm_druglistrecord.generique());
         queryInsert.bindValue(12, c_bdm_druglistrecord.statut());
         queryInsert.bindValue(13, "");                                // pour l'instant les spec son vides
         if ( !queryInsert.exec())
            { outSQL_error( queryInsert, "ERREUR  : C_BDM_Api::updateDrugLists() queryInsert", prepare, __FILE__, __LINE__);
              return 0;
            }
        ++position;
        if (m_pQProgressBar)  {m_pQProgressBar->setValue(position/10); qApp->processEvents();qApp->processEvents();}
        }
     //.......................... numero de version ..........................................
     prepare  =              (" INSERT INTO "+m_BDM_VERSION_TBL_NAME+" ( "
                              "`"+m_BDM_VERSION_OWNER     +"`,"     // 0
                              "`"+m_BDM_VERSION_LANG      +"`,"     // 1
                              "`"+m_BDM_VERSION_NUMBER    +"` "     // 2
                             ") VALUES (?,?,?)");

    QSqlQuery queryVersion(QString::null , database() );
    queryVersion.prepare(prepare);
    queryVersion.bindValue(0,  m_pC_BDM_PluginI->owner());
    queryVersion.bindValue(1,  m_pC_BDM_PluginI->lang());
    queryVersion.bindValue(2,  m_pC_BDM_PluginI->dataSourceVersion());
    if ( !queryVersion.exec())
       {outSQL_error( queryVersion, "ERREUR  : C_BDM_Api::updateDrugLists() queryVersion", prepare, __FILE__, __LINE__);
        return 0;
       }
    return 1;
}

//-------------------------------- dataSourceVersion ------------------------------------------------------
/*! \brief return datasource version
 */
QString C_BDM_Api::dataSourceVersion()
{   QSqlQuery query(QString::null , database() );
    QString version  = "";
    QString requete  =  QString (" SELECT %1 FROM %2 "
                                 " WHERE  %3  = \"%4\" ").arg( m_BDM_VERSION_NUMBER, m_BDM_VERSION_TBL_NAME, m_BDM_VERSION_OWNER, m_pC_BDM_PluginI->owner());
    if (!query.exec(requete))
       {outSQL_error( query, "ERREUR  : C_BDM_Api::dataSourceVersion()", requete, __FILE__, __LINE__);
        return QString::null;
       }
    if (query.isActive() )
        {while(query.next())    // il ne devrait il n'y en avoir qu'un
              {version = query.value(0).toString();      // date
              }
        }
    return version;
}
//-------------------------------- getFirstSmrInfoForCIP ------------------------------------------------------
/*! \brief select SMR and ASM informations for a drug. You must call this methode While returns true.
 *  \param const QString &cip      code CIP of the drug from wich wee want datas.
 *  \param QString &date           it will contains date        of SMR ASM.
 *  \param QString &level          it will contains level       of SMR ASM..
 *  \param QString &indication     it will contains indication  of SMR ASM..
 *  \param QString &descriptif     it will contains description of SMR ASM..
 *  \param QString &codeCimx       it will contains code CIM10  of SMR ASM..
 *  \return true while datas are presents.. You must loop while returns true.
 */
bool C_BDM_Api::getNextSmrInfoForCIP(      const QString &cip,
                                           QString &date,
                                           QString &level,
                                           QString &levelLibelle,
                                           QString &indication,
                                           QString &descriptif,
                                           QString &codeCimx)
{if (m_pC_BDM_PluginI) return m_pC_BDM_PluginI->getNextSmrInfoForCIP(cip,date,level,levelLibelle,indication,descriptif,codeCimx);
 return false;
}
//-------------------------------- getMonographieFromCIP ------------------------------------------------------
/*! \brief select monographie for a drug.
 *  \param const QString &cip      code CIP of the drug from wich wee want datas.
 *  \return QString contains monographie
 */
QString  C_BDM_Api::getMonographieFromCIP (    const QString &cip   , bool dataMustBeReadInCache /* = TRUE */ )
{if (m_pC_BDM_PluginI) return m_pC_BDM_PluginI->getMonographieFromCIP ( cip  , dataMustBeReadInCache);
 return QString::null;
}
//-------------------------------- getPriseUnitFormFromCIP ------------------------------------------------------
/*! \brief return the prise unit form from cip. (comprimés, suppositoires sachets,ampoules,doses kg, cuillères à café etc...)
 *  \param const QString &cip      code CIP of the drug from wich wee want datas.
 *  \return QString with unit form
 */
QString   C_BDM_Api::getPriseUnitFormFromCIP ( const QString &cip, const QString &commercialName /* = 0 */)
{if (m_pC_BDM_PluginI) return m_pC_BDM_PluginI->getPriseUnitFormFromCIP ( cip , commercialName);
 return QString::null;
}
//--------------------------- get_CIS_RCP_From_CIP -----------------------------------------------------------
/*! \brief return ANSM (ex afssaps) CIS ans RCP code from CIP code, to use in html request with ANSM (ex afssaps) web site.
 *  \param const QString cip is drug cip code.
 *  \param QString *rcp is pointer on QString to return RCP result if not zero .
 *  \return CIS code string
*/
QString C_BDM_Api::get_CIS_and_RCP_From_CIP(const QString &cip, QString *rcp /* =0 */)
{QSqlQuery query(QString::null , database() );
 QString     cis = "";
 QString requete = "";
 if (rcp)   *rcp = "";
 //.......... on essaie avec le plugin commercial ...............
 if (m_pC_BDM_PluginI)
    {cis           = m_pC_BDM_PluginI->get_CIS_and_RCP_From_CIP(cip, rcp);
    }
 //.......... si CIS pas trouve on essaie de trouver le CIS avec le plan B (tables afssaps) ...............
 if (cis.length()==0)
    {requete = QString("SELECT `afs_ciscip_cis_code` FROM `afs_ciscip` WHERE `afs_ciscip_cip_code`  = \"%1\"").arg(cip );
     if (!query.exec(requete))
        {QString err = tr("\nERROR: C_BDM_Api::get_CIS_RCP_From_CIP( \n%1\nREQUEST: %2").arg(query.lastError().text(),requete).toAscii();
         outMessage(err);
         return QString::null;
        }
     if ( query.next() ) cis = query.value(0).toString();
    }

 //.......... si CIS trouve et RCP non trouve on essaie si besoin (rcp != 0) de trouver le RCP avec le plan B (tables afssaps) ...............
 if (rcp && cis.length() && rcp->length()==0)
    {requete = QString("SELECT `afs_cis_rcp` FROM `afs_cis` WHERE `afs_cis_code`  = \"%1\"").arg(cis );
     if (!query.exec(requete))
        {QString err = tr("\nERROR: C_BDM_Api::get_CIS_RCP_From_CIP( \n%1\nREQUEST: %2").arg(query.lastError().text(),requete).toAscii();
         outMessage(err);
         return QString::null;
        }
     if ( query.next() ) *rcp = query.value(0).toString();
    }
 return cis;
}
//-------------------------------- isStupefiant ------------------------------------------------------
/*! \brief return if the product identified par Id is a stupefiant
 *  \param const QString &cip      code CIP of the drug from wich wee want datas.
 *  \return 1 is stupefiant
 */
int C_BDM_Api::isStupefiant ( const QString &cip )
{if (m_pC_BDM_PluginI)
    {return m_pC_BDM_PluginI->isStupefiant (cip );
    }
 return 0;
}

//-------------------------------- fill_ATC_treeWidget ------------------------------------------------------
/*! \brief fill pQTreeWidget with ATC classification
 *  \param pQTreeWidget QTreeWidget to fill with datas     .
 */
void C_BDM_Api::fill_ATC_treeWidget(QTreeWidget *pQTreeWidget)
{       if (m_pC_BDM_PluginI==0) return;
        QTreeWidgetItem *curParentItem = 0;
        QTreeWidgetItem          *item = 0;
        long                    curLen = 0;
        QString            atc_libelle = "";
        QString              atc_code  = "";

        pQTreeWidget->clear();
        while (m_pC_BDM_PluginI->nextATC_Code(atc_code, atc_libelle))
              {int            len  = atc_code.length();

               if (len==1)
                  { curParentItem = new QTreeWidgetItem (pQTreeWidget);
                    curParentItem->setText(0,atc_libelle);
                    curParentItem->setText(1,atc_code);
                    curLen = len;
                  }
               else if (len > curLen)
                  { item =   new QTreeWidgetItem (curParentItem);
                    item->setText(0,atc_libelle);
                    item->setText(1,atc_code);
                    if (len != 7) curParentItem = item;
                    curLen = len;
                  }
               else if (len == curLen)
                  { item =   new QTreeWidgetItem (curParentItem);
                    item->setText(0,atc_libelle);
                    item->setText(1,atc_code);
                    curLen = len;
                  }
               else if (len < curLen)
                  { //......... remonter tant que le père n'a pas de partie comumune avec le fils ............
                    while( curParentItem->parent() != 0 &&  atc_code.left(curParentItem->text(1).length()) != curParentItem->text(1))
                         {curParentItem = curParentItem->parent();
                         }
                    curParentItem = new QTreeWidgetItem (curParentItem);
                    curParentItem->setText(0,atc_libelle);
                    curParentItem->setText(1,atc_code);
                    curLen = len;
                  }
              }    // end while (query.next()
}

/////////////////////////////////////////////////////////////////// PRIVATE ZONE ///////////////////////////////////////////////////////////////////
//-------------------------------- connectBase ------------------------------------------------------
int C_BDM_Api::connectBase(const QString &params)
{QString errMess;
 if (BaseConnect(params, "BDM_BASEGET", "BaseGetTest", &errMess )==0) return 0;
 m_pQSqlQuery = new QSqlQuery (QString::null , this->database());
 return 1;
}

//-------------------------------- getFirstSmrInfoForCIP ------------------------------------------------------
// ACTION : return all SMR for a CIP (globals and cimx)
/*
bool C_BDM_Api::getNextSmrInfoForCIP(      const QString &cip,
                                           QString &date,
                                           QString &level,
                                           QString &levelLibelle,
                                           QString &indication,
                                           QString &descriptif,
                                           QString &codeCimx)
{if (!database().isOpen() && database().open()== FALSE)
    {outMessage( tr("ERREUR : C_BDM_Api::getNextSmrInfoForCIP() database can not be open"), __FILE__, __LINE__);  return 0;
    }
 if (m_pQSqlQuery==0)
    {outMessage( tr("ERREUR : C_BDM_Api::getNextSmrInfoForCIP() m_pQSqlQuery = 0"), __FILE__, __LINE__);          return 0;
    }

 if (m_firstTimeGetNextSmrInfoForCIP)       // si premier passage on requete autrement on recupere
    {
      QString requete = QString (
      //       0 Level ASMR (text) 1 libelle            2 indication       3 description detaillee   4 CIMX (si present) 5 date
      " SELECT it_inter_regle ,    it_inter_mecanisme , c2.it_compo_name , c2.it_compo_descr ,       c2.it_compo_id_ctx, it_inter_date"
      " FROM it_link  "
      " join it_compo as c1 on it_link_compo_pk1 = c1.it_compo_pk "
      " join it_inter       on it_inter_pk       = it_link_inter_pk "
      " join it_compo as c2 on c2.it_compo_pk    = it_link_compo_pk2 "
      " where c1.it_compo_id_ctx='%1' Group by it_link_compo_pk1, it_link_compo_pk2" ).arg(cip);
      m_pQSqlQuery->exec(requete );
      outSQL_error( *m_pQSqlQuery, "ERREUR  : C_BDM_Api::getNextSmrInfoForCIP()", requete, __FILE__, __LINE__);
    }
 if (m_pQSqlQuery->isActive() && m_pQSqlQuery->next())
    { date          = m_pQSqlQuery->value(5).toDate().toString("dd-MM-yyyy");
      level         = m_pQSqlQuery->value(0).toString();
      levelLibelle  = m_pQSqlQuery->value(1).toString();
      indication    = CGestIni::Utf8_Query(m_pQSqlQuery, 2);
      descriptif    = CGestIni::Utf8_Query(m_pQSqlQuery, 3);
      codeCimx      = m_pQSqlQuery->value(4).toString();
      m_firstTimeGetNextSmrInfoForCIP = FALSE;
      return TRUE;
    }    // end while (query.next())

 m_firstTimeGetNextSmrInfoForCIP = TRUE;            // on a fini de recuperer donc remettre à zero
 return FALSE;
}


//-------------------------------- initializeASMR ------------------------------------------------------
int C_BDM_Api::initializeASMR(C_BDM_PluginI *pC_BDM_PluginI)
{
 return 1;
}

//-------------------------------- initializeSMR ------------------------------------------------------
int C_BDM_Api::initializeSMR(C_BDM_PluginI *pC_BDM_PluginI)
{if (pC_BDM_PluginI==0)                                       return 0;
 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 if (m_StatusWidget)     m_StatusWidget->setText(tr("initialisation SMR comptage en cours ..."));

 if (pC_BDM_PluginI->getSmrList_Start()==0)
    {QApplication::restoreOverrideCursor();
     if (m_StatusWidget) m_StatusWidget->setText(tr(" Echec de l'initialisation SMR"));
     return 0;
    }
 //............... un peu de signalisation ................
 if (m_StatusWidget)     m_StatusWidget->setText(tr(" Initialisation SMR en cours ..."));

 m_position  = 0;
 m_nbToParse = pC_BDM_PluginI->smrList_Count();
 outMessage(  tr("Nb records <font color=#00c0ff>%1</font> : <font color=#00ffff>%2</font>").arg("C_BDM_Api::initializeSMR()",QString::number(m_nbToParse)));
 if (m_pQProgressBar) m_pQProgressBar->setRange(0, m_nbToParse/10);

 C_BDM_SmrListRecord c_bdm_smrlistrecord;

 while (pC_BDM_PluginI->getSmrList_NextRecord(c_bdm_smrlistrecord))
    {QString pk_comp_1 = it_createComposant(
                                       c_bdm_smrlistrecord.libelle_1(),          // nom de la drogue
                                       c_bdm_smrlistrecord.descrip_1(),          // tr("drug for SMR"),                 //
                                       c_bdm_smrlistrecord.id_type_1(),          // 'CIP'
                                       c_bdm_smrlistrecord.id_1(),               // numero de CIP
                                       c_bdm_smrlistrecord.smr_type(),           // ASMR ou SMR
                                       c_bdm_smrlistrecord.datetime(),
                                       c_bdm_smrlistrecord.owner());
     QString pk_comp_2 = it_createComposant(
                                       c_bdm_smrlistrecord.libelle_2(),          // nom de l'indication ou AMM
                                       c_bdm_smrlistrecord.descrip_2(),          // tr("indication for SMR"),           //
                                       c_bdm_smrlistrecord.id_type_2(),          // 'CIM10' 'CISP'
                                       c_bdm_smrlistrecord.id_2(),               // code CIM10 ou CISP
                                       c_bdm_smrlistrecord.smr_type(),           // ASMR ou SMR
                                       c_bdm_smrlistrecord.datetime(),
                                       c_bdm_smrlistrecord.owner());
     QString pk_inter  = it_createRecord(c_bdm_smrlistrecord.level(),
                                         c_bdm_smrlistrecord.level_libelle(),
                                         c_bdm_smrlistrecord.cat(),
                                         c_bdm_smrlistrecord.datetime(),
                                         c_bdm_smrlistrecord.owner());
     it_createLink(pk_comp_1,
                   pk_comp_2,
                   pk_inter,
                   c_bdm_smrlistrecord.smr_type(),
                   c_bdm_smrlistrecord.datetime(),
                   c_bdm_smrlistrecord.owner());
     ++m_position;
     if ((m_position&63)==63) onSmrAvancement(c_bdm_smrlistrecord.cat());  // marche pô avec QTime ??
    }
 m_isValid = 1;
 QApplication::restoreOverrideCursor();
 if (m_StatusWidget)    m_StatusWidget->setText(tr("initialisation SMR terminée"));
 return 1;
}

//-------------------------------- onSmrAvancement ------------------------------------------------------
void C_BDM_Api::onSmrAvancement(const QString &label)
{ if (m_pQProgressBar)  {m_pQProgressBar->setValue(m_position/10); qApp->processEvents();qApp->processEvents();qApp->processEvents();}
  if (m_StatusWidget)    m_StatusWidget->setText(tr("%3 %1 sur %2").arg(QString::number(m_position),QString::number(m_nbToParse), label));
}

*/

////////////////////////////////////////// fonctions d'interogation des tables d'interaction ////////////////////////////////
//--------------------------- it_getInteractionForTwoComposants -----------------------------------------------------------
QString C_BDM_Api::it_getInteractionForTwoComposants(QTreeWidget *pQTreeWidget, const QString &class_it, const QString &produit_1, const QString &produit_2)
{pQTreeWidget->clear();
 if (!database().isOpen() && database().open()== FALSE) return QString::null;
 QSqlQuery query(QString::null , database() );
 QString requete  = "";
 int          nb  = 0;
 int        il_1  = 0;
 int        il_2  = 0;
 QStringList pk1_List   = produit_1.length() ? isThisValueLikeInTable_ToList("it_compo",
                                                                             "it_compo_name",
                                                                             produit_1.toUpper(),
                                                                             "",
                                                                             QString(" AND `it_compo_class`=\"%1\" ").arg(class_it)) : QStringList();
 QStringList pk2_List   = produit_2.length() ? isThisValueLikeInTable_ToList("it_compo",
                                                                             "it_compo_name",
                                                                             produit_2.toUpper(),
                                                                             "",
                                                                             QString(" AND `it_compo_class`=\"%1\" ").arg(class_it)) : QStringList();
 int nbpk1              = pk1_List.count();
 int nbpk2              = pk2_List.count();

 if (nbpk1 && nbpk2)
    {if (nbpk1 * nbpk2 >50)
        {return tr("Trop grand nombre de requ\303\252tes : %1").arg(QString::number(nbpk1 * nbpk2));
        }
     for (il_1=0; il_1<nbpk1; ++il_1)
         {for (il_2=0; il_2<nbpk2; ++il_2)
              {requete  = QString(" SELECT `it_link_inter_pk`,`it_link_compo_pk1`,`it_link_compo_pk2` FROM `it_link`"
                                  " WHERE `it_link_compo_pk1`  = \"%1\" AND `it_link_compo_pk2`  = \"%2\"").arg( pk1_List[il_1], pk2_List[il_2] );
               nb += it_execQueryGetInteraction(query, requete, pQTreeWidget);
              }
         }
    }
  else if (nbpk1)
    {if (nbpk1>50)
        {return tr("Trop grand nombre de requ\303\252tes : %1").arg(QString::number(nbpk1));
        }
     for (il_1=0; il_1<nbpk1; ++il_1)
         {requete  = QString(" SELECT `it_link_inter_pk`,`it_link_compo_pk1`,`it_link_compo_pk2` FROM `it_link`"
                             " WHERE  `it_link_compo_pk1`  = \"%1\"").arg( pk1_List[il_1]);
          nb += it_execQueryGetInteraction(query, requete, pQTreeWidget);
         }
     if (nb==0)
        {for (il_1=0; il_1<nbpk1; ++il_1)
             {requete  = QString(" SELECT `it_link_inter_pk`,`it_link_compo_pk1`,`it_link_compo_pk2` FROM `it_link`"
                                 " WHERE  `it_link_compo_pk2`  = \"%1\"").arg( pk1_List[il_1]);
              nb += it_execQueryGetInteraction(query, requete, pQTreeWidget);
             }
        }
    }
  else if (nbpk2)
    {if (nbpk2>50)
        {return tr("Trop grand nombre de requ\303\252tes : %1").arg(QString::number(nbpk2));
        }
    for (il_2=0; il_2<nbpk2;++il_2)
         {requete  = QString(" SELECT `it_link_inter_pk`,`it_link_compo_pk1`,`it_link_compo_pk2` FROM `it_link`"
                             " WHERE  `it_link_compo_pk2`  = \"%1\"").arg( pk2_List[il_2]);
          nb += it_execQueryGetInteraction(query, requete, pQTreeWidget);
         }
    if (nb==0)
       {for (il_2=0; il_2<nbpk2; ++il_2)
            {requete  = QString(" SELECT `it_link_inter_pk`,`it_link_compo_pk1`,`it_link_compo_pk2` FROM `it_link`"
                                " WHERE  `it_link_compo_pk1`  = \"%1\"").arg( pk2_List[il_2]);
             nb += it_execQueryGetInteraction(query, requete, pQTreeWidget);
            }
       }
    }
 return tr("Nombre de r\303\251ponses : %1").arg(QString::number(nb));
}
//--------------------------- it_execQueryGetInteraction -----------------------------------------------------------
int C_BDM_Api::it_execQueryGetInteraction(QSqlQuery &query, const QString &requete, QTreeWidget *pQTreeWidget)
{if (!query.exec(requete))
    {outSQL_error( query, "ERREUR  : execQueryGetInteraction()", requete, __FILE__, __LINE__);
     return 0;
    }
  int i = 0;
  //............................. query SELECT `it_link_inter_pk` `it_link_compo_pk1` `it_link_compo_pk2` ..........
  if (query.isActive() )
      {while(query.next())
            {QTreeWidgetItem *pItem = it_getInteractionFromPk(query.value(0).toString(), pQTreeWidget);      // rechercher les infos de l'interaction entre pk1 et pk2
             if (pItem)
                { pItem->setText(1,   it_getComposantNameFromPk(query.value(1).toString()) +                 // recuperer le nom du composant 1
                                      " et " +
                                      it_getComposantNameFromPk(query.value(2).toString()));                 // recuperer le nom du composant 2
                  ++i;
                }
            }
      }
 return i;
}

//--------------------------- it_getInteractionFromPk -----------------------------------------------------------
QTreeWidgetItem * C_BDM_Api::it_getInteractionFromPk(const QString &pk, QTreeWidget *pQTreeWidget)
{   QSqlQuery query(QString::null , database() );
    QString requete  =  QString(" SELECT `it_inter_date`, `it_inter_regle`, `it_inter_mecanisme`, `it_inter_cat`,`it_inter_owner` FROM `it_inter`"
                                " WHERE  `it_inter_pk`  = \"%1\" ").arg( pk);
    requete += ownersSelectMention("it_inter");
    if (!query.exec(requete))
       {outSQL_error( query, "ERREUR  : getInteraction()", requete, __FILE__, __LINE__);
        return 0;
       }
    if (query.isActive() )
        {while(query.next())    // il ne devrait il n'y en avoir qu'un
              {QTreeWidgetItem *pItem = new QTreeWidgetItem(pQTreeWidget);
               pItem->setText(0, query.value(0).toString());      // date
            // pItem->setText(1, "les composants de l'interaction seront mis apres"
               pItem->setText(2, query.value(1).toString());      // la regle est le niveau
               pItem->setText(3, query.value(2).toString());      // texte sur le mecanisme
               pItem->setText(4, query.value(3).toString());      // texte sur la conduite a tenir
               pItem->setText(5, query.value(4).toString());      // proprio
               return pItem;
              }
        }
    else
       {return 0;
       }
    return 0;
}
//--------------------------- it_getComposantNameFromPk -----------------------------------------------------------
QString C_BDM_Api::it_getComposantNameFromPk(const QString &pk)
{   QSqlQuery query(QString::null , database() );
    QString requete  = QString(" SELECT `it_compo_name`, `it_compo_descr` FROM `it_compo`"
                               " WHERE  `it_compo_pk`  = \"%1\" ").arg( pk );
    requete += ownersSelectMention("it_compo");
    if (!query.exec(requete))
      {outSQL_error( query, "ERREUR  : getNameFacteurFromPk()", requete, __FILE__, __LINE__);
       return QString::null;
      }
    if (query.isActive() )
        {while(query.next())    // il ne devrait il n'y en avoir qu'un
              {return query.value(0).toString();
              }
        }
    else
       {return QString::null;
       }
    return QString::null;
}
////////////////////////////////////////// fonctions de renseignement des tables d'interaction ////////////////////////////////
//--------------------------- it_createLink ----------------------------------------------------------------------------------
QString C_BDM_Api::it_createLink(const QString &pk1, const QString &pk2, const QString &pki, const QString &class_it, const QString   &datetime, const QString &owner)
{    QString err = "";
     if (!isInOwnerList(owner))
        {err = tr("ERREUR  : C_BaseCommon::it_it_createLinkFacteursInteraction() \nThis owner : '%1' is not found").arg(owner).toAscii();
         outMessage(err);
         return QString::null;
        }

     if (!database().isOpen() && database().open()== FALSE) return QString::null;
     QSqlQuery query(QString::null , database() );
     QString prepare  = QLatin1String(" INSERT INTO it_link ( `it_link_owner`, `it_link_compo_pk1`,`it_link_compo_pk2`, `it_link_inter_pk`, `it_link_class`, `it_link_date`)"
                                      " VALUES (?,?,?,?,?,?)");
     query.prepare(prepare);
     query.bindValue(0, owner);
     query.bindValue(1, pk1);
     query.bindValue(2, pk2);
     query.bindValue(3, pki);
     query.bindValue(4, class_it);
     query.bindValue(5, datetime);
     if ( !query.exec())
        {outSQL_error( query, "ERREUR  : C_BaseMedica::it_it_createLinkFacteursInteraction()", prepare, __FILE__, __LINE__);
         return QString::null;
        }
     return getLastPrimaryKey( "it_link", "it_link_pk");
}

//--------------------------- it_createRecord -----------------------------------------------------------
QString C_BDM_Api::it_createRecord( const QString   &regle, const QString   &mecanisme, const QString   &cat, const QString   &datetime, const QString   &owner)
{   QString err = "";
    if (!isInOwnerList(owner))
       {err = tr("ERREUR  : C_BaseCommon::it_createInteractionRecord() : This owner : '%1' is not found").arg(owner).toAscii();
        outMessage( err);
        return QString::null;
       }
    if (!database().isOpen() && database().open()== FALSE) return QString::null;
    QString c    = cat;
    QString mec  = mecanisme;
    QDateTime dt = QDateTime::fromString(datetime,Qt::ISODate);
    QSqlQuery query(QString::null , database() );

    QString requete  = QString("SELECT `it_inter_pk` FROM `it_inter` WHERE ("
                               "`it_inter_regle`      = \"%1\" AND "
                               "`it_inter_mecanisme`  = \"%2\" AND "
                               "`it_inter_date`            %3  AND "       // %3 deviendra si date invalide ' IS NULL' sinon '= datetime'
                               "`it_inter_cat`        = \"%4\" ) "
                               ).arg(regle,
                                     mec.replace("\"","\\\"").replace(",","\\,"),
                                     dt.isValid() ? QString("=\"")+datetime+"\"" : QString(" IS NULL"), // %2 devient si date invalide ' IS NULL' sinon '= datetime'
                                     c.replace("\"","\\\"").replace(",","\\,") );
    requete += ownersSelectMention("it_inter");
    if (!query.exec(requete))
       { outSQL_error(query, "ERREUR  : C_BaseMedica::it_createRecord()", requete, __FILE__, __LINE__);
         return QString::null;
       }
    if ( query.next() ) return query.value(0).toString();    // on a trouve on se casse avec

 //............... on a pas trouve on cree ............................
 QString prepare  = QLatin1String(" INSERT INTO it_inter (`it_inter_owner`, `it_inter_regle`,`it_inter_mecanisme`, `it_inter_cat`, `it_inter_date`)"
                                  " VALUES (?,?,?,?,?)");
 query.prepare(prepare);
 query.bindValue(0, owner);
 query.bindValue(1, regle);
 query.bindValue(2, mecanisme);
 query.bindValue(3, cat);
 query.bindValue(4, datetime);
 if ( !query.exec())
    {outSQL_error(query, "ERREUR  : C_BaseMedica::it_createInteractionRecord()", prepare, __FILE__, __LINE__);
     return QString::null;
    }
 return getLastPrimaryKey( "it_inter", "it_inter_pk");
}

//--------------------------- it_createComposant -----------------------------------------------------------
QString C_BDM_Api::it_createComposant(const QString &libelle, const QString &descr, const QString &id_ctx_type, const QString &id_ctx, const QString &id_class, const QString   &datetime, const QString   &owner)
{
    QString   prepare = "";
    QString   pk      = "";

    QSqlQuery query(QString::null , database() );;

    if (!isInOwnerList(owner))
       {outMessage( tr("ERREUR  : C_BaseCommon::it_createComposant() : This owner : '%1' is not found").arg(owner).toAscii());
        return QString::null;
       }
    QDateTime dt = QDateTime::fromString(datetime,Qt::ISODate);
    QString   s  = descr;             s = s.replace("\"","\\\"").replace(",","\\,");
    QString   l  = libelle.toUpper(); l = l.replace("\"","\\\"").replace(",","\\,");
    //int     pos  = posLastEnclosedSymbol(s,"(",")");
    //if (pos     != -1) s.truncate(pos);

    if ( !dt.isValid() )
       {pk = isThisValueInTable("it_compo","it_compo_name", l,"",
                                QString(" AND `it_compo_class`=\"%1\" AND `it_compo_id_ctx`=\"%2\" AND `it_compo_descr`= \"%3\" AND `it_compo_date` IS NULL")
                                .arg(id_class, id_ctx, s));
        outMessage( tr("WARNING  : C_BaseCommon::it_createComposant() : The date : '%1' of this composant '%2'' is not valid and will be turned to NULL").arg(datetime,libelle).toAscii());
       }
    else
       {pk =isThisValueInTable("it_compo","it_compo_name", l,"",
                               QString(" AND `it_compo_class`=\"%1\" AND `it_compo_id_ctx`=\"%2\" AND `it_compo_descr`= \"%3\" AND `it_compo_date`=\"%4\"")
                               .arg(id_class, id_ctx,  s, datetime));
       }

    if (pk.length())
       {C_Utils_Log::outMessage( 0, tr("WARNING  : C_BaseMedica::it_createComposant() : '%1' not added because it is already in '%2'").arg(libelle.toUpper(),"it_compo").toAscii());
        //...................... ^ en mettant zero on empeche la sortie dans le widget de log et elle se fait juste dans la console d'erreurs normale
        return pk;                 // si deja present cassos
       }

    prepare  = QLatin1String("INSERT INTO it_compo (`it_compo_owner`, `it_compo_name`,`it_compo_descr`,`it_compo_id_ctx`, `it_compo_id_ctx_type`, `it_compo_class`, `it_compo_date`) "
                             "VALUES (?,?,?,?,?,?,?)");
    if (!database().isOpen() && database().open()== FALSE) return QString::null;

    query.prepare(prepare);
    query.bindValue(0, owner);
    query.bindValue(1, libelle.toUpper());
    query.bindValue(2, descr);
    query.bindValue(3, id_ctx);
    query.bindValue(4, id_ctx_type);
    query.bindValue(5, id_class);
    query.bindValue(6, datetime);
    if ( !query.exec())
       {outSQL_error( query, "ERREUR  : C_BaseMedica::it_createComposant()", prepare, __FILE__, __LINE__);
        return QString::null;
       }
    return getLastPrimaryKey( "it_compo", "it_compo_pk");
}
////////////////////////////////////////// fonctions de creation des tables d'interaction ////////////////////////////////
//--------------------------- it_createTables -----------------------------------------------------------
int C_BDM_Api::it_createTables()
{
if (dropTable(  "it_compo")==0) return 0;
if (createTable(" CREATE TABLE `it_compo` ("
                "`it_compo_pk`          BIGINT NOT NULL AUTO_INCREMENT,"
                "`it_compo_owner`       VARCHAR(40)   ,"
                "`it_compo_name`        VARCHAR(255)  ,"
                "`it_compo_descr`       VARCHAR(4048) ,"
                "`it_compo_id_ctx`      VARCHAR(80)   ,"
                "`it_compo_id_ctx_type` VARCHAR(40)   ,"
                "`it_compo_class`       VARCHAR(4)    ,"
                "`it_compo_date`        DATETIME      ,"
                "PRIMARY KEY (`it_compo_pk`)"
                ")")==0) return 0;
if (dropTable(  "it_group")==0) return 0;
if (createTable("CREATE TABLE `it_group` ("
                "`it_group_pk`          BIGINT  NOT NULL AUTO_INCREMENT,"
                "`it_group_owner`       VARCHAR(40)  ,"
                "`it_group_libelle`     VARCHAR(255) ,"
                "`it_group_note`        TEXT         ,"
                "`it_group_id`          CHAR(10)     ,"
                "PRIMARY KEY (`it_group_pk`)"
                ")"
                )==0) return 0;
if (dropTable(  "it_inter")==0) return 0;
if (createTable("CREATE TABLE `it_inter` ("
                "`it_inter_pk`           BIGINT  NOT NULL AUTO_INCREMENT,"
                "`it_inter_owner`        VARCHAR(40)   ,"
                "`it_inter_regle`        VARCHAR(255)  ,"
                "`it_inter_mecanisme`    VARCHAR(2000) ,"
                "`it_inter_cat`          VARCHAR(2000) ,"
                "`it_inter_date`         DATETIME      ,"
                "PRIMARY KEY (`it_inter_pk`)"
                ")"
                )==0) return 0;
if (dropTable(  "it_link")==0) return 0;
if (createTable("CREATE TABLE `it_link` ("
                "`it_link_pk`            BIGINT  NOT NULL AUTO_INCREMENT,"
                "`it_link_owner`         VARCHAR(40)      ,"
                "`it_link_inter_pk`      BIGINT  NOT NULL ,"
                "`it_link_compo_pk1`     BIGINT  NOT NULL ,"
                "`it_link_compo_pk2`     BIGINT  NOT NULL ,"
                "`it_link_class`         VARCHAR(4)       ,"
                "`it_link_date`          DATETIME         ,"
                "PRIMARY KEY (`it_link_pk`)"
                ")"
                )==0) return 0;
 return 1;
}
