Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.2 patch 1092 git-svn-id: svn://10.65.10.50/trunk@16297 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			591 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			591 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "cg2102.h"
 | |
| #include "cg2107.h"
 | |
| 
 | |
| #include "cg2100e.h"
 | |
| #include "cgsaldac.h"
 | |
| 
 | |
| #include <defmask.h>
 | |
| #include <diction.h>
 | |
| #include <relation.h>
 | |
| #include <treectrl.h>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TPartite_cache
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TPartite_cache : public TString_array
 | |
| {
 | |
|   TBill _bill;
 | |
|   long _numreg;
 | |
| 
 | |
| public:
 | |
|   const TBill& bill() const { return _bill; }
 | |
|   long num_reg() const { return _numreg; }
 | |
|   void set_bill(const TBill& conto, long numreg, bool all);
 | |
| 
 | |
|   bool has_game(int id) const { return id >= 0 && id < items(); }
 | |
|   TPartita* find(int index) const;  // Find by index (0 based)
 | |
|   TPartita& game(int index) const { return *find(index); }
 | |
| };
 | |
| 
 | |
| // Callback per scansione cursore
 | |
| static bool fill_games(const TRelation& rel, void* pJolly)
 | |
| {
 | |
|   TString_array& a = *(TString_array*)pJolly;
 | |
|   TString16 key, last_key; 
 | |
|   
 | |
|   const TRectype& rec = rel.curr();
 | |
|   key.format("%d|%s", rec.get_int(PART_ANNO), (const char*)rec.get(PART_NUMPART));
 | |
| 
 | |
|   const int last = a.items()-1;
 | |
|   if (last >= 0)
 | |
|     last_key = a.row(last);
 | |
| 
 | |
|   if (key != last_key)
 | |
|     a.add(key);
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void TPartite_cache::set_bill(const TBill& conto, long numreg, bool all)
 | |
| {
 | |
|   _bill = conto;
 | |
|   _numreg = numreg;
 | |
|   destroy();
 | |
|   TRelation partite(LF_PARTITE);
 | |
|   TRectype& rec = partite.curr();
 | |
|   rec.put(PART_TIPOCF, conto.tipo());
 | |
|   rec.put(PART_GRUPPO, conto.tipo() > ' ' ? 0 : conto.gruppo());
 | |
|   rec.put(PART_CONTO,  conto.tipo() > ' ' ? 0 : conto.conto());
 | |
|   rec.put(PART_SOTTOCONTO, conto.sottoconto());
 | |
| 
 | |
|   TString filter;
 | |
|   filter << '(' << PART_NUMRIG << "<9999)";
 | |
|   if (!all)
 | |
|     filter << "&&((" << PART_CHIUSA << "!='X')||(" 
 | |
|            << PART_NREG << "==" << numreg << "))";
 | |
| 
 | |
|   TCursor cur(&partite, filter, 1, &rec, &rec);
 | |
|   cur.scan(fill_games, this);
 | |
| }
 | |
| 
 | |
| 
 | |
| TPartita* TPartite_cache::find(int idx) const
 | |
| {
 | |
|   TPartita* g = NULL;
 | |
|   if (has_game(idx))
 | |
|   {
 | |
|     const TToken_string& str = row(idx);
 | |
|     int anno; str.get(0, anno);
 | |
|     TString8 numero; str.get(1, numero); 
 | |
|     TPartite_array& giochi = app().partite();
 | |
|     g = &giochi.partita(_bill, anno, numero);
 | |
|   }
 | |
|   return g;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSolder_tree
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TSolder_tree : public TBidirectional_tree
 | |
| {
 | |
|   TPartite_cache _cache;
 | |
|   TToken_string _curr;
 | |
| 
 | |
| public:
 | |
|   virtual bool goto_root();
 | |
|   virtual bool goto_firstson();
 | |
|   virtual bool goto_rbrother(); 
 | |
|   virtual bool goto_node(const TString &id) { _curr = id; return true; }
 | |
|   virtual bool has_son() const;
 | |
|   virtual bool has_rbrother() const;
 | |
|   virtual TObject* curr_node() const { return (TObject*)&_curr; }
 | |
|   virtual void node2id(const TObject* obj, TString& id) const { id = *(TString*)obj; }
 | |
|   
 | |
|   virtual bool has_root() const { return _cache.bill().ok(); }
 | |
|   virtual bool has_father() const { return _curr.not_empty(); }
 | |
|   virtual bool has_lbrother() const;
 | |
|   virtual bool goto_father();
 | |
|   virtual bool goto_lbrother();
 | |
|   virtual bool get_description(TString& desc) const;
 | |
|   virtual bool marked() const;
 | |
| 
 | |
| public:
 | |
|   void set_root(const TBill& conto, long numreg, bool all);
 | |
| 
 | |
|   TPartita* partita() const;
 | |
| }; 
 | |
| 
 | |
| TPartita* TSolder_tree::partita() const
 | |
| {
 | |
|   int index = -1; _curr.get(0, index);
 | |
|   TPartita* g = _cache.find(index);
 | |
|   return g;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::goto_root()
 | |
| {
 | |
|   _curr.cut(0);
 | |
|   return _cache.bill().ok();
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::goto_firstson()
 | |
| {
 | |
|   const int level = _curr.items();
 | |
|   if (level >= 4)
 | |
|     return false;
 | |
| 
 | |
|   const TPartita* g = partita();  // Funziona per level <= 1
 | |
|   if (g == NULL)
 | |
|     return false;
 | |
| 
 | |
|   if (level == 0)
 | |
|   {
 | |
|     _curr = "0";
 | |
|     return true;  // Basta il test precedente g!=NULL
 | |
|   }
 | |
| 
 | |
|   if (level == 1)
 | |
|   {
 | |
|     const int riga = g->first();
 | |
|     const bool ok = riga > 0 && riga < 9999;
 | |
|     if (ok) 
 | |
|       _curr.add(riga);
 | |
|     return ok;
 | |
|   }
 | |
|   
 | |
|   const int riga = _curr.get_int(1);
 | |
|   if (level == 2)
 | |
|   {
 | |
|     const bool ok = g->esiste(riga, 1);
 | |
|     if (ok)
 | |
|       _curr.add(1);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const int rata = _curr.get_int(2);
 | |
|   if (level == 3)
 | |
|   {
 | |
|     const TRiga_scadenze& scad = g->rata(riga, rata);
 | |
|     const int p = scad.first();
 | |
|     const bool ok = p > 0 && p < 9999;
 | |
|     if (ok)
 | |
|       _curr.add(p);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::goto_rbrother()
 | |
| {
 | |
|   const int level = _curr.items();
 | |
|   if (level == 0) // Il prossimo clifo non esiste mai per progetto
 | |
|     return false;   
 | |
|    
 | |
|   const int index = _curr.get_int(0);
 | |
|   if (level == 1) // Esite la prossima partita?
 | |
|   {
 | |
|     const bool ok = _cache.find(index+1) != NULL; 
 | |
|     if (ok)
 | |
|       _curr.add(index+1, 0);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const TPartita& g = _cache.game(index);
 | |
|   const int riga = _curr.get_int(1);
 | |
|   if (level == 2) // Esite la prossima riga?
 | |
|   {
 | |
|     const int nriga = g.succ(riga);
 | |
|     const bool ok = nriga > riga && nriga < 9999;
 | |
|     if (ok)
 | |
|       _curr.add(nriga, 1);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const int rata = _curr.get_int(2);
 | |
|   if (level == 3) // Esiste la prossima rata?
 | |
|   {
 | |
|     const int nrata = rata+1;
 | |
|     const bool ok = g.esiste(riga, nrata);
 | |
|     if (ok)
 | |
|       _curr.add(nrata, 2);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const int pag = _curr.get_int(3);
 | |
|   if (level == 4) // Esiste il prossimo pagamento
 | |
|   {
 | |
|     const TRiga_scadenze& scad = g.rata(riga, rata);
 | |
|     const int npag = scad.succ(pag);
 | |
|     const bool ok = g.esiste(riga, rata, npag);
 | |
|     if (ok)
 | |
|       _curr.add(npag, 3);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::has_son() const
 | |
| {
 | |
|   TSolder_tree& me = (TSolder_tree&)*this;
 | |
|   const TString16 old = me._curr;
 | |
|   const bool ok = me.goto_firstson();
 | |
|   me._curr = old;
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::has_rbrother() const
 | |
| {
 | |
|   TSolder_tree& me = (TSolder_tree&)*this;
 | |
|   const TString16 old = me._curr;
 | |
|   const bool ok = me.goto_rbrother();
 | |
|   me._curr = old;
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::has_lbrother() const
 | |
| {
 | |
|   TSolder_tree& me = (TSolder_tree&)*this;
 | |
|   const TString16 old = me._curr;
 | |
|   const bool ok = me.goto_lbrother();
 | |
|   me._curr = old;
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::goto_father()
 | |
| {
 | |
|   const bool ok = has_father();
 | |
|   if (ok)
 | |
|   {
 | |
|     const int pipe = _curr.rfind(_curr.separator());
 | |
|     if (pipe >= 0)
 | |
|       _curr.cut(pipe);
 | |
|     else
 | |
|       _curr.cut(0);
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::goto_lbrother()
 | |
| {
 | |
|   const int level = _curr.items();
 | |
|   if (level == 0) // Il precedente clifo non esiste mai per progetto
 | |
|     return false;   
 | |
|    
 | |
|   const int index = _curr.get_int(0);
 | |
|   if (level == 1) // Esite la precedente partita?
 | |
|   {
 | |
|     const bool ok = index > 0; 
 | |
|     if (ok)
 | |
|       _curr.add(index-1, 0);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const TPartita& g = _cache.game(index);
 | |
|   const int riga = _curr.get_int(1);
 | |
|   if (level == 2) // Esite la precedente riga?
 | |
|   {
 | |
|     const int nriga = g.pred(riga);
 | |
|     const bool ok = nriga > 0 && nriga < 9999;
 | |
|     if (ok)
 | |
|       _curr.add(nriga, 1);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const int rata = _curr.get_int(2);
 | |
|   if (level == 3) // Esiste la precedente rata?
 | |
|   {
 | |
|     const int nrata = rata-1;
 | |
|     const bool ok = nrata > 0;
 | |
|     if (ok)
 | |
|       _curr.add(nrata, 2);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   const int pag = _curr.get_int(3);
 | |
|   if (level == 4) // Esiste il precedente pagamento
 | |
|   {
 | |
|     const TRiga_scadenze& scad = g.rata(riga, rata);
 | |
|     const int npag = scad.pred(pag);
 | |
|     const bool ok = npag > 0;
 | |
|     if (ok)
 | |
|       _curr.add(npag, 3);
 | |
|     return ok;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::get_description(TString& desc) const
 | |
| {
 | |
|   const int level = _curr.items();
 | |
|   if (level == 0) // Il prossimo clifo non esiste mai per progetto
 | |
|   {
 | |
|     desc = _cache.bill().descrizione();
 | |
|     desc.strip_double_spaces();
 | |
|     return true;   
 | |
|   }
 | |
| 
 | |
|   const TPartita& g = *partita();
 | |
|   if (level == 1)
 | |
|   {
 | |
|     desc.cut(0) << g.anno() << '/' << g.numero();
 | |
|     desc.strip(" ");
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   int nriga = 1; _curr.get(1, nriga);
 | |
|   const TRiga_partite& riga = g.riga(nriga);
 | |
|   if (level == 2)
 | |
|   {
 | |
|     desc = riga.get(PART_DESCR);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   int nrata = 1; _curr.get(2, nrata);
 | |
|   const TRiga_scadenze& scad = riga.rata(nrata);
 | |
|   if (level == 3)
 | |
|   {
 | |
|     desc = TR("Rata"); 
 | |
|     desc << ' ' << nrata << ' ' << scad.get(SCAD_DATASCAD);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   int npag = 2; _curr.get(3, npag);
 | |
|   const TRectype& pag = scad.row(npag);
 | |
|   if (level == 4)
 | |
|   {
 | |
|     const TRiga_partite& rpag = g.riga(npag);
 | |
|     const tipo_movimento tipo = rpag.tipo();
 | |
|     switch(tipo)
 | |
|     {
 | |
|     case tm_insoluto: desc = TR("Insoluto"); break;
 | |
|     case tm_pagamento_insoluto: desc = TR("Pagamento insoluto"); break;
 | |
|     default: desc = TR("Pagamento"); break;
 | |
|     }
 | |
|     desc << ' ' << rpag.get(PART_DATAPAG);
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   desc = _curr;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void TSolder_tree::set_root(const TBill& conto, long numreg, bool all)
 | |
| {
 | |
|   _cache.set_bill(conto, numreg, all);
 | |
| }
 | |
| 
 | |
| bool TSolder_tree::marked() const
 | |
| {
 | |
|   bool yes = false;
 | |
|   const int level = _curr.items();
 | |
|   if (level >= 2)
 | |
|   {
 | |
|     const TPartita& g = *partita();
 | |
|     int nriga = 1; _curr.get(1, nriga);
 | |
|     const TRiga_partite& riga = g.riga(nriga);
 | |
|     yes = riga.get_long(PART_NREG) == _cache.num_reg(); 
 | |
|   }
 | |
| 
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TNew_game_mask
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TNew_game_mask : public TAutomask
 | |
| {
 | |
|   const TBill& _conto;
 | |
| 
 | |
| protected:
 | |
|   virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | |
| 
 | |
| public:
 | |
|   TNew_game_mask(const TBill& conto);
 | |
| };
 | |
| 
 | |
| bool TNew_game_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | |
| {
 | |
|   bool ok = true;
 | |
|   switch (o.dlg())
 | |
|   {
 | |
|   case 102:
 | |
|     if (e == fe_modify || e == fe_close)
 | |
|     {
 | |
|       const int anno = get_int(101);
 | |
|       const char* part = get(102);
 | |
|       const TPartita p(_conto, anno, part);
 | |
|       if (p.first() > 0)
 | |
|         ok = error_box("La partita %d/%s esiste gia'", anno, part);
 | |
|     }
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| TNew_game_mask::TNew_game_mask(const TBill& conto) 
 | |
|               : TAutomask(TR("Nuova partita"), 1, 24, 5), _conto(conto)
 | |
| {
 | |
|   TReal_field& anno = add_number(101, 0, PR("Anno    "), 1, 1, 4, "A");
 | |
|   anno.check_type(CHECK_REQUIRED);
 | |
|   
 | |
|   const char* flags = TPartita::allineamento_richiesto(_conto.tipo()) == 'R' ? "R" : "";
 | |
|   TEdit_field& partita = add_string(102, 0, PR("Partita "), 1, 2, 6, flags);
 | |
|   partita.check_type(CHECK_REQUIRED);
 | |
|   
 | |
|   add_button(DLG_OK, 0, "", -12, -1, 10, 2);
 | |
|   add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
 | |
|   set_handlers();
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TEasySolder_mask
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Forse andrebbe in libreria!
 | |
| void TEasySolder_mask::set_imp(short id, const TImporto& imp)
 | |
| {
 | |
|   TEdit_field& e = efield(id);
 | |
|   CHECK(e.size() >= 15, "Campo troppo piccolo per contenere un importo");
 | |
|   if (!imp.is_zero())
 | |
|   {
 | |
|     const TCurrency c(imp.valore());
 | |
|     TString80 str;
 | |
|     str << c.string(true) << ' ' << imp.sezione();
 | |
|     e.set(str);
 | |
|   }
 | |
|   else
 | |
|     e.reset();
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TEasySolder_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | |
| {
 | |
|   switch (o.dlg())
 | |
|   {
 | |
|   case DLG_NEWREC:
 | |
|     if (e == fe_button)
 | |
|     {
 | |
|       TNew_game_mask m(_conto.tipo());
 | |
|       if (m.run() == K_ENTER)
 | |
|       {
 | |
|       }
 | |
|     }
 | |
|     break;
 | |
|   case F_TUTTE:
 | |
|     if (e == fe_modify)
 | |
|     {
 | |
|       TSolder_tree& t = *(TSolder_tree*)_tree;
 | |
|       const bool all = o.get().full();
 | |
|       t.set_root(_conto, _numreg, all);
 | |
|       if (t.goto_root())
 | |
|         t.expand();
 | |
|       TTree_field& tfp = tfield(F_PARTITE);
 | |
|       tfp.win().force_update();
 | |
|     }
 | |
|     break;
 | |
|   case F_PARTITE:
 | |
|     if (e == fe_modify)
 | |
|     {
 | |
|       TSolder_tree& t = *(TSolder_tree*)_tree;
 | |
|       TToken_string curr; t.curr_id(curr);
 | |
|       const int level = curr.items();
 | |
|       if (level > 0)
 | |
|       {
 | |
|         const TPartita& p = *t.partita();
 | |
|         TImporto saldo, doc, pag, imp;
 | |
|         p.calcola_saldo(saldo, doc, pag, imp);
 | |
|         set_imp(F_DOCUMENTI_P, doc);        
 | |
|         set_imp(F_PAGAMENTI_P, pag);
 | |
|         set_imp(F_IMPORTI_P, imp);
 | |
|         set_imp(F_SALDO_P, saldo);
 | |
|       }
 | |
|       if (level > 1)
 | |
|       {
 | |
|         const TPartita& p = *t.partita();
 | |
|         const int nriga = curr.get_int(1);
 | |
|         const TRiga_partite& r = p.riga(nriga);
 | |
|         TImporto imp(r.get_char(PART_SEZ), r.get_real(PART_IMPORTO));
 | |
|         set(F_DATA_R, r.get(PART_DATADOC));
 | |
|         set_imp(F_IMPORTO_R, imp);
 | |
|       }
 | |
|       if (level > 2)
 | |
|       {
 | |
|         const int nriga = curr.get_int(1);
 | |
|         const TRiga_partite& r = t.partita()->riga(nriga);
 | |
|         const int nrata = curr.get_int(2);
 | |
|         const TRiga_scadenze& s = r.rata(nrata);
 | |
|         TImporto doc = s.importo(false);
 | |
|         TImporto pag = s.importo_pagato(false);
 | |
|         TImporto saldo = s.residuo(false);
 | |
|         set(F_DATA_S, s.get(SCAD_DATASCAD));
 | |
|         set_imp(F_IMPORTO_S, doc);
 | |
|         set_imp(F_PAGAMENTI_S, pag);
 | |
|         set_imp(F_SALDO_S, saldo);
 | |
|       }
 | |
|       if (level > 3)
 | |
|       {
 | |
|         const int nriga = curr.get_int(1);
 | |
|         const TRiga_partite& rf = t.partita()->riga(nriga);
 | |
|         const int nrata = curr.get_int(2);
 | |
|         const TRiga_scadenze& s = rf.rata(nrata);
 | |
|         const int nrigp = curr.get_int(3);
 | |
|         const TRectype& p = s.row(nrigp);
 | |
|         const TRiga_partite& rp = t.partita()->riga(nrigp);
 | |
| 
 | |
|         const TImporto pag(rp.get_char(PART_SEZ),       p.get_real(PAGSCA_IMPORTO));
 | |
|         const TImporto abb(rp.get_char(PART_SEZABB),    p.get_real(PAGSCA_ABBUONI));
 | |
|         const TImporto dif(rp.get_char(PART_SEZDIFCAM), p.get_real(PAGSCA_DIFFCAM));
 | |
|         set(F_DATA_PAG, rp.get(PART_DATAPAG));
 | |
|         set_imp(F_IMPORTO_PAG, pag);
 | |
|         set_imp(F_ABBUONI_PAG, abb);
 | |
|         set_imp(F_DIFFCAM_PAG, dif);
 | |
|       }
 | |
|       show(-10, level > 0);
 | |
|       show(-20, level > 1);
 | |
|       show(-30, level > 2);
 | |
|       show(-40, level > 3);
 | |
|     }
 | |
|     break;
 | |
|   default: break;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void TEasySolder_mask::init(const TBill& conto, long numreg, int numrig)
 | |
| {
 | |
|   _conto = conto;
 | |
|   _numreg= numreg;
 | |
|   _numrig = numrig;
 | |
|   _changed = false;
 | |
| 
 | |
|   if (_tree == NULL)
 | |
|   {
 | |
|     _tree = new TSolder_tree;
 | |
|     tfield(F_PARTITE).set_tree(_tree);
 | |
|   }
 | |
|   TSolder_tree& t = *(TSolder_tree*)_tree;
 | |
|   t.set_root(_conto, _numreg, get_bool(F_TUTTE));
 | |
|   if (t.goto_root())
 | |
|     t.expand();
 | |
| }
 | |
| 
 | |
| TEasySolder_mask::TEasySolder_mask(const TBill& conto, long numreg, int numrig) 
 | |
|                 : TAutomask("cg2100e"), _tree(NULL)
 | |
| { 
 | |
|   init(conto, numreg, numrig);
 | |
| }
 | |
| 
 | |
| TEasySolder_mask::~TEasySolder_mask()
 | |
| {
 | |
|   if (_tree)
 | |
|     delete _tree;
 | |
| }
 |