2616 lines
		
	
	
		
			75 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2616 lines
		
	
	
		
			75 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <colors.h>
 | |
| #include <msksheet.h>
 | |
| #include <progind.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h>                  
 | |
| 
 | |
| #include "cg2100.h"
 | |
| #include "cg2102.h"
 | |
| #include "cg21sld.h"
 | |
| 
 | |
| #include <clifo.h>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Funzioni di decodifica/calcolo
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| char TPrimanota_application::row_type(const TToken_string& s)
 | |
| {
 | |
|   const int l = s.len()-1;
 | |
|   return l > 0 ? s[l] : ' ';
 | |
| }
 | |
| 
 | |
| // Determina il tipo IVA da causale+anno
 | |
| // Certified 100%
 | |
| TipoIVA TPrimanota_application::cau2IVA(const char* cod, int annoiva)
 | |
| {
 | |
|   if (!read_caus(cod, annoiva))
 | |
|     error_box("Causale errata: '%s'", cod);
 | |
|   return causale().iva();
 | |
| }
 | |
| 
 | |
| // Calcolo della percentuale di un dato codice IVA
 | |
| // Certified 99%         
 | |
| const real& TPrimanota_application::cod2IVA(const TMask& m)
 | |
| {
 | |
|   static TString16 _codiva;           // Ultimo codice iva decodificato
 | |
|   static real _percent;               // Percentuale dell'ultimo codice iva
 | |
|                                       // Tipo Costo Ricavo
 | |
|   if (app().iva() == iva_acquisti && m.get_int(103) == 3)
 | |
|     return ZERO;
 | |
|   
 | |
|   const TString& codiva = m.get(102);
 | |
|   if (_codiva != codiva)
 | |
|   {
 | |
|     _codiva = codiva;
 | |
|     TCodiceIVA c(_codiva);
 | |
|     _percent = c.percentuale();
 | |
|   }
 | |
|   
 | |
|   return _percent;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Scorpora dall'imponibile la percentuale d'imposta(0.0%-100.0%) e ritorna l'imposta stessa
 | |
| // Certified 99%  Non sono sicurissimo degli imponibili negativi
 | |
| real TPrimanota_application::scorpora(real& imponibile, const real& percent)
 | |
| {
 | |
|   real imposta = abs(imponibile) * percent / (percent + 100.0); imposta.ceil();
 | |
|   if (imponibile.sign() < 0) imposta = -imposta; 
 | |
|   imponibile -= imposta;
 | |
|   return imposta;
 | |
| }  
 | |
| 
 | |
| 
 | |
| // Calcola il totale del documento tenendo conto del segno della prima riga e di quella delle
 | |
| // ritenute sociali sulla causale                        
 | |
| real TPrimanota_application::totale_documento()
 | |
| {
 | |
|   const TMask& m = curr_mask();
 | |
| 
 | |
|   const bool swapt = test_swap(FALSE);    // Totale invertito ?
 | |
|   const bool swaps = test_swap(TRUE);     // Ritenute sociali invertite ?
 | |
| 
 | |
|   real tot(m.get(F_TOTALE));              // Legge totale
 | |
|   const real ritfis(m.get(F_RITFIS));
 | |
|   tot += ritfis;                          // Somma ritenute fiscali
 | |
|   
 | |
|   real ritsoc(m.get(F_RITSOC));           
 | |
|   if (swapt ^ swaps)
 | |
|     ritsoc = -ritsoc;
 | |
|   tot += ritsoc;                          // Somma ritenute sociali con segno
 | |
| 
 | |
|   return tot;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Determina se un codice sospeso o no
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::suspended_handler(TMask_field& f, KEY k)
 | |
| {                   
 | |
|   if (f.to_check(k))
 | |
|   {
 | |
|     const TEdit_field& c = (const TEdit_field&)f;
 | |
|     const TBrowse* b = c.browse();
 | |
|     CHECKD(b, "Can't check suspension of a edit-field without a USE ", f.dlg());
 | |
|     const TLocalisamfile& i = b->cursor()->file();
 | |
|     //                        Tabella    File
 | |
|     const char* sf = i.tab() ? "B2" : "SOSPESO";  
 | |
|     const bool suspended = i.get_bool(sf);
 | |
|     if (suspended)
 | |
|     {                                                                    
 | |
|       sf = f.get();
 | |
|       return f.error_box("Il codice '%s' e' sospeso e non puo' essere utilizzato", sf);  
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Determina se un codice detrazione e' di tipo detraibile o no
 | |
| // Certified 70%
 | |
| bool TPrimanota_application::detraibile(TToken_string& row)
 | |
| {    
 | |
|   const TPrimanota_application& a = app();
 | |
|   if (a.iva() == iva_vendite)                 // Vendite sempre detraibili
 | |
|     return TRUE;
 | |
| 
 | |
|   const int tipo_det = row.get_int(2);            // Leggi tipo detraibilita
 | |
|   if (tipo_det != 0)
 | |
|     return FALSE;
 | |
|   
 | |
|   const int annodoc = a._msk[2]->get_date(F_DATADOC).year();
 | |
|   const bool prorata100 = a.causale().reg().prorata100(annodoc);
 | |
|   return !prorata100;                        // Se prorata = 100% e' indetraibile
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Funzioni di ricerca
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| int TPrimanota_application::type2pos(char tipo)
 | |
| {
 | |
|   TString_array& cg = app().cgs().rows_array();
 | |
|   for (int i = 0; i < cg.items(); i++)
 | |
|   {
 | |
|     const TToken_string& s = cg.row(i);
 | |
|     const char t = row_type(s);
 | |
|     if (t == tipo)
 | |
|       return i;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Trova nelle righe contabili un conto nelle righe di tipo prescelto
 | |
| int TPrimanota_application::bill2pos(const TBill& conto, char tipo)
 | |
| {
 | |
|   TString_array& cg = app().cgs().rows_array();
 | |
|   const int num_rows = cg.items();
 | |
|   for (int i = 0; i < num_rows; i++)
 | |
|   {
 | |
|     TToken_string& s = cg.row(i);
 | |
|     const char t = row_type(s);
 | |
|     if (t == tipo)
 | |
|     {
 | |
|       const TBill c(s, 3, 0x0);
 | |
|       if (c == conto)
 | |
|         return i;
 | |
|     }
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Trova nelle righe contabili un conto di contropartita per il conto dato
 | |
| int TPrimanota_application::bill2contr(const TBill& conto, char sezione) const
 | |
| {
 | |
|   TString_array& rows = cgs().rows_array();
 | |
|   const int num_rows = rows.items();
 | |
|   TBill c;                                // Conto corrente (Buona questa!)
 | |
|   for (int i = 0; i < num_rows; i++)
 | |
|   {
 | |
|     TToken_string& r = rows.row(i);
 | |
|     const real dare(r.get(0));
 | |
|     const char sez = dare.is_zero() ? 'A' : 'D';
 | |
|     if (sez == sezione)                   // Devo cercare sezione contraria
 | |
|       continue;
 | |
|     c.get(r, 3, 0x0);
 | |
|     if (conto == c)
 | |
|       return i;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Controlla se un conto e' usato nelle righe IVA                              
 | |
| int TPrimanota_application::bill_used(const TBill& conto) const
 | |
| {
 | |
|   TString_array& rows = ivas().rows_array();
 | |
|   TBill c;               // Conto corrente
 | |
|   int users = 0;
 | |
|   for (int i = rows.items(); i >= 0 ; i--)
 | |
|   {
 | |
|     TToken_string& row = rows.row(i);
 | |
|     if (!row.empty_items())
 | |
|     {                       
 | |
|       c.get(row, 6, 0x0);
 | |
|       if (conto == c) 
 | |
|         users++;
 | |
|     }  
 | |
|   }
 | |
|   return users;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Gestione sheet CG
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TSheet_field& TPrimanota_application::cgs() const
 | |
| {                                  
 | |
|   const TMask* m = _msk[_iva == nessuna_iva ? 1 : 2];
 | |
|   CHECK(m, "Null cgs() mask");
 | |
|   TSheet_field& s = (TSheet_field&)m->field(F_SHEETCG);
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| // Scrive l'importo imp nella opportuna colonna della riga n
 | |
| void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp)
 | |
| { 
 | |
|   TSheet_field& s = cgs();
 | |
|   imp.add_to(s.row(n), 0);
 | |
|   s.force_update(n);
 | |
| }
 | |
| 
 | |
| // Legge l'importo della riga n e lo ritorna col segno dovuto
 | |
| // Certified 100%
 | |
| TImporto TPrimanota_application::get_cgs_imp(int n)
 | |
| {     
 | |
|   TSheet_field& s = cgs();
 | |
|   
 | |
|   TImporto importo;
 | |
|   
 | |
|   const TMask& m = s.sheet_mask();
 | |
|   if (m.is_running() && s.selected() == n)
 | |
|   {
 | |
|     const TString& imp = m.get(CG_DARE);
 | |
|     if (imp.not_empty())
 | |
|       importo.set('D', real(imp));
 | |
|     else  
 | |
|       importo.set('A', real(m.get(CG_AVERE)));
 | |
|   }
 | |
|   else
 | |
|     importo = s.row(n);
 | |
|   
 | |
|   return importo;
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::add_cgs_imp(int n, const TImporto& imp)
 | |
| {
 | |
|   TImporto tot(get_cgs_imp(n));
 | |
|   tot += imp;       
 | |
|   tot.normalize();
 | |
|   set_cgs_imp(n, tot);
 | |
|   return tot.is_zero();
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::sub_cgs_imp(int n, const TImporto& imp)
 | |
| {
 | |
|   TImporto tot(get_cgs_imp(n));
 | |
|   tot -= imp; 
 | |
|   tot.normalize();
 | |
|   set_cgs_imp(n, tot);
 | |
|   return tot.is_zero();
 | |
| }
 | |
| 
 | |
| TImporto TPrimanota_application::real2imp(const real& r, char row_type)
 | |
| {   
 | |
|   bool dare;
 | |
|   if (row_type == 'S')
 | |
|   {
 | |
|     dare = causale().sezione_ritsoc() == 'D';
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     dare = causale().sezione_clifo() == 'D';
 | |
|     if (row_type != 'T' && row_type != 'F') 
 | |
|       dare = !dare;
 | |
|   }  
 | |
|   
 | |
|   TImporto importo(dare ? 'D' : 'A', r);
 | |
|   return importo;
 | |
| }
 | |
| 
 | |
| // Disabilita le celle della riga contabile n in base al suo tipo
 | |
| void TPrimanota_application::disable_cgs_cells(int n, char tipo)
 | |
| {
 | |
|   TSheet_field& cg = cgs();
 | |
| 
 | |
|   int first = 0, last = 0;    // Range di righe da disabilitare
 | |
|   switch(tipo)
 | |
|   {
 | |
|   case 'T':                   // Totale documento
 | |
|     if (causale().corrispettivi())
 | |
|     {
 | |
|       last = 2;
 | |
|     }    
 | |
|     else
 | |
|     {
 | |
|       last = 3;
 | |
|       cg.disable_cell(n, 5);
 | |
|       cg.disable_cell(n, 6);
 | |
|     }
 | |
|     break;
 | |
|   case 'A':                   // Abbuoni attivi
 | |
|   case 'C':                   // Differenza cambio
 | |
|   case 'D':                   // IVA Detraibile
 | |
|   case 'F':                   // Ritenute Fiscali
 | |
|   case 'L':                   // Contropartita delle spese
 | |
|   case 'N':                   // IVA Non detraibile
 | |
|   case 'P':                   // Abbuoni passivi
 | |
|   case 'R':                   // Ritenute professionali
 | |
|   case 'S':                   // Ritenute Sociali
 | |
|     last = 3;                 
 | |
|     break;          
 | |
|   case 'K':                   // Riga cliente/fornitore per saldaconto
 | |
|     if (curr_mask().is_running() && n == cg.items()-1) // Sono in inserimento di una riga nuova
 | |
|       break;
 | |
|     first = 2;  
 | |
|   case 'I':
 | |
|     last = 7;                 // Imponibile
 | |
|     break;
 | |
|   default:
 | |
|     last = 0;                 // Solo contabile
 | |
|     break;
 | |
|   }
 | |
|   
 | |
|   bool needs_update = FALSE;  
 | |
| 
 | |
|   if (last)
 | |
|   {
 | |
|     for (int i = first; i < last; i++)
 | |
|       cg.disable_cell(n, i);
 | |
|     needs_update = TRUE;  
 | |
|   }  
 | |
| 
 | |
|   COLOR back_color, fore_color;
 | |
|   type2colors(tipo, back_color, fore_color);
 | |
|   if (back_color != NORMAL_BACK_COLOR || fore_color != NORMAL_COLOR)
 | |
|   {
 | |
|     cg.set_back_and_fore_color(back_color, fore_color, n);
 | |
|     needs_update = TRUE;  
 | |
|   }
 | |
|     
 | |
|   if (needs_update)  
 | |
|     cg.force_update(n);
 | |
| }
 | |
| 
 | |
| void TPrimanota_application::reset_sheet_row(TSheet_field& s, int n)
 | |
| {
 | |
|   s.row(s.items());           // Append a new line
 | |
|   s.destroy(n);               // Remove line n
 | |
| }
 | |
| 
 | |
| int TPrimanota_application::set_cgs_row(int n, const TImporto& imp,
 | |
|                                         TBill& conto, const char* desc,
 | |
|                                         char tipo)
 | |
| {
 | |
|   TSheet_field& cg = cgs();
 | |
|   if (n < 0) n = cg.first_empty();
 | |
|   TToken_string& row = cg.row(n);
 | |
|   row = "";
 | |
|   imp.add_to(row, 0);
 | |
|   row.add(conto.string(0x3));
 | |
|   row.add("");                          // Codice decrizione
 | |
|   row.add(desc);                        // Descrizione aggiuntiva
 | |
|   
 | |
|   if (tipo == 'T')                      // Calcolo contropartita
 | |
|   {
 | |
|     TToken_string& irow = ivas().row(0);
 | |
|     TBill contro(irow, 5, 0x3);
 | |
|     if (contro.ok())                    // Errore MI3599
 | |
|       row.add(contro.string(0x3));
 | |
|     else  
 | |
|       row.add(" | | | | ");  
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     const int pos = type2pos('T');
 | |
|     if (pos >= 0)
 | |
|     {                         
 | |
|       TBill contro(cg.row(pos), 2, 0x3);
 | |
|       if (contro.ok())
 | |
|         row.add(contro.string(0x3));
 | |
|     }
 | |
|     else 
 | |
|       row.add(" | | | | ");  
 | |
|   }
 | |
| 
 | |
|   row << "| |" << tipo;
 | |
| 
 | |
|   disable_cgs_cells(n, tipo);
 | |
| 
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| 
 | |
| HIDDEN int compare_rows(const TObject** o1, const TObject** o2)
 | |
| {
 | |
|   // Totale, Rit.Fisc., Rit.Soc., da riga IVA, riga contabile, IVA detr., IVA non detr.
 | |
|   const char* const sort_order = "TFSI DNAPRC"; 
 | |
| 
 | |
|   const TToken_string* r1 = (const TToken_string*)*o1;
 | |
|   const TToken_string* r2 = (const TToken_string*)*o2;
 | |
|   const char c1 = app().row_type(*r1);
 | |
|   const char c2 = app().row_type(*r2);
 | |
|   return int(strchr(sort_order, c1) - strchr(sort_order, c2));
 | |
| }
 | |
| 
 | |
| HIDDEN bool can_remove(TToken_string& s)
 | |
| {     
 | |
|   const char* dare = s.get(0);
 | |
|   bool yes = dare == NULL ;
 | |
|   if (!yes)
 | |
|   {
 | |
|     if (*dare == '\0' || *dare == ' ' || strcmp(dare,"0") == 0)
 | |
|     {
 | |
|       const char* avere = s.get();
 | |
|       yes = (avere == NULL || *avere == '\0' || *avere == ' ' || strcmp(avere,"0") == 0);
 | |
|     }  
 | |
|   }
 | |
|   return yes;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TPrimanota_application::cgs_pack()
 | |
| { 
 | |
|   TString_array& rows = cgs().rows_array();
 | |
|   const bool pagamento = is_pagamento();
 | |
|   const long numreg = curr_mask().get_long(F_NUMREG);
 | |
| 
 | |
|   for (int i = rows.items()-1; i >= 0; i--)
 | |
|   {
 | |
|     TToken_string& r = rows.row(i);
 | |
|     if (can_remove(r))
 | |
|     {                                    
 | |
|       bool ok = TRUE;
 | |
|       if (pagamento && row_type(r) == 'K')
 | |
|       {
 | |
|         ok = !partite().utilizzata(numreg, i+1);
 | |
|         if (ok)
 | |
|           cg_notify(cgs(), i, K_DEL);
 | |
|       }  
 | |
|       if (ok) 
 | |
|         rows.destroy(i, TRUE);
 | |
|     }  
 | |
|   }  
 | |
|   if (!pagamento)                      // Il pagamento e' gia' ordinato
 | |
|     rows.TArray::sort(compare_rows);   // Pack and sort array
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TPrimanota_application::ci_sono_importi() const
 | |
| {
 | |
|   TString_array& rows = cgs().rows_array();
 | |
|   for (int i = 0; i < rows.items(); i++)
 | |
|   {
 | |
|     TToken_string& r = rows.row(i);
 | |
|     const real dare(r.get(0));
 | |
|     if (dare != ZERO) return TRUE;
 | |
|     const real avere(r.get());
 | |
|     if (avere != ZERO) return TRUE;
 | |
|   } 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| real TPrimanota_application::calcola_saldo() const
 | |
| {
 | |
|   real tdare, tavere;
 | |
|   TImporto saldaconto;
 | |
|   const bool pag = is_pagamento() && !_as400;
 | |
|   
 | |
|   TString_array& rows = cgs().rows_array();
 | |
|   const int max = rows.items();
 | |
|   for (int i = 0; i < max; i++)
 | |
|   {
 | |
|     TToken_string& r = rows.row(i);
 | |
|     const real dare(r.get(0));
 | |
|     const real avere(r.get());
 | |
|     
 | |
|     tdare += dare;
 | |
|     tavere += avere;
 | |
|     
 | |
|     if (pag)
 | |
|     {                                      
 | |
|       const char tipo = row_type(r);     
 | |
|       if (strchr("ACGKP", tipo) != NULL) // Abbuoni attivi, differenze cambio, 
 | |
|       {                                  // spese, clienti/fornitori, abbuoni passivi
 | |
|         const char sez = dare.is_zero() ? 'A' : 'D';
 | |
|         const TImporto importo(sez, sez == 'A' ? avere : dare);
 | |
|         saldaconto += importo;  
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   TMask& m = curr_mask();
 | |
|   const real sbilancio = abs(tdare)-abs(tavere);
 | |
|   const real absbilancio = abs(tdare - tavere);
 | |
|   switch (sbilancio.sign()) 
 | |
|   {                   
 | |
|   case +1: // Il dare supera l'avere in valore assoluto
 | |
|     m.set(F_DARE, absbilancio);
 | |
|     m.reset(F_AVERE);
 | |
|     break;
 | |
|   case -1: // L'avere supera il dare in valore assoluto
 | |
|     m.reset(F_DARE);
 | |
|     m.set(F_AVERE, absbilancio);
 | |
|     break;
 | |
|   default: // Sbilancio nullo
 | |
|     m.reset(F_DARE);
 | |
|     m.reset(F_AVERE);
 | |
|     break;
 | |
|   }
 | |
|   
 | |
|   if (pag)
 | |
|   { 
 | |
|     const char s(causale().sezione(2));    // Conto della cassa
 | |
|     const real t(m.get(F_TOTALE));
 | |
|     TImporto totdoc(s, t);
 | |
|     totdoc += saldaconto;
 | |
|     totdoc.normalize(s);
 | |
|     m.set(K_RESIDUO, totdoc.valore().string());
 | |
|   }
 | |
|   
 | |
|   return sbilancio;
 | |
| }
 | |
| 
 | |
| HIDDEN bool imptot_error(const TImporto& imptot, const TImporto& impsal, bool val)
 | |
| {   
 | |
|   bool ok = TRUE;
 | |
|   TImporto cassa(impsal); cassa.swap_section();
 | |
|   TImporto residuo(imptot); residuo -= cassa; residuo.normalize(imptot.sezione());
 | |
|   
 | |
|   if (!residuo.is_zero())
 | |
|   {                                         
 | |
|     const char* const pic = val ? ".3" : ".";
 | |
|     TPrimanota_application& a = app();
 | |
|     const TMask& m = a.curr_mask();
 | |
| 
 | |
|     TString msg(255);
 | |
|     msg << "Il totale documento ";
 | |
|     if (val) 
 | |
|       msg << "in valuta " << m.get(SK_VALUTA);
 | |
|     else
 | |
|       msg << "inserito";
 | |
|     msg << " e' " << imptot.valore().string(pic) << ' ' << imptot.sezione() << ",\n";
 | |
|     msg << "i pagamenti e le spese ammontano a " 
 | |
|         << cassa.valore().string(pic) << ' ' << cassa.sezione() << ",\n";
 | |
|     msg << "per cui il residuo e' " << residuo.valore().string(pic) << '.';              
 | |
|     
 | |
|     if (m.edit_mode() && impsal.is_zero())
 | |
|     {
 | |
|       msg << "\nSi desidera registrare ugualmente?";
 | |
|       ok = a.cgs().yesno_box(msg);
 | |
|     }    
 | |
|     else
 | |
|       ok = a.cgs().error_box(msg);
 | |
|   }
 | |
|   
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // Handler dello sheet di contabilita'
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::cg_handler(TMask_field& f, KEY k)
 | |
| {          
 | |
|   if (k == K_ENTER)
 | |
|   {             
 | |
|     TPrimanota_application& a = app();
 | |
|     const real saldo = a.calcola_saldo();
 | |
|     
 | |
|     if (saldo != ZERO)
 | |
|     {
 | |
|       const char* ss = saldo.string("."); 
 | |
|       if (*ss == '-') ss++;
 | |
|       return f.error_box("Il movimento e' sbilanciato di %s lire.", ss);
 | |
|     } 
 | |
|     
 | |
|     TMask& m = f.mask();
 | |
|     const bool paga = a.is_pagamento(); 
 | |
|     const bool nota = a.is_nota_credito() && m.field(F_NUMRIF).active(); 
 | |
|     const bool fatt = a.is_fattura() && m.page_enabled(2);
 | |
|     
 | |
|     const long numreg = m.get_long(F_NUMREG);
 | |
|     
 | |
|     const bool in_valuta = m.get(SK_VALUTA).not_empty();
 | |
|     TImporto saldaconto, saldaconto_val;
 | |
|     
 | |
|     TSheet_field& cg = a.cgs();
 | |
|     bool empty = TRUE;
 | |
|     for (int i = 0; i < cg.items(); i++)
 | |
|     {                        
 | |
|       TToken_string& r = cg.row(i);
 | |
|       TImporto importo; importo = r;
 | |
|       
 | |
|       if (!importo.is_zero())
 | |
|       {
 | |
|         const TBill c(r, 3, 0x0);
 | |
|         if (!c.ok()) 
 | |
|           return f.error_box("Il conto della riga %d non e' completo", i+1);
 | |
|         const TBill co(r, 10, 0x0);
 | |
|         if (!co.empty() && !co.ok()) 
 | |
|         {
 | |
|           const bool ok = f.yesno_box("La contropartita della riga %d non e' completa:\n"
 | |
|                                       "Si desidera continuare ugualmente?", i+1);
 | |
|           if (!ok) return FALSE;
 | |
|         }
 | |
|         
 | |
|         empty = FALSE;       
 | |
|         if (paga || nota)
 | |
|         {
 | |
|           const char tipo = row_type(r);
 | |
|           if (tipo == 'K' || tipo == 'T' || a._as400)
 | |
|           {                                               
 | |
|             const int currig = i+1;
 | |
|             const TImporto speso = a.partite().importo_speso(numreg, currig);
 | |
|             
 | |
|             bool errato = importo != speso;
 | |
|             if (errato && a._as400 && speso.is_zero())
 | |
|               errato = FALSE;
 | |
|               
 | |
|             if (errato)
 | |
|             {
 | |
|               TString msg(128);
 | |
|               msg << "L'importo sul saldaconto della riga " << currig << " e' " 
 | |
|                   << speso.valore().string("."); 
 | |
|               if (!speso.is_zero())    
 | |
|                 msg << (speso.sezione() == 'A' ? " Avere" : " Dare");
 | |
|               
 | |
|               bool ok = FALSE;    
 | |
|               if (m.edit_mode() && speso.is_zero())    
 | |
|               {
 | |
|                 msg << "\nSi desidera registrare ugualmente?";
 | |
|                 ok = f.yesno_box(msg);
 | |
|               }
 | |
|               else
 | |
|                 ok = f.error_box(msg);
 | |
|               if (!ok)  
 | |
|                 return FALSE;  
 | |
|             }
 | |
|           }
 | |
|           if (strchr("ACGKPT", tipo) != NULL)
 | |
|           {
 | |
|             saldaconto += importo;  
 | |
|             if (in_valuta)
 | |
|               saldaconto_val += a.partite().importo_speso(numreg, i+1, TRUE, 0x1);
 | |
|           }  
 | |
|         }  
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     if (empty)
 | |
|       return f.error_box("Il movimento non ha nessuna riga contabile con un importo");
 | |
|     
 | |
|     if ((paga || nota) && !a._as400)
 | |
|     {              
 | |
|       const char sez(a.causale().sezione(2));
 | |
|       const TImporto totdoc(sez, m.get_real(F_TOTALE));
 | |
|       bool ok = imptot_error(totdoc, saldaconto, FALSE);
 | |
|       
 | |
|       if (ok && in_valuta && !saldaconto.is_zero())                                                   
 | |
|       {
 | |
|         const TImporto totdoc_val(sez, m.get_real(SK_TOTDOCVAL));
 | |
|         ok = imptot_error(totdoc_val, saldaconto_val, TRUE);
 | |
|       }  
 | |
|       
 | |
|       if (!ok) 
 | |
|         return FALSE;
 | |
|     }
 | |
|     
 | |
|     if (fatt || nota)
 | |
|     {
 | |
|       TBill contocf; 
 | |
|       if (a.cerca_conto_cf(contocf) < 0)
 | |
|       {
 | |
|         TString msg(80); msg = "Non esiste una riga contabile riferita al ";
 | |
|         msg << (contocf.tipo() == 'C' ? "cliente" : "fornitore") << ' ';
 | |
|         msg << contocf.codclifo() << ":\n";
 | |
|         if (m.edit_mode())
 | |
|         {         
 | |
|           msg << "Si desidera eliminare il saldaconto?";
 | |
|           const bool kill = f.yesno_box(msg);
 | |
|           if (kill)
 | |
|           { 
 | |
|             if (fatt)                   // Se e' una fattura elimina il numero partita
 | |
|             {
 | |
|               m.reset(F_ANNORIF);
 | |
|               m.reset(F_NUMRIF);
 | |
|             }
 | |
|             else
 | |
|             {                           // Se e' una nota credito elimina il saldaconto
 | |
|               a.notify_cgline_deletion(-1);
 | |
|             }  
 | |
|           }
 | |
|           else
 | |
|             return FALSE;
 | |
|         }
 | |
|         else         
 | |
|         {
 | |
|           msg << "Impossibile registrare il saldaconto!";
 | |
|           return f.error_box(msg);
 | |
|         }  
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TPrimanota_application::generazione_righe_cg(int r)
 | |
| {   
 | |
|   TSheet_field& cg = cgs();
 | |
|   TToken_string& row = cg.row(r);
 | |
|   
 | |
|   if (can_remove(row))                      // Ignora righe senza importo
 | |
|     return;
 | |
| 
 | |
|   begin_wait();
 | |
| 
 | |
|   TImporto importo; importo = row; 
 | |
|   const bool causale_ok = causale().codice()[0] > ' ';  
 | |
| 
 | |
|   if (r == 0 && cg.row(1).empty_items())
 | |
|   {
 | |
|     TBill contro(row, 9, 0x3);              // Contropartita della prima riga
 | |
|     if (causale_ok && !contro.ok())
 | |
|     {
 | |
|       causale().bill(2, contro);            // Prendi contropartita dalla causale
 | |
|       if (contro.ok())
 | |
|       {
 | |
|         contro.add_to(row, 9, 0x3);
 | |
|         cg.force_update(r);
 | |
|       }  
 | |
|     }
 | |
|     if (contro.ok())
 | |
|     {
 | |
|       importo.swap_section();
 | |
|       set_cgs_row(1, importo, contro, "", ' ');
 | |
|       TBill conto(row, 2, 0x3);
 | |
|       conto.add_to(cg.row(1), 9, 0x3);
 | |
|       cg.force_update(1);  
 | |
|     }  
 | |
|   }                        
 | |
| 
 | |
|   if (causale_ok)
 | |
|   {
 | |
|     int first_not_empty = 0; 
 | |
|     for (int i = 0; i < r; i++)
 | |
|     {   
 | |
|       TToken_string& row = cg.row(i);
 | |
|       if (!can_remove(row))
 | |
|       {
 | |
|         first_not_empty = i;
 | |
|         break;
 | |
|       }  
 | |
|     }
 | |
|     
 | |
|     TBill conto(row, 2, 0x3);
 | |
|     if (first_not_empty == r)              // Sono la prima riga con importo ?
 | |
|     {            
 | |
|       int last = -1;
 | |
|       for (i = r+1; i < cg.items(); i++)   // Aggiorna tutte le altre contropartite
 | |
|       {                                    
 | |
|         TToken_string& rowi = cg.row(i);
 | |
|         int gruppo =  rowi.get_int(3);
 | |
|         if (gruppo != 0)                   // Considera righe con conto ...
 | |
|         {     
 | |
|           gruppo = rowi.get_int(10);
 | |
|           if (gruppo == 0)                 // ... e senza contropartita
 | |
|           { 
 | |
|             char sez = ' ';                // Calcola sezione D/A della riga i
 | |
|             if (cg.cell_disabled(i,0)) sez = 'A'; else
 | |
|               if (cg.cell_disabled(i,1)) sez = 'D';
 | |
|             
 | |
|             if (sez != ' ' && importo.sezione() != sez)  // Considera solo le sezioni opposte 
 | |
|             {   
 | |
|               conto.add_to(rowi, 9, 0x3);
 | |
|               cg.force_update(i);
 | |
|               if (last < 0) last = i;
 | |
|               else last = 0;
 | |
|             }  
 | |
|           }  
 | |
|         }
 | |
|       }
 | |
|       if (last > r)
 | |
|       {
 | |
|         importo.swap_section();
 | |
|         set_cgs_imp(last, importo);
 | |
|         
 | |
|         const int gruppo = row.get_int(10);             
 | |
|         if (gruppo == 0)                      // Se non ho contropartita ...
 | |
|         {
 | |
|           TBill contro(cg.row(last), 2, 0x3); // ... copiala dalla riga corrispondente
 | |
|           contro.add_to(row, 9, 0x3); 
 | |
|           cg.force_update(r);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {                  
 | |
|       TToken_string& first = cg.row(first_not_empty);
 | |
|       int gruppo = first.get_int(10);
 | |
|       if (gruppo == 0)                      // Se la prima riga non ha contropartita ...
 | |
|       {
 | |
|         conto.add_to(first, 9, 0x3);        // ... copiaci la mia partita
 | |
|         cg.force_update(first_not_empty);
 | |
|       }              
 | |
|       gruppo = row.get_int(10);             
 | |
|       if (gruppo == 0)                      // Se non ho contropartita ...
 | |
|       {
 | |
|         TBill contro(first, 2, 0x3);        // ... copiala dalla prima riga
 | |
|         contro.add_to(row, 9, 0x3); 
 | |
|         cg.force_update(r);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   end_wait();
 | |
| }
 | |
| 
 | |
| 
 | |
| int TPrimanota_application::crea_somma_spese(TImporto& imp)
 | |
| {
 | |
|   TConto cassa; causale().bill(2, cassa);
 | |
|   const TString80 desc(causale().desc_agg(2));
 | |
|   imp.swap_section(); imp.normalize();
 | |
|   const int r = set_cgs_row(-1, imp, cassa, desc, 'L');
 | |
|   cgs().force_update();
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k)
 | |
| {                            
 | |
|   static TImporto old_spesa;
 | |
|   static bool delete_l = FALSE;
 | |
|   
 | |
|   CHECKD(r >= 0, "Chi e' quel ca$$one che notifica la riga ", r);
 | |
|   
 | |
|   TPrimanota_application& a = app();
 | |
| 
 | |
|   if (k == K_CTRL + K_DEL)
 | |
|   {
 | |
|     if (delete_l)
 | |
|     {
 | |
|       const int l = type2pos('L');
 | |
|       CHECK(l >= 0, "Impossibile cancellare riga di tipo L");
 | |
|       cg.destroy(l);
 | |
|       delete_l = FALSE;
 | |
|     }
 | |
|     a.calcola_saldo();                      // Ricalcola saldo dopo cancellazione
 | |
|     return TRUE;                            // Ritorna subito, altrimenti crea riga vuota
 | |
|   }  
 | |
|   
 | |
|   if (k == K_INS)                           // La riga non esiste ancora
 | |
|     return TRUE;
 | |
|   
 | |
|   TToken_string& row = cg.row(r);
 | |
|   const char tipo = row_type(row);          // Tipo della riga in esame
 | |
| 
 | |
|   switch(k)
 | |
|   {                             
 | |
|   case K_SPACE:
 | |
|     if (tipo == 'G')
 | |
|       old_spesa = row;
 | |
|     break;  
 | |
|   case K_TAB:
 | |
|     cg.sheet_mask().enable(DLG_DELREC, tipo <= ' ' || tipo == 'K' || tipo == 'G');
 | |
|     break;
 | |
|   case K_DEL:                  
 | |
|     if (tipo == 'G')
 | |
|     {
 | |
|       row.add("", 0); 
 | |
|       row.add("", 1);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (tipo == 'K')
 | |
|       {
 | |
|         a.notify_cgline_deletion(r+1);
 | |
|       }  
 | |
|       break;  
 | |
|     }  
 | |
|   case K_ENTER:   
 | |
|     if (tipo == 'G')
 | |
|     {       
 | |
|       TImporto growth; growth = row; growth -= old_spesa;
 | |
|       if (!growth.is_zero())
 | |
|       {
 | |
|         const int s = type2pos('L');
 | |
|         if (s < 0)
 | |
|           a.crea_somma_spese(growth);
 | |
|         else
 | |
|           delete_l = a.sub_cgs_imp(s, growth);
 | |
|       }    
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (a.iva() == nessuna_iva && !a.is_saldaconto())        
 | |
|         a.generazione_righe_cg(r);
 | |
|     }  
 | |
|     if (k == K_ENTER)
 | |
|       a.calcola_saldo();             // Altrimenti ci pensa CTRL-DEL
 | |
|     break;
 | |
|   case K_CTRL+K_INS:                 // Post inserimento
 | |
|     if (a.is_pagamento())
 | |
|     {  
 | |
|       const char tipo = cg.mask().get(SK_TIPORIGA)[0];
 | |
|       if (tipo == 'K' || tipo == 'G') 
 | |
|       {                             
 | |
|         const int k = tipo == 'K' ? 1 : RIGA_SPESE;      
 | |
|         TBill conto; a.causale().bill(k, conto);
 | |
|         const TString80 desc(a.causale().desc_agg(k));
 | |
|         const char sez = a.causale().sezione(k);
 | |
|         const real imp(cg.mask().get(K_RESIDUO));
 | |
|         TImporto importo(sez, imp);
 | |
|         a.set_cgs_row(r, importo, conto, desc, tipo);
 | |
|         
 | |
|         if (tipo == 'K')
 | |
|         {     
 | |
|           for (int i = 0; i < r; i++)
 | |
|           {
 | |
|             const TToken_string& row = cg.row(i);
 | |
|             if (row_type(row) != 'K') 
 | |
|             {
 | |
|               cg.swap_rows(r, i);
 | |
|               cg.force_update();
 | |
|               cg.select(i, FALSE);
 | |
|               break;
 | |
|             }  
 | |
|           }  
 | |
|         }   
 | |
|         else
 | |
|         {
 | |
|           if (!importo.is_zero())
 | |
|           {
 | |
|             const int s = type2pos('L');
 | |
|             if (s < 0)           
 | |
|               a.crea_somma_spese(importo);
 | |
|             else
 | |
|               a.sub_cgs_imp(s, importo);
 | |
|           }  
 | |
|         }  
 | |
|         a.calcola_saldo();
 | |
|       }
 | |
|     }    
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }  
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::descr_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   if (k == K_TAB && f.focusdirty())
 | |
|   {
 | |
|     if (app().iva() != nessuna_iva)
 | |
|     { 
 | |
|       const int first = type2pos('T'); 
 | |
|       if (first >= 0)
 | |
|       {
 | |
|         TSheet_field& cg = app().cgs();
 | |
|         const TString80 old = cg.row(first).get(8);
 | |
|         if (old.blank())
 | |
|         {
 | |
|           cg.row(first).add(f.get(), 8);
 | |
|           cg.force_update(first);
 | |
|         }  
 | |
|       }  
 | |
|     }  
 | |
|   }
 | |
|   if (k == K_ENTER && f.get().empty())
 | |
|   {
 | |
|     if (f.mask().get(F_CODCAUS).empty())
 | |
|       return f.error_box("La descrizione del documento e' necessaria in mancanza della causale");
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler per le colonne 'Dare' e 'Avere' dello sheet contabile.  
 | |
| // Scrivendo qualcosa in dare (101) cancella l'importo in avere (102) e viceversa
 | |
| bool TPrimanota_application::dareavere_handler(TMask_field& f, KEY k)
 | |
| {          
 | |
|   TPrimanota_application& a = app();
 | |
|   TSheet_field& cgs = a.cgs();
 | |
|   const int currig = cgs.selected();
 | |
|   
 | |
|   if (k == K_F8 && a.is_pagamento())
 | |
|   {                        
 | |
|     const long numreg = a.curr_mask().get_long(F_NUMREG);
 | |
|     const TImporto speso = a.partite().importo_speso(numreg, currig+1);
 | |
|     
 | |
|     const char* ss = speso.valore().string();
 | |
|     TMask& m = f.mask();                
 | |
|     m.set(CG_DARE,  speso.sezione() == 'D' ? ss : ""); 
 | |
|     m.set(CG_AVERE, speso.sezione() == 'A' ? ss : "");
 | |
|     
 | |
|     if (!m.is_running())
 | |
|     {
 | |
|       speso.add_to(cgs.row(currig), 0);             // Aggiorna riga sheet
 | |
|       a.calcola_saldo();                            // Aggiorna saldo e residuo
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   if (k == K_TAB && f.focusdirty())
 | |
|   {                               
 | |
|     const TString& val = f.get();
 | |
|     TToken_string& row = cgs.row(currig);
 | |
|     row.add(val, f.dlg() - CG_DARE);               // Aggiorno stringa sheet
 | |
| 
 | |
|     if (val.not_empty())
 | |
|     {
 | |
|       // Calcola id del campo da resettare
 | |
|       const int id = f.dlg() == CG_DARE ? CG_AVERE : CG_DARE;  
 | |
|       f.mask().reset(id);                         // Aggiorna maschera e ...
 | |
|       row.add("", id - CG_DARE);                  // ... riga dello sheet
 | |
|     }  
 | |
|     
 | |
|     if (!f.mask().is_running())
 | |
|       a.calcola_saldo();                          // Aggiorna saldo e residuo
 | |
|   }
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| TSheet_field& TPrimanota_application::pags() const
 | |
| {                                         
 | |
|   CHECK(is_fattura(), "Can't use rate sheet without a fattura");         
 | |
|   const int pos = _msk[2]->id2pos(FS_RATESHEET);   
 | |
|   CHECK(pos > 0, "Can't find rate sheet");
 | |
|   TSheet_field& s = (TSheet_field&)_msk[2]->fld(pos);
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Gestione sheet IVA
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Ritorna lo sheet delle righe IVA
 | |
| // Certified 100%
 | |
| TSheet_field& TPrimanota_application::ivas() const
 | |
| {
 | |
|   TSheet_field& s = (TSheet_field&)_msk[2]->field(F_SHEETIVA);
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| /*
 | |
| TBill& TPrimanota_application::ivas_bill(TBill& c)
 | |
| {
 | |
|   if (iva() == iva_vendite)
 | |
|   {
 | |
|     const int spric = c.tipo_cr();
 | |
|     if (spric == 2 || spric == 3)
 | |
|     {
 | |
|       const TString& td = causale().tipo_doc();
 | |
|       if (td == "FV" || td == "NC" || td == "ND") 
 | |
|         c.tipo_cr(4);
 | |
|     }
 | |
|   } 
 | |
|   return c;
 | |
| } 
 | |
| */
 | |
| 
 | |
| // Gestione del campo imponibile sullo sheet iva
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::imponibile_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.dirty())
 | |
|   { 
 | |
|     TMask& m = f.mask();
 | |
|     TString16 iva(m.get(102));        
 | |
|     if (iva.empty())
 | |
|     {
 | |
|       iva = app().curr_mask().get(F_CODIVA);
 | |
|       m.set(102, iva);
 | |
|     }  
 | |
|     if (iva.not_empty() && !app().causale().corrispettivi())
 | |
|     {
 | |
|       const real& percent = cod2IVA(m);
 | |
|       const real imponibile(f.get());
 | |
|       real imposta = abs(imponibile) * percent / 100.0; imposta.ceil();
 | |
|       if (imponibile.sign() < 0) imposta = -imposta;
 | |
|       m.set(104, imposta);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Gestione del codice IVA sullo sheet iva
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::codiva_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (!suspended_handler(f, key))
 | |
|     return FALSE;
 | |
| 
 | |
|   if (key == K_TAB && f.dirty())
 | |
|   {
 | |
|     TMask& m = f.mask();
 | |
|     
 | |
|     if (m.get_int(107) == 0)
 | |
|     { 
 | |
|       TCodiceIVA iva(f.get());
 | |
|       TBill b; app().IVA2bill(iva, b);
 | |
|       
 | |
|       char cr[2] = { b.tipo_cr() + '0', '\0' };
 | |
|       m.set(105, *cr > '0' ? cr : "");
 | |
|       
 | |
|       const char tipo[2] = { b.tipo(), '\0' };
 | |
|       m.set(106, tipo);
 | |
|       m.set(107, b.gruppo());
 | |
|       m.set(108, b.conto());
 | |
|       const short id = b.tipo() == 'C' ? 209 : (b.tipo() == 'F' ? 309 : 109);
 | |
|       m.set(id, b.sottoconto());
 | |
|       m.set(id+1, b.descrizione());
 | |
|     }
 | |
|     
 | |
|     TMask_field& im = m.field(101);
 | |
|     im.set_dirty();
 | |
|     im.on_hit();
 | |
|   } 
 | |
|   else
 | |
|   {
 | |
|     if (key == K_ENTER)
 | |
|     { 
 | |
|       if (f.get().empty() && f.mask().get(101).not_empty())
 | |
|         return f.error_box("Codice IVA obbligatorio");
 | |
|     }
 | |
|   }  
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Gestione del codice detrazione sullo sheet iva
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::detrazione_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.dirty() && app().iva() == iva_acquisti)
 | |
|   {
 | |
|     TMask_field& ci = f.mask().field(101);
 | |
|     ci.set_dirty();
 | |
|     ci.on_hit();
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Gestione del campo imposta sullo sheet iva
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::imposta_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if ((key == K_ENTER || key == K_TAB) && f.dirty())
 | |
|   {
 | |
|     const real imponibile(f.mask().get(101));
 | |
|     const real percent = app().causale().corrispettivi() ? ZERO : cod2IVA(f.mask());
 | |
|     real imposta = abs(imponibile) * percent / 100.0; 
 | |
|     imposta.ceil();
 | |
|     if (imponibile.sign() < 0) imposta = -imposta;
 | |
|     
 | |
|     const real val(f.get());
 | |
|     if (val != imposta)
 | |
|     {         
 | |
|       f.warning_box("L'imposta dovrebbe essere %s", (const char*)imposta.string("."));
 | |
|     }
 | |
|   } else
 | |
|     if (key == K_F8)
 | |
|     {
 | |
|       real imposta(f.get());
 | |
|       if (imposta.is_zero())
 | |
|       {
 | |
|         real imponibile(f.mask().get(101));
 | |
|         const real& percent = cod2IVA(f.mask());
 | |
|         imposta = scorpora(imponibile, percent);
 | |
|         f.mask().set(101, imponibile.string());
 | |
|         f.set(imposta.string());
 | |
|       }
 | |
|       else 
 | |
|         f.warning_box("Cancellare l'imposta (tasto F2) prima di effettuare lo scorporo");  
 | |
|     }
 | |
| 
 | |
|   return TRUE;
 | |
| }    
 | |
| 
 | |
| 
 | |
| // Calcola il totale degli imponibili e delle imposte e aggiorna
 | |
| // i corrispondenti campi della maschera
 | |
| // Certified 99%
 | |
| real TPrimanota_application::calcola_imp() const
 | |
| {                   
 | |
|   TArray& rows = ivas().rows_array();
 | |
| 
 | |
|   real imponibili, imposte;
 | |
|   for (int r = rows.items()-1; r >= 0; r--)
 | |
|   {
 | |
|     TToken_string& row = (TToken_string&)rows[r];
 | |
|     imponibili += real(row.get(0));  
 | |
|     imposte += real(row.get(3));
 | |
|   }
 | |
|   
 | |
|   TMask& m = curr_mask();
 | |
|   m.set(F_IMPONIBILI, imponibili);
 | |
|   m.set(F_IMPOSTE, imposte);
 | |
|   
 | |
|   // Se e' attiva la terza pagina allora riporta i totali in testata
 | |
|   if (is_fattura())
 | |
|   {                              
 | |
|     real tot(m.get(F_TOTALE)); tot -= imposte;
 | |
|     m.set(FS_IMPONIBILI, tot);
 | |
|     m.set(FS_IMPOSTE, imposte);
 | |
|   }
 | |
|   
 | |
|   return imponibili+imposte;
 | |
| }
 | |
|                  
 | |
| // Elimina dallo sheet le righr iva senza importi (imponibile e imposta)
 | |
| // Certified 99%
 | |
| void TPrimanota_application::ivas_pack()
 | |
| {
 | |
|   TString_array& rows = ivas().rows_array();
 | |
|   
 | |
|   const int max = rows.items();
 | |
|   for (int i = 0; i < max; i++)
 | |
|   {
 | |
|     TToken_string& r = rows.row(i);
 | |
|     const real imponibile(r.get(0));
 | |
|     if (imponibile != ZERO) continue;
 | |
|     const real imposta(r.get(3));
 | |
|     if (imposta != ZERO) continue;
 | |
|     rows.destroy(i, FALSE);
 | |
|   }
 | |
| 
 | |
|   rows.pack();           // Pack array
 | |
| }
 | |
| 
 | |
| // Certified 50%
 | |
| bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k)
 | |
| {
 | |
|   static int oldpos,oldposiva;
 | |
|   static TImporto oldimp, oldiva;
 | |
|   
 | |
|   TPrimanota_application& a = app();
 | |
|   if (a._as400) 
 | |
|     return TRUE;
 | |
|                 
 | |
|   if (k == K_INS || k == K_CTRL+K_DEL)              
 | |
|     return TRUE;
 | |
|                 
 | |
|   TToken_string& row = iva.row(r);
 | |
|   const TCausale& cau = a.causale();
 | |
| 
 | |
|   if (k == K_SPACE)
 | |
|   {                                                                               
 | |
|     oldimp = a.real2imp(real(row.get(0)), 'I');      // Imponibile
 | |
|     oldiva = a.real2imp(real(row.get(3)), 'I');      // Imposta
 | |
|     
 | |
|     if (oldiva.is_zero() && cau.corrispettivi())     // In caso di corrispettivi ...
 | |
|     {               
 | |
|       const TString zanicchi(row.get(1));            // Codice IVA
 | |
|       const TCodiceIVA i(zanicchi);          
 | |
|       oldiva.valore() = i.scorpora(oldimp.valore()); // ... scorpora imposta dall'imponibile
 | |
|     }  
 | |
|     
 | |
|     const char tipod = detraibile(row) ? 'D' : 'N';        
 | |
|     oldposiva = type2pos(tipod);                                      
 | |
| 
 | |
|     if (oldposiva < 0 && !oldiva.is_zero())
 | |
|     {
 | |
|       const int ri = tipod == 'D' ? RIGA_IVA_DETRAIBILE : RIGA_IVA_NON_DETRAIBILE;           
 | |
|       TBill c; cau.bill(ri, c); 
 | |
|       if (c.ok())
 | |
|       {
 | |
|         const TString80 d(cau.desc_agg(ri));
 | |
|         oldposiva = a.set_cgs_row(-1, a.real2imp(ZERO, 'I'), c, d, tipod);
 | |
|       }  
 | |
|       else 
 | |
|         if (ri == 4)                           // Se non esiste il conto IVA indetraibile ...
 | |
|         {                                      // ... somma imponibile e imposta
 | |
|           oldimp += oldiva;                    
 | |
|           oldiva = 0.0;                             
 | |
|         }
 | |
|     }  
 | |
|     
 | |
|     TBill oldconto(row, 6, 0x0);               // g/c/s 6 7 8
 | |
|     if (oldconto.ok())
 | |
|     {
 | |
|       oldpos = bill2pos(oldconto, 'I');
 | |
|       if (oldpos < 0)
 | |
|       {                      
 | |
|         const TString d(cau.desc_agg(2));
 | |
|         oldpos = a.set_cgs_row(-1, a.real2imp(ZERO, 'I'), oldconto, d, 'I');
 | |
|       }  
 | |
|     } 
 | |
|     else 
 | |
|       oldpos = -1;                             // Se il conto e' incompleto ignoralo
 | |
|   }
 | |
|   if (k == K_DEL)                              // Cancellazione di una riga
 | |
|   {
 | |
|     row.add("0", 0);                           // Azzera imponibile
 | |
|     row.add("0", 3);                           // Azzera imposta
 | |
|     k = K_ENTER;                               // Elegante o Sporco trucco (dipende dai gusti!)
 | |
|   }
 | |
|   if (k == K_ENTER)
 | |
|   {   
 | |
|     int delimp = -1, deliva = -1;              // Eventuali righe contabili da cancellare
 | |
|     if (oldpos >= 0)                           // Se il conto esisteva anche prima ...
 | |
|     {                                          // sottrai il vecchio imponibile
 | |
|       TImporto i(a.get_cgs_imp(oldpos));
 | |
|       i -= oldimp;
 | |
|       a.set_cgs_imp(oldpos, i);
 | |
|       if (i.is_zero()) delimp = oldpos;
 | |
|     } 
 | |
|     if (oldposiva >= 0)                        // Se conto IVA esisteva anche prima ...
 | |
|     {                                          // sottrai la vecchia imposta
 | |
|       TImporto i(a.get_cgs_imp(oldposiva));
 | |
|       i -= oldiva;
 | |
|       a.set_cgs_imp(oldposiva, i);
 | |
|       if (i.is_zero()) deliva = oldposiva;
 | |
|     }
 | |
| 
 | |
|     real imponibile(row.get(0));               // Nuovo imponibile
 | |
|     real imposta(row.get(3));                  // Nuova imposta
 | |
|     
 | |
|     if (imposta.is_zero() && cau.corrispettivi())   // In caso di corrispettivi ...
 | |
|     {               
 | |
|       const TString zanicchi(row.get(1));                         
 | |
|       const TCodiceIVA i(zanicchi);          
 | |
|       imposta = i.scorpora(imponibile);        // ... scorpora imposta dall'imponibile
 | |
|     }  
 | |
|     
 | |
|     TBill conto(row, 5, 0x3);
 | |
|     int newpos = bill2pos(conto, 'I');         // Riga in cui andra' l'imponibile
 | |
|     
 | |
|     const bool detrarre = detraibile(row);     // Determina se IVA detraibile
 | |
|     
 | |
|     // Calcola riga causale col conto opportuno
 | |
|     const int ri = detrarre ? RIGA_IVA_DETRAIBILE : RIGA_IVA_NON_DETRAIBILE;           
 | |
|     TBill contoiva;  cau.bill(ri, contoiva);
 | |
|     
 | |
|     if (!detrarre && !contoiva.ok())           // Se non c'e' il conto IVA indetraibile ...
 | |
|     {                                          // ... somma imponibile e imposta
 | |
|       imponibile += imposta;                   
 | |
|       imposta = 0.0;
 | |
|     }
 | |
|     
 | |
|     const TImporto newimp = a.real2imp(imponibile, 'I');
 | |
|     
 | |
|     // Aggiorna conto sulla riga contabile
 | |
|     if (newpos < 0)
 | |
|     {
 | |
|       if (delimp >= 0)       
 | |
|       {
 | |
|         a.reset_cgs_row(delimp);           // Cancella vecchia riga
 | |
|         if (deliva > delimp) deliva--;
 | |
|       }  
 | |
|       
 | |
|       if (conto.ok() && !newimp.is_zero())        // Se c'e' imponibile ...
 | |
|       {                                        // crea una nuova riga contabile
 | |
|         const TString d(cau.desc_agg(2));
 | |
|         a.set_cgs_row(-1, newimp, conto, d, 'I');
 | |
|       }  
 | |
|     }  
 | |
|     else
 | |
|     {
 | |
|       const bool empty = a.add_cgs_imp(newpos, newimp);
 | |
|       if (empty)                               // Se la riga si e' azzerata ...
 | |
|       {                                        // ... cancellala
 | |
|         a.reset_cgs_row(newpos);
 | |
|         newpos = -1;
 | |
|       }
 | |
|     }  
 | |
|     oldimp = newimp; 
 | |
|     oldpos = newpos;
 | |
|     
 | |
|     // Aggiorna conto IVA sulla riga contabile
 | |
| 
 | |
|     const char tipod = detrarre ? 'D' : 'N';
 | |
|     int newposiva = type2pos(tipod);
 | |
| 
 | |
|     if (deliva >= 0 && newposiva != deliva)                 // E' cambiato il tipo d'imposta
 | |
|       a.reset_cgs_row(deliva);                              // Azzera il vecchio tipo se necessario
 | |
|     
 | |
|     const TImporto newiva = a.real2imp(imposta, 'I');
 | |
|     if (newposiva < 0)
 | |
|     {                                          
 | |
|       if (!imposta.is_zero())                               // Se  c'e' imposta ...
 | |
|       {                                                     // ... crea nuova riga per l'IVA
 | |
|         const TString d(cau.desc_agg(ri));
 | |
|         newposiva = a.set_cgs_row(-1, newiva, contoiva, d, tipod);
 | |
|       }  
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       const bool empty = a.add_cgs_imp(newposiva, newiva);
 | |
|       if (empty)                                    // Se l'imposta si e' azzerata ...
 | |
|       {
 | |
|         a.reset_cgs_row(newposiva);                 // ... cancellala
 | |
|         newposiva = -1;
 | |
|       }  
 | |
|     }
 | |
| 
 | |
|     oldiva    = newiva;         
 | |
|     oldposiva = newposiva;   
 | |
|   
 | |
|     TMask& m = a.curr_mask();                                   
 | |
|     if (r == 0)                             // Se cambio la prima riga ...
 | |
|     {
 | |
|       a.add_cgs_tot(m);                     // ... ricalcola conti e imponibili
 | |
|     }  
 | |
|     else
 | |
|     {                                                                 
 | |
|       a.calcola_saldo();                    // Calcola sbilancio
 | |
|       a.calcola_imp();                      // Calcola imponibili
 | |
|     }
 | |
|     
 | |
|     if (a.is_fattura() && m.insert_mode())
 | |
|     {          
 | |
|       TPagamento& pag = a.pagamento();                         
 | |
|       const TValuta cambio(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
 | |
|       const bool inv = cambio.in_valuta();
 | |
|       real imposta, imponibile;              
 | |
|       if (inv)
 | |
|       {         
 | |
|         const real il(m.get(F_IMPOSTE));
 | |
|         imposta = cambio.lit2val(il);
 | |
|         imponibile = m.get_real(SK_TOTDOCVAL) - imposta;   
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         imposta = m.get_real(F_IMPOSTE);   
 | |
|         imponibile = m.get_real(F_TOTALE) - imposta;   
 | |
|       }
 | |
|       imposta.round(pag.round(inv)); imponibile.round(pag.round(inv));
 | |
|       real pimposta(pag.imposta(inv)); real pimponibile(pag.imponibile(inv));
 | |
|       pimposta.round(pag.round(inv)); pimponibile.round(pag.round(inv));
 | |
|       
 | |
|       if (pimposta != imposta || pimponibile != imponibile) 
 | |
|         a.set_scadenze(m);                // Ricalcola rate 
 | |
|     }
 | |
|   }                                                         
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler dello sheet
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::iva_handler(TMask_field& f, KEY k)
 | |
| {  
 | |
|   if ((k == K_TAB && !f.mask().is_running()) || k == K_ENTER)
 | |
|   {
 | |
|     const real imp = app().calcola_imp();
 | |
|     if (k == K_ENTER)
 | |
|     {
 | |
|       const real tot = app().totale_documento();
 | |
|       if (imp != tot)
 | |
|       {
 | |
|         const TString t(tot.string("."));
 | |
|         const TString i(imp.string("."));
 | |
|         return error_box("La somma del totale documento e delle ritenute (%s) e' diverso dalla " 
 | |
|                          "somma degli imponibili e delle imposte (%s)", (const char*)t, (const char*)i);
 | |
|       }  
 | |
| 
 | |
|       TSheet_field& iva = app().ivas();
 | |
|       for (int i = 0; i < iva.items(); i++)
 | |
|       {
 | |
|         TToken_string& row = iva.row(i);
 | |
|         const real im(row.get(0)); 
 | |
|         if (!im.is_zero())
 | |
|         {                            
 | |
|           const TFixed_string codiva = row.get(1);
 | |
|           if (codiva.blank())
 | |
|             return error_box("Il codice IVA della riga %d e' obbligatorio", i+1);
 | |
|         
 | |
|           TBill c(row, 5, 0x1);
 | |
|           if (!c.ok() || !c.find()) 
 | |
|             return error_box("Il conto della riga iva %d e' errato o incompleto", i+1);
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Il gruppo non possiede una ricerca propria per cui se viene variato richiama
 | |
| // quella del conto.
 | |
| bool TPrimanota_application::cg_gruppo_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|   {
 | |
|     TEdit_field& conto = f.mask().efield(f.dlg()+1);
 | |
|     const TRectype& curr = conto.browse()->cursor()->curr();
 | |
|     if (curr.get(RMV_GRUPPO) != f.get()) // Se non e' gia' posizionato ...
 | |
|       conto.check(RUNNING_CHECK);        // ... forza ricerca sul conto
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::cg_conto_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   bool ok = TRUE;
 | |
|   
 | |
|   if (key == K_ENTER)
 | |
|   {                          
 | |
|     TMask& m = f.mask();
 | |
|     if (m.get(CG_ROWTYPE)[0] == 'T' && !app().causale().corrispettivi())  
 | |
|     {
 | |
|       const char tipo = app().clifo();        // Tipo conto richiesto dal movimento
 | |
|       char cf = m.get(f.dlg()-2)[0]; 
 | |
|       if (cf < ' ') cf = ' ';                 // Tipo conto della riga
 | |
|       if (cf != tipo)                         // Incongruenza!
 | |
|       {
 | |
|         const char* d = tipo == 'C' ? "clienti" : "fornitori";
 | |
|         ok = f.error_box("La riga totale richiede un conto %s.", d);
 | |
|       }                   
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // Gestore del sottoconto dello sheet IVA
 | |
| // Attenzione questo handler e' agganciato anche alla descrizione del sottoconto
 | |
| bool TPrimanota_application::iva_sottoconto_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (!suspended_handler(f, key))
 | |
|     return FALSE;
 | |
| 
 | |
|   if (key == K_TAB && f.dirty())
 | |
|   {                                          
 | |
|     TMask& m = f.mask();
 | |
|     const TEdit_field& e = (const TEdit_field&)f;        
 | |
|     const TRectype& piano = e.browse()->cursor()->curr();
 | |
|     int spric = piano.get_int("TIPOSPRIC");
 | |
|     
 | |
|     if (app().iva() == iva_vendite)
 | |
|     {
 | |
|       const TCausale& caus = app().causale();
 | |
|       if (spric == 2 || spric == 3)
 | |
|       {
 | |
|         const TString& td = caus.tipo_doc();
 | |
|         if (td == "FV" || td == "NC" || td == "ND") 
 | |
|           spric = 4;
 | |
|       }                         
 | |
|     }
 | |
| 
 | |
|     TString s; if (spric > 0) s << spric;
 | |
|     m.set(105, s, TRUE);       // Setta il campo spesa-ricavo della riga IVA
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::sheet_clifo_handler(TMask_field& f, KEY k)
 | |
| {
 | |
|   if (!suspended_handler(f, k))
 | |
|     return FALSE;
 | |
|   
 | |
|   if (k == K_TAB || k == K_ENTER)
 | |
|   {
 | |
|     const long codice = atol(f.get());
 | |
|     if (codice > 0L)
 | |
|     {
 | |
|       TMask& m = f.mask();
 | |
|       const short cid  = 100 + (f.dlg() % 100) -1;
 | |
|       const short gid  = cid-1;
 | |
|       const int conto  = m.get_int(cid);
 | |
|       const int gruppo = m.get_int(gid);
 | |
|       if (gruppo == 0 && conto == 0)
 | |
|       {
 | |
|         TBill c(0, 0, codice, f.dlg() > 300 ? 'F' : 'C');
 | |
|         m.set(f.dlg()+1, c.descrizione());  // Carica gruppo e conto
 | |
|         if (c.ok())
 | |
|         {
 | |
|           m.set(gid-1, c.tipo() == 'C' ? "C" : "F");
 | |
|           m.set(gid, c.gruppo());
 | |
|           m.set(cid, c.conto());
 | |
|         }  
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Handlers dei campi della testata
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Handler of the F_NUMREG field on the query mask
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::num_handler(TMask_field& f, KEY key)
 | |
| {                       
 | |
|   if (key == K_TAB && f.to_check(key, TRUE))
 | |
|   {                    
 | |
|     TPrimanota_application& a = app();    
 | |
|     TMask& m = f.mask();
 | |
|     
 | |
|     a._skip_giornale_check = FALSE;
 | |
|     a._skip_bollato_check  = FALSE;
 | |
|     
 | |
|     const long max = a._lastreg+1;
 | |
|     const long num = f.empty() ? max : atol(f.get());
 | |
|     if (num < max)
 | |
|     {
 | |
|       if (a.find(1))
 | |
|       {
 | |
|         const TLocalisamfile& mov = a._rel->lfile();     
 | |
|         bool ok = TRUE;
 | |
|         
 | |
|         if (mov.get_bool(MOV_STAMPATO))
 | |
|         {
 | |
|           ok = f.yesno_box("Il movimento e' gia' stato stampato sul libro giornale:\n"
 | |
|                            "si desidera continuare ugualmente?");
 | |
|           a._skip_giornale_check = ok;              
 | |
|         }                
 | |
|         
 | |
|         if (ok && mov.get_bool(MOV_REGST))
 | |
|         {
 | |
|           ok = f.yesno_box("Il movimento e' gia' stato stampato sul bollato:\n"
 | |
|                            "si desidera continuare ugualmente?");
 | |
|           a._skip_bollato_check = ok;                            
 | |
|         }
 | |
|         
 | |
|         if (ok && mov.get_bool(MOV_INVIATO))
 | |
|         {                  
 | |
|           ok = f.yesno_box("Il movimento e' stato inviato ad un'altra contabilita':\n"
 | |
|                            "si desidera continuare ugualmente?");
 | |
|         }
 | |
|         
 | |
|         if (ok)    
 | |
|         {          
 | |
|           // Riempie a mano i campi necessari nel caso non sia stato usata la ricerca F9
 | |
|           m.set(F_DATAREG,  mov.get(MOV_DATAREG), TRUE);     
 | |
|           // DATACOMP new way
 | |
|           // m.set(F_DATACOMP, mov.get("DATACOMP"), TRUE);  
 | |
|           m.set(F_CODCAUS,  mov.get(MOV_CODCAUS));
 | |
| 
 | |
|           f.set_focusdirty(FALSE);
 | |
|           ok = m.stop_run(K_AUTO_ENTER);
 | |
|         }  
 | |
|         else
 | |
|         {
 | |
|           m.reset(F_NUMREG);
 | |
|           if (a.lnflag())
 | |
|             m.stop_run(K_FORCE_CLOSE);
 | |
|         }
 | |
|         return ok;
 | |
|       }  
 | |
|     }
 | |
|     else if (num > max)
 | |
|     {
 | |
|       f.set(format("%ld", max));
 | |
|       return f.error_box("Non e' possibile inserire movimenti superiori al %ld", max);
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of the F_CODCAUS field on the query mask
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::caus_query_handler(TMask_field& f, KEY key)
 | |
| {                  
 | |
|   const TMask& m = f.mask();
 | |
|   if (!m.is_running()) return TRUE;
 | |
| 
 | |
|   if (f.to_check(key))
 | |
|   {
 | |
|     const TString cau = f.get();
 | |
|     const int ann = m.get_int(F_ANNOIVA);
 | |
|     
 | |
|     const TipoIVA i = app().cau2IVA(cau, ann);    // Cerca causale e suo tipo
 | |
|     if (i != iva_errata)
 | |
|     {
 | |
|       const bool ok = suspended_handler(f, key);  // Controlla sospensione
 | |
|       if (ok && key == K_TAB)
 | |
|       {
 | |
|         f.set_focusdirty(FALSE);
 | |
|         return f.mask().stop_run(K_INS);                 // Entra in modo inserimento
 | |
|       }  
 | |
|     } 
 | |
|     else 
 | |
|     {
 | |
|       return error_box("Causale non presente in archivio");
 | |
|     }
 | |
|   } 
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Handler of the F_CODCAUS field on the modify mask
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::caus_modify_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (f.to_check(key))
 | |
|   {
 | |
|     bool ok = suspended_handler(f, key);
 | |
|     if (!ok) return FALSE;
 | |
| 
 | |
|     const int ann = f.mask().get_int(F_ANNOIVA);
 | |
|     const TString cau(f.get());
 | |
|     const TCausale c(cau, ann);
 | |
|     if (!c.ok()) return FALSE;
 | |
|     
 | |
|     ok = app().causale().similar(c);
 | |
|     if (!ok) 
 | |
|       return FALSE;                     // L'errore viene gia' segnalato dalla similar
 | |
|     if (key == K_TAB)
 | |
|     {
 | |
|       app().read_caus(cau, ann);
 | |
|       app().cgs().force_update();
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of the F_DATAREG field
 | |
| // Certified 70%
 | |
| bool TPrimanota_application::datareg_handler(TMask_field& f, KEY key)
 | |
| {                           
 | |
|   bool ok = TRUE;
 | |
|   TMask& m = f.mask();  
 | |
|   
 | |
|   //if ((key == K_TAB && m.is_running() ) || key == K_ENTER)
 | |
|   if (key == K_TAB && f.focusdirty() || key == K_ENTER)
 | |
|   {            
 | |
|     const TDate dr(f.get());                         // Data dell'operazione
 | |
|     if (dr > TDate(TODAY))
 | |
|       return f.error_box("La data dell'operazione e' superiore quella di sistema");
 | |
|     
 | |
|     TPrimanota_application& a = app();
 | |
|     
 | |
|     const int ae = a._esercizi.date2esc(dr);     // Codice esercizio
 | |
|     if (ae <= 0) 
 | |
|       return f.error_box("La data dell'operazione non appartiene a nessun esercizio");
 | |
| 
 | |
|     TLibro_giornale& gio = a.giornale();                                                 
 | |
|     const int ar = dr.year();                    // Anno per registri
 | |
|     if (m.query_mode() || gio.year() != ar)
 | |
|     {
 | |
|       ok = gio.read(ar);
 | |
|       if (!ok) 
 | |
|         return f.error_box("Non esiste il libro giornale del %d", ar);
 | |
|     }  
 | |
|     else
 | |
|       ok = TRUE;
 | |
|     
 | |
|     if (key == K_ENTER || f.focusdirty())
 | |
|     {               
 | |
|       const long numreg = m.get_long(F_NUMREG);
 | |
|       const bool error = numreg == 0 || numreg > a._lastreg; 
 | |
|       
 | |
|       if (key != K_ENTER && !a._skip_giornale_check)
 | |
|       {    
 | |
|         if (dr < gio.last_print())
 | |
|         {
 | |
|           f.error_box("La data dell'operazione e' antecedente al %s,\n"
 | |
|                       "ultima stampa del libro giornale del %d", 
 | |
|                       gio.last_print().string(), ar);
 | |
|           if (error) return FALSE;           
 | |
|         }              
 | |
|         if (key == K_TAB && dr < gio.last_reg())                
 | |
|           f.warning_box("La data dell'operazione e' antecedente al %s,\n"
 | |
|                         "ultima registrazione sul libro giornale del %d", 
 | |
|                         gio.last_reg().string(), ar);
 | |
|       }
 | |
|       
 | |
|       if (m.query_mode())
 | |
|         a.read_caus(m.get(F_CODCAUS), ar);
 | |
|       
 | |
|       TRegistro& reg = a.causale().reg();                       
 | |
|       const TString codreg(reg.name());
 | |
|       if (codreg.not_empty())
 | |
|       {
 | |
|         if (reg.year() != ar)
 | |
|         {
 | |
|           const bool ok = reg.read(codreg, ar);
 | |
|           if (!ok) return FALSE;
 | |
|           a.read_caus(NULL, 0);
 | |
|           if (a.iva() != nessuna_iva)
 | |
|             m.field(F_CODREG).on_hit();
 | |
|         }  
 | |
|         
 | |
|         if (!a._skip_bollato_check)
 | |
|         {  
 | |
|           if (dr < reg.last_print()) 
 | |
|           {
 | |
|             f.error_box("La data dell'operazione e' antecedente al %s,\n"
 | |
|                         "ultima stampa del registro '%s' del %d", 
 | |
|                         reg.last_print().string(), (const char*)codreg, ar);
 | |
|             if (error) return FALSE;           
 | |
|           }              
 | |
|           if (f.dirty() && dr < reg.last_reg()) 
 | |
|             f.warning_box("La data dell'operazione e' antecedente al %s,\n"
 | |
|                           "ultima registrazione sul registro '%s' del %d", 
 | |
|                           reg.last_reg().string(), (const char*)codreg, ar);
 | |
|         }
 | |
|         
 | |
|         if (reg.iva() != nessuna_iva && a._rel->controlla_liquidazione(dr, reg) == TRUE)
 | |
|         {
 | |
|           const char* const mese = itom(dr.month());
 | |
|           f.warning_box("La liquidazione IVA relativa al mese di %s e' gia' stata calcolata", mese);
 | |
|         }
 | |
|       }  
 | |
|     }  
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // Handler of the F_DATACOMP field on the modify mask
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::datacomp_handler(TMask_field& f, KEY key)
 | |
| {                          
 | |
|   TMask& m = f.mask();      
 | |
| 
 | |
|   if (key == K_TAB || key == K_ENTER)
 | |
|   {
 | |
|     const TDate dr(m.get(F_DATAREG));      // Data operazione
 | |
|     
 | |
|     TString16 datacomp = f.get();
 | |
|     if (datacomp.empty())
 | |
|     {
 | |
|       datacomp = dr.string();
 | |
|       // DATACOMP new way
 | |
|       if (key == K_ENTER)
 | |
|         f.set(datacomp);
 | |
|     }
 | |
|     const TDate dc(datacomp);                          // Data di competenza
 | |
|     TEsercizi_contabili& esc = app()._esercizi;
 | |
|     const int ae = esc.date2esc(dc);                   // Esercizio corrispondente
 | |
|     
 | |
|     const char* data = "del 74/ter";
 | |
|     if (f.dlg() == F_DATACOMP)
 | |
|     {
 | |
|       m.set(F_ANNOES, ae, TRUE);                       // Aggiorna anno esercizio in entrambe le pagine
 | |
|       data = "di competenza";
 | |
|     }  
 | |
|     
 | |
|     if (ae)
 | |
|     {                     
 | |
|       const int ar = esc.date2esc(dr);        // Esercizio in corso
 | |
|       const int pr = esc.pred(ar);            // Esercizio precedente
 | |
|       if (ae != ar && ae != pr)
 | |
|       {
 | |
|         TString e(80); 
 | |
|         e << "La data " << data << " deve appartenere all'esercizio " << ar; 
 | |
|         if (pr > 0) e << " o al " << pr;
 | |
|         return f.error_box(e);
 | |
|       }
 | |
|     }  
 | |
|     else  
 | |
|     {
 | |
|       if (m.is_running())
 | |
|         return f.error_box("La data %s non appartiene a nessun esercizio", data);
 | |
|     }  
 | |
|   }    
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Handler of the F_DATA74TER field on the modify mask
 | |
| // Certified 90%
 | |
| bool TPrimanota_application::data74ter_handler(TMask_field& f, KEY key)
 | |
| {                          
 | |
|   if (!f.to_check(key)) return TRUE;
 | |
|   bool ok = datacomp_handler(f, key);
 | |
|   if (ok)
 | |
|   { 
 | |
|     const TDate d74(f.get());
 | |
|     const TLibro_giornale& g = app().giornale();
 | |
|     if (d74 < g.last_print())
 | |
|     {
 | |
|       ok = f.error_box("La data per il 74/ter e' antecedente alla data di stampa "
 | |
|                        "del libro giornale dell'esercizio %d", g.year());
 | |
|     }           
 | |
|   }
 | |
|   return ok; 
 | |
| }   
 | |
| 
 | |
| 
 | |
| bool TPrimanota_application::numdoc_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   TMask& m = f.mask();
 | |
|   if (key == K_TAB && f.to_check(key, TRUE) && m.insert_mode() && app().is_saldaconto())
 | |
|   {
 | |
|     const TString n = f.get();
 | |
|     if (n.not_empty() && !app().npart_is_prot()) // Copiare numero documento nel numero partita?
 | |
|     { 
 | |
|       if (m.field(F_NUMRIF).active() && m.get(F_NUMRIF).blank())
 | |
|         m.set(F_NUMRIF, n, TRUE);             
 | |
|     }  
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::datadoc_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   TMask& m = f.mask();
 | |
| 
 | |
|   if (key == K_TAB && f.to_check(key, TRUE) && app().is_saldaconto())
 | |
|   {
 | |
|     const TDate dd(f.get());                            // Fattura o nota credito
 | |
|     if (dd.ok())
 | |
|     {     
 | |
|       if (m.insert_mode() && m.field(F_ANNORIF).active() && m.get(F_ANNORIF).empty())
 | |
|         m.set(F_ANNORIF, dd.year());                    // copia anno documento
 | |
|       
 | |
|       TPrimanota_application& a = app();  
 | |
|       if (a.is_fattura())     
 | |
|       {   
 | |
|         if (m.insert_mode())
 | |
|         {   
 | |
|           if (m.get_bool(FS_RECALC))   // Evita scancellamenti indesiderati
 | |
|             a.recalc_scadenze(dd);
 | |
|         }  
 | |
|         else 
 | |
|         {
 | |
|           if (a._pag) 
 | |
|             a._pag->set_datadoc(dd);
 | |
|         }  
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::occas_code_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   TMask& m = f.mask();
 | |
|   if (key == K_TAB && (f.dirty() || !m.is_running()))
 | |
|   {
 | |
|     const TString& code = f.get();
 | |
|     if (code.not_empty())
 | |
|     {
 | |
|       TRelation occas(LF_OCCAS);
 | |
|       occas.curr().put("CFPI", code);
 | |
|       if (occas.read(_isequal) == NOERR)
 | |
|       {                     
 | |
|         m.autoload(occas);
 | |
|         m.send_key(K_TAB, O_COMUNE);         // Forza decodifica comuni
 | |
|         m.send_key(K_TAB, O_COMUNENAS);
 | |
|       }  
 | |
|     }
 | |
|   } 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::occas_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_SPACE && f.mask().is_running())
 | |
|   {
 | |
|     TMask& om = app().occas_mask();
 | |
|     om.run();     
 | |
|     f.set_focus();
 | |
|   }  
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Crea o aggiorna la riga contabile col totale documento
 | |
| // Certified 99%
 | |
| void TPrimanota_application::add_cgs_tot(TMask& m)
 | |
| {                           
 | |
|   const bool corri = causale().corrispettivi();
 | |
|   const char tipo = corri ? ' ' : app().clifo();
 | |
|   int gruppo = 0, conto = 0;
 | |
|   long codice = corri ? 0L : m.get_long(tipo == 'C' ? F_CLIENTE : F_FORNITORE);
 | |
| 
 | |
|   TSheet_field& ss = cgs();
 | |
|   const int riga_totale = type2pos('T');   
 | |
|   
 | |
|   // Cerca di preservare il gruppo-conto-sottoconto sulla riga totale
 | |
|   if (riga_totale >= 0)
 | |
|   {          
 | |
|     TToken_string& rowt = ss.row(riga_totale);
 | |
| 
 | |
|     gruppo = rowt.get_int(3); 
 | |
|     conto = rowt.get_int();
 | |
|     const long oldcode = rowt.get_long();
 | |
| 
 | |
|     if (corri)
 | |
|       codice = oldcode;          // I corrispettivi non hanno un cliente in testata
 | |
|     else
 | |
|     {     
 | |
|       if (m.insert_mode())       // Errore MI3567: se cambio cliente ripesca conto
 | |
|       {
 | |
|         if (codice != oldcode)   // Se cambia il codice cliente ...
 | |
|           gruppo = conto = 0;    // ... forza il ricalcolo del gruppo-conto
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   TBill nuovo(gruppo, conto, codice, tipo);
 | |
|   if (!corri && (gruppo == 0 || conto == 0))
 | |
|     nuovo.find(); // Compila anche gruppo e conto in base al codice clifo
 | |
|   
 | |
|   if (nuovo.gruppo() == 0 || nuovo.conto() == 0)
 | |
|   {    
 | |
|     // Se l'utente non ha ancora specificato un conto lo prendo dalla prima riga della causale
 | |
|     causale().bill(1, nuovo);  
 | |
|     
 | |
|     // Nelle fatture si deve sempre aggiungere il codice clifo (in causale normalmente non c'e')
 | |
|     if (!corri)
 | |
|       nuovo.codclifo() = codice;
 | |
|   }
 | |
|   
 | |
|   if (riga_totale >= 0) 
 | |
|   {       
 | |
|     TToken_string& row = ss.row(riga_totale);
 | |
|     const TBill vecchio(row, 2, 0x1);
 | |
|     if (!vecchio.empty() && nuovo != vecchio)                  // Se cambio cliente/fornitore
 | |
|     {
 | |
|       for (int i = 0; i < ss.items(); i++) if (i != riga_totale)
 | |
|       {
 | |
|         TToken_string& r = ss.row(i);
 | |
|         const TBill tacchia(r, 9, 0x1);
 | |
|         if (tacchia == vecchio) 
 | |
|         {
 | |
|           nuovo.add_to(r, 9, 0x3);   // Aggiorna contropartite
 | |
|           ss.force_update(i);
 | |
|         }  
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   if (!_as400)
 | |
|   {
 | |
|     // Creazione/Aggiornamento riga totale 
 | |
|     const real tot(m.get(F_TOTALE));
 | |
|     set_cgs_row(riga_totale, real2imp(tot, 'T'), nuovo, m.get(F_DESCR), 'T');
 | |
|   }
 | |
| 
 | |
|   calcola_imp();                                    // Ricalcola totale IVA
 | |
|   calcola_saldo();                                  // Ricalcola sbilanci
 | |
| }
 | |
| 
 | |
| // Handler of the F_CLIENTE & F_FORNITORE field on the modify mask
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::clifo_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (!suspended_handler(f, key))
 | |
|     return FALSE;
 | |
|     
 | |
|   if (key == K_TAB && f.active())
 | |
|   {                                  
 | |
|     TPrimanota_application& a = app();
 | |
|     TMask& m = f.mask();
 | |
|     
 | |
|     if (f.focusdirty() && a.is_nota_credito())
 | |
|     {   
 | |
|       TPartite_array& p = a.partite();
 | |
|       if (m.edit_mode())
 | |
|         p.add_numreg(m.get_long(F_NUMREG));
 | |
| 
 | |
|       const TPartita* game = p.first();
 | |
|       if (game != NULL && atol(f.get()) != game->conto().codclifo())  
 | |
|       { 
 | |
|         const bool del = f.yesno_box("Si desidera cancellare i pagamenti effettuati?");
 | |
|         if (!del)     // Ripristina codice copiandolo dalla prima partita
 | |
|         {
 | |
|           TString cod; cod << game->conto().codclifo();
 | |
|           f.set(cod);
 | |
|           return TRUE;
 | |
|         }
 | |
|         f.set_dirty();     // yesno_box cleared the dirty flag
 | |
|         a.notify_cgline_deletion(-1);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     const char cf = a.clifo();
 | |
|     const long codice = atol(f.get());
 | |
| 
 | |
|     if (codice == 0) 
 | |
|     {
 | |
|       m.hide(F_OCCASEDIT);                                 // Spegni bottone occasionali
 | |
|       m.show(F_STATOPAIV);                                 // Stato partita IVA
 | |
|       m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE); // Partita IVA
 | |
|       m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE); // Codice Fiscale
 | |
|       a.activate_numrif(m, TRUE);
 | |
|       return TRUE;
 | |
|     }  
 | |
|     
 | |
|     TRelation cliforel(LF_CLIFO); cliforel.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF");
 | |
|     TRectype& clifo = cliforel.curr();
 | |
|     clifo.put(CLI_TIPOCF, cf);   
 | |
|     clifo.put(CLI_CODCF, codice);   
 | |
|     cliforel.read();
 | |
| 
 | |
|     if (!m.is_running() || f.dirty())
 | |
|     {
 | |
|       a._conto_ricavo.set(clifo.get_int(CLI_GRUPPORIC), 
 | |
|                           clifo.get_int(CLI_CONTORIC), 
 | |
|                           clifo.get_long(CLI_SOTTOCRIC));
 | |
|       
 | |
|       const int alleg = clifo.get_int(CLI_ALLEG);
 | |
|       TEdit_field& upi = m.efield(F_RIEPILOGO);
 | |
|       upi.check_type(alleg == 3 ? CHECK_REQUIRED : CHECK_NORMAL);
 | |
|       
 | |
|       if (m.insert_mode() && m.get(F_CODPAG).empty()) 
 | |
|       {
 | |
|         const TString& s = clifo.get(CLI_CODPAG);
 | |
|         if (s.not_empty())
 | |
|         {
 | |
|           TEdit_field& cp = m.efield(F_CODPAG);
 | |
|           if (cp.active())              // Se il campo F_CODPAG e' attivo
 | |
|           {
 | |
|             cp.set(s);                  // Setta il codice di pagamento sulla maschera
 | |
|             cp.check(RUNNING_CHECK);    // lo decodifica
 | |
|             cp.on_hit();                // lo ricopia eventualmente a pag.3
 | |
|           }  
 | |
|         }  
 | |
|       }
 | |
| 
 | |
|       if (f.focusdirty() && a.is_saldaconto())
 | |
|       {                         
 | |
|         if (m.field(SK_VALUTA).active() && m.get(SK_VALUTA).empty())
 | |
|         {
 | |
|           const TString& valuta = clifo.get(CLI_CODVAL);
 | |
|           if (valuta.not_empty())
 | |
|             m.set(SK_VALUTA, valuta, TRUE);
 | |
|         }                   
 | |
|         
 | |
|         if (a.is_fattura())
 | |
|         {
 | |
|           if (clifo.get(CLI_CODCAB).not_empty())
 | |
|           {
 | |
|             m.set(FS_VSABI, clifo.get(CLI_CODABI));
 | |
|             m.set(FS_VSCAB, clifo.get(CLI_CODCAB));
 | |
|             m.send_key(K_TAB, FS_VSCAB);
 | |
|           }
 | |
|           
 | |
|           const TString& agente = cliforel.curr(LF_CFVEN).get(CLI_CODAG);
 | |
|           if (agente.not_empty())
 | |
|           {
 | |
|             m.set(FS_AGENTE, agente, TRUE);
 | |
|             m.send_key(K_TAB, FS_AGENTE);
 | |
|           }  
 | |
|         }  
 | |
|       }
 | |
|     }  
 | |
| 
 | |
|     const bool occas = clifo.get_bool(CLI_OCCAS);
 | |
|     m.show(F_OCCASEDIT, occas);                                  // Bottone Dati anagrafici
 | |
|     m.show(F_STATOPAIV, !occas);                                 // Stato partita IVA
 | |
|     m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE, !occas); // Partita IVA
 | |
|     m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE, !occas); // Codice Fiscale
 | |
|     
 | |
|     if (occas && a.is_fattura() && a.partite().first() != NULL)
 | |
|     {
 | |
|       f.warning_box("Attenzione, il saldaconto verra' eliminato!");
 | |
|       f.set_dirty();    // warning_box cleans the field!
 | |
|     }  
 | |
|     a.activate_numrif(m, TRUE);
 | |
|     
 | |
|     if (f.focusdirty())
 | |
|     {
 | |
|       a.add_cgs_tot(m);
 | |
|       if (occas && a.occas_mask().get(O_CODICE).blank())
 | |
|         m.send_key(K_SPACE, F_OCCASEDIT);   // Lancia maschera occasionali
 | |
|     }
 | |
|     
 | |
|   }  
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TPrimanota_application::IVA2bill(const TCodiceIVA& iva, TBill& bill)
 | |
| {
 | |
|   const TCausale& cau = causale();
 | |
|   if (!cau.corrispettivi())   
 | |
|     bill = _conto_ricavo;
 | |
|   return cau.IVA2bill(iva, bill);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of the F_CODIVA
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.get().not_empty())
 | |
|   {
 | |
|     if (!suspended_handler(f, key))
 | |
|       return FALSE;
 | |
|     
 | |
|     TPrimanota_application& a = app();
 | |
|     const real imp(a.ivas().row(1).get(0));   // Se il totale non e' stato spezzato
 | |
|     if (imp.is_zero())
 | |
|     {                     
 | |
|       TToken_string& row = a.ivas().row(0);
 | |
| 
 | |
|       TMask& m = f.mask();
 | |
|       iva_notify(a.ivas(), 0, K_SPACE);
 | |
|       
 | |
|       const TCodiceIVA iva(f.get());   
 | |
|       const bool corr = a.causale().corrispettivi();
 | |
|       const bool acq3 = (a.iva() == iva_acquisti) && (row.get_int(2) == 3);
 | |
|       
 | |
|       real tot = a.totale_documento();        // Calcola totale documento
 | |
|       real imposta;                               // Calcola imposta
 | |
|       if (!corr && !acq3)
 | |
|         imposta = iva.scorpora(tot);
 | |
|       
 | |
|       row.add(tot.string(), 0);                   // imponibile
 | |
|       row.add(imposta.string(), 3);               // imposta
 | |
|       
 | |
|       if (iva.codice() != row.get(1))
 | |
|       {
 | |
|         row.add(iva.codice(), 1);       // Aggiorna codice IVA
 | |
|         TBill bill;                     // Aggiorna conto della prima riga IVA
 | |
|         a.IVA2bill(iva, bill);
 | |
|         bill.add_to(row, 4, 0x7);  
 | |
|       }
 | |
|       a.ivas().force_update(0);
 | |
| 
 | |
|       iva_notify(a.ivas(), 0, K_ENTER);
 | |
|     }   
 | |
|   }  
 | |
|   return TRUE;  
 | |
| }
 | |
| 
 | |
| // Riempie i campi valuta a zero in base agli altri
 | |
| void TPrimanota_application::gioca_cambi(int force)
 | |
| {               
 | |
|   TMask& m = curr_mask();    
 | |
|   if (m.get(SK_VALUTA).empty())
 | |
|     return;
 | |
|   
 | |
|   const real totale = m.get(F_TOTALE);
 | |
|   const real totval = m.get(SK_TOTDOCVAL);
 | |
|   const real cambio = m.get(SK_CAMBIO);  
 | |
| 
 | |
|   if ( (force == 0x1 || totale.is_zero()) && !(totval.is_zero() || cambio.is_zero()) )
 | |
|   {
 | |
|     const TValuta cam(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
 | |
|     const real new_totale = cam.val2lit(totval);
 | |
|     if (new_totale != totale)
 | |
|       m.set(F_TOTALE, new_totale, TRUE);
 | |
|   } 
 | |
|   
 | |
|   if ( (force == 0x2 || totval.is_zero()) && !(totale.is_zero() || cambio.is_zero()) )
 | |
|   {
 | |
|     const TValuta cam(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
 | |
|     const real new_totval = cam.lit2val(totale);
 | |
|     if (new_totval != totval)
 | |
|       m.set(SK_TOTDOCVAL, new_totval, TRUE);
 | |
|   } 
 | |
|   
 | |
|   if ( (force == 0x4 || cambio.is_zero()) && !(totale.is_zero() || totval.is_zero()) )
 | |
|   {
 | |
|     real new_cambio = totale / totval; new_cambio.round(5);
 | |
|     if (new_cambio != cambio)
 | |
|       m.set(SK_CAMBIO, new_cambio, TRUE);
 | |
|   } 
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of the F_TOTALE
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::totdoc_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   bool ok = TRUE;
 | |
|   TMask& m = f.mask();
 | |
| 
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|   {       
 | |
|     TPrimanota_application& a = app();
 | |
|     a.gioca_cambi();
 | |
| 
 | |
|     if (a.iva() != nessuna_iva)
 | |
|     {
 | |
|       a.add_cgs_tot(m);
 | |
|       if (m.insert_mode())               // Se si e' in inserimento provoca ricalcolo
 | |
|         m.field(F_CODIVA).on_hit();      // dello sheet iva e delle scadenze
 | |
|     }  
 | |
|     else   
 | |
|     {
 | |
|       if (a.is_pagamento())
 | |
|         a.calcola_saldo();
 | |
|     }                         
 | |
|   }
 | |
|   
 | |
|   if (key == K_ENTER)
 | |
|   {
 | |
|     const real totale(f.get());
 | |
|     if (totale.is_zero())
 | |
|       ok = yesno_box("Totale documento nullo: continuare ugualmente?");
 | |
|     
 | |
|     if (ok)
 | |
|     {
 | |
|       const TValuta cambio(m, SK_VALUTA, SK_DATACAMBIO, SK_CAMBIO);
 | |
|       if (cambio.in_valuta())
 | |
|       {
 | |
|         const real totval(m.get(SK_TOTDOCVAL));
 | |
|         const real totlit = cambio.val2lit(totval);
 | |
|         if (totale != totlit)
 | |
|           ok = f.yesno_box("Il totale documento in lire dovrebbe essere %s: continuare ugualmente?",
 | |
|                          totlit.string("."));
 | |
|       }  
 | |
|     }  
 | |
|   }    
 | |
|   
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::totdocval_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|   {  
 | |
|     TPrimanota_application& a = app();
 | |
|     a.gioca_cambi();
 | |
|     
 | |
|     TMask& m = f.mask();
 | |
|     if (a.is_fattura() && m.insert_mode())    
 | |
|       a.set_scadenze(m);  
 | |
|   }
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Aggiunge o aggiorna la riga delle ritenute fiscali o sociali   
 | |
| // Certified 99%
 | |
| void TPrimanota_application::add_cgs_rit(bool fiscali)
 | |
| {                            
 | |
|   if (_as400)
 | |
|     return;
 | |
| 
 | |
|   TMask& m = curr_mask();
 | |
|   const real imp(m.get(fiscali ? F_RITFIS : F_RITSOC)); // Determina importo
 | |
| 
 | |
|   const char tipo = fiscali ? 'F' : 'S';
 | |
|   const int pos = type2pos(tipo);          // Cerca la riga contabile
 | |
|   if (pos < 0)                             // Se non c'e' ...
 | |
|   {  
 | |
|     if (!imp.is_zero())                      // ... e l'importo e' valido
 | |
|     {                                        // crea una nuova riga di ritenute
 | |
|       const int riga = fiscali ? RIGA_RITENUTE_FISCALI : RIGA_RITENUTE_SOCIALI;
 | |
|       TBill conto; causale().bill(riga, conto);
 | |
|       const TString desc(causale().desc_agg(riga));
 | |
|       set_cgs_row(-1, real2imp(imp, tipo), conto, desc, tipo);
 | |
|     }  
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (imp.is_zero())                       // se l'importo e' nullo ...
 | |
|       reset_cgs_row(pos);                    // ... azzera la riga contabile
 | |
|     else                                     // altrimenti ...
 | |
|       set_cgs_imp(pos, real2imp(imp, tipo)); // ... aggiorna importo
 | |
|   }  
 | |
|   
 | |
|   if (m.insert_mode())
 | |
|     m.field(F_CODIVA).on_hit();              // Ricalcola sheet iva e contabile
 | |
|   else
 | |
|     app().calcola_saldo();                   // Ricalcola solo lo sbilancio
 | |
| }
 | |
| 
 | |
| // Handler of the F_PROTIVA
 | |
| bool TPrimanota_application::protiva_handler(TMask_field& f, KEY key)
 | |
| {          
 | |
|   bool ok = TRUE;            
 | |
|   TMask& m = f.mask();
 | |
|   
 | |
|   if (m.insert_mode())
 | |
|   {
 | |
|     if (key == K_ENTER && f.dirty())
 | |
|     {
 | |
|       const long protiva = atol(f.get());
 | |
|       const long protocol = app().causale().reg().protocol() + 1;
 | |
|       if (protiva != protocol)
 | |
|         ok = f.yesno_box("Accettare il protocollo IVA fuori sequenza: %ld invece di %ld", 
 | |
|                          protiva, protocol);    
 | |
|       
 | |
|     }
 | |
|     else 
 | |
|     if (key == K_TAB && m.insert_mode() && app().npart_is_prot() &&
 | |
|         m.field(F_NUMRIF).active() && m.get(F_NUMRIF).blank())
 | |
|     {
 | |
|       const TString& piva = f.get();
 | |
|       if (piva.not_empty())    
 | |
|         m.set(F_NUMRIF, piva, TRUE); 
 | |
|     }
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of the F_RITFIS
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::ritfis_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|     app().add_cgs_rit(TRUE);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Handler of F_RITSOC
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::ritsoc_handler(TMask_field& f, KEY key)
 | |
| {
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|     app().add_cgs_rit(FALSE);
 | |
|   return TRUE;
 | |
| }                                  
 | |
| 
 | |
| // Handler of F_CORRLIRE
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::corrlire_handler(TMask_field& f, KEY key)
 | |
| {   
 | |
|   TMask& m = f.mask();
 | |
| 
 | |
|   if (key == K_ENTER && f.get().empty())
 | |
|   {
 | |
|     if (m.get(F_CORRVALUTA).not_empty()) 
 | |
|     {
 | |
|       TMask_field& cv = m.field(F_CORRVALUTA);
 | |
|       cv.set_focusdirty();
 | |
|       cv.on_hit();
 | |
|     }  
 | |
|     else
 | |
|       key = K_F8;  
 | |
|   }
 | |
| 
 | |
|   if (key == K_F8)
 | |
|   {
 | |
|     f.set(m.get(F_IMPONIBILI));
 | |
|     f.set_dirty();
 | |
|     m.reset(F_CORRVALUTA);
 | |
|     key = K_TAB;
 | |
|   }
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|   {                     
 | |
|     if (m.get(F_CORRVALUTA).empty())
 | |
|     {
 | |
|       const real cambio = m.get(F_CAMBIOINTRA);
 | |
|       if (cambio != ZERO && m.get(F_CORRVALUTA).empty())
 | |
|       {
 | |
|         real c(f.get());
 | |
|         c /= cambio;
 | |
|         m.set(F_CORRVALUTA, c.string());
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   if (key == K_ENTER)
 | |
|   {
 | |
|     const TString im(m.get(F_IMPONIBILI));
 | |
|     const char* cl = f.get();
 | |
|     if (im != cl) 
 | |
|       warning_box("Il corrispettivo in lire e' diverso dal totale degli imponibili");
 | |
|   }
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Handler of F_CORRVALUTA
 | |
| // Certified 99%
 | |
| bool TPrimanota_application::corrvaluta_handler(TMask_field& f, KEY key)
 | |
| {               
 | |
|   if (key == K_TAB && f.focusdirty())
 | |
|   {                     
 | |
|     TMask& m = f.mask();
 | |
|     if (m.get(F_CORRLIRE).empty())
 | |
|     {
 | |
|       const real cambio = m.get(F_CAMBIOINTRA);
 | |
|       if (cambio != ZERO)
 | |
|       {
 | |
|         real c = f.get();
 | |
|         c *= cambio;
 | |
|         m.set(F_CORRLIRE, c.string());
 | |
|       }  
 | |
|     }  
 | |
|   } else
 | |
|     if (key == K_ENTER && f.get().empty())
 | |
|     {
 | |
|       TMask_field& cl = f.mask().field(F_CORRLIRE);
 | |
|       cl.set_dirty();
 | |
|       cl.on_hit();
 | |
|     }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TPrimanota_application::activate_numrif(TMask& m, bool init_pag)
 | |
| {
 | |
|   bool shown = is_saldaconto();         // Il numero riferimento esiste 
 | |
|   
 | |
|   if (shown)
 | |
|   {
 | |
|     const bool hide = m.get_bool(F_SOLAIVA) || m.field(F_OCCASEDIT).shown();
 | |
|     if (hide) shown = FALSE;
 | |
|   }  
 | |
|   
 | |
|   if (shown != m.field(F_NUMRIF).shown())
 | |
|   {
 | |
|     m.show(F_ANNORIF, shown);
 | |
|     m.show(F_NUMRIF,  shown); 
 | |
|     if (shown)
 | |
|     {  
 | |
|       if (m.get(F_ANNORIF).empty())
 | |
|       {
 | |
|         m.set(F_ANNORIF, m.get(F_DATADOC).right(4));
 | |
|         m.set(F_NUMRIF, m.get(_npart_is_prot ? F_PROTIVA : F_NUMDOC));
 | |
|       }  
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       m.reset(F_ANNORIF);
 | |
|       m.reset(F_NUMRIF);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Gestione pagina 3
 | |
|   const bool page = shown && is_fattura() && !m.get(F_NUMRIF).blank();
 | |
|   if (page != m.page_enabled(2))
 | |
|   {
 | |
|     m.enable_page(2, page);                 
 | |
|     if (page && init_pag && m.is_running())
 | |
|     {
 | |
|       if (m.edit_mode())
 | |
|       {
 | |
|         const TString16 dt(m.get(F_DATADOC));
 | |
|         set_pagamento(NULL, dt);          // Reset pagamento
 | |
|         set_totale_pagamento(TRUE);
 | |
|       }
 | |
|       else
 | |
|         set_scadenze(m);                  // Inizializza pagamento
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   return shown;
 | |
| }
 | |
| 
 | |
| // Handler del checkbox di movimento di sola IVA
 | |
| bool TPrimanota_application::solaiva_handler(TMask_field& f, KEY key)
 | |
| {                                         
 | |
|   TMask& m = f.mask();
 | |
|   const bool run = m.is_running();
 | |
| 
 | |
|   if ((key == K_TAB && f.focusdirty()) || !run)
 | |
|   {     
 | |
|     TPrimanota_application& a = app();                                  
 | |
|     
 | |
|     bool anchecg = f.get()[0] != 'X'; 
 | |
|     bool recalcg = anchecg;
 | |
|     
 | |
|     if (run && a.is_fattura())
 | |
|     {
 | |
|       const TPartita* game = a.partite().first();
 | |
| 
 | |
|       if (anchecg)
 | |
|       {                          
 | |
|         if (game != NULL)
 | |
|         {
 | |
|           m.set(F_ANNORIF, game->anno());
 | |
|           m.set(F_NUMRIF, game->numero());
 | |
|         }
 | |
|       }
 | |
|       else
 | |
|       {                 
 | |
|         bool del = TRUE;
 | |
|         if (game != NULL)
 | |
|           del = f.yesno_box("Si desidera cancellare il saldaconto?");
 | |
|         if (!del)  
 | |
|         {
 | |
|           f.reset();
 | |
|           anchecg = TRUE;
 | |
|           recalcg = FALSE;
 | |
|         }  
 | |
|       }
 | |
|       a.activate_numrif(m, TRUE);
 | |
|     }
 | |
|     
 | |
|     m.show(F_SHEETCG, anchecg);
 | |
|     m.show(F_DARE,    anchecg);
 | |
|     m.show(F_AVERE,   anchecg);
 | |
|     
 | |
|     if (run && recalcg)
 | |
|     {                      
 | |
|       TSheet_field& iva = a.ivas();
 | |
|       const int righe = iva.items();
 | |
|       TProgind pi(righe, "Generazione righe contabilita'", FALSE, TRUE, 16);
 | |
|       
 | |
|       TSheet_field& cg = a.cgs();
 | |
|       cg.reset();
 | |
|       
 | |
|       a.add_cgs_tot(m);                                        // Genera totale documento
 | |
|       if (m.get(F_RITFIS).not_empty()) a.add_cgs_rit(TRUE);    // Genera ritenute fiscali
 | |
|       if (m.get(F_RITSOC).not_empty()) a.add_cgs_rit(FALSE);   // Genera ritenute sociali
 | |
|       
 | |
|       TToken_string oldrow(128);
 | |
|       for (int i = 0; i < righe; i++)
 | |
|       {             
 | |
|         TToken_string& r = iva.row(i);
 | |
|         if (!r.empty_items())
 | |
|         {
 | |
|           oldrow = r;
 | |
|           r = "";
 | |
|           iva_notify(iva, i, K_SPACE);   // Simula la creazione di una nuova riga iva
 | |
|           r = oldrow;
 | |
|           iva_notify(iva, i, K_ENTER);
 | |
|         }
 | |
|         pi.setstatus(i+1);
 | |
|       }
 | |
|       a.fill_sheet(m);                   // Aggiunge righe vuote
 | |
|       cg.force_update();
 | |
|       m.set_focus();                     // Ripristina il focus al campo (a causa della progind)
 | |
|     }
 | |
|   }  
 | |
|   return TRUE;  
 | |
| }
 | |
| 
 | |
| 
 |