Files correlati : ca0.exe ca2.exe Ricompilazione Demo : [ ] Commento : Bug 0001669: Aggiungere un conto di contabilità di default alle commesse Aggiungere un conto di contabilità di default alle commesse git-svn-id: svn://10.65.10.50/trunk@20665 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1236 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1236 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <defmask.h>
 | 
						||
#include <recset.h>
 | 
						||
 | 
						||
#include "ca2.h"
 | 
						||
#include "ca2100a.h"
 | 
						||
#include "calib01.h"
 | 
						||
 | 
						||
#include "../cg/cglib01.h"
 | 
						||
 | 
						||
#include <mov.h>
 | 
						||
#include <rmov.h>
 | 
						||
 | 
						||
#include "movana.h"
 | 
						||
#include "rmovana.h"
 | 
						||
#include "rrip.h"
 | 
						||
#include "saldana.h"
 | 
						||
#include "cdc.h"
 | 
						||
#include "commesse.h"
 | 
						||
#include "fasi.h"
 | 
						||
 | 
						||
 | 
						||
class TMovanal_msk : public TAutomask
 | 
						||
{
 | 
						||
  TAssoc_array _saldi;
 | 
						||
  bool _use_pdc;
 | 
						||
  short _cms_start;
 | 
						||
  short _cms_end;
 | 
						||
  short _cdc_start;
 | 
						||
  short _cdc_end;
 | 
						||
	short _pcon_start;
 | 
						||
	short _pcon_end;
 | 
						||
 | 
						||
 | 
						||
  TCache_ripartizioni _cache_rip;
 | 
						||
 | 
						||
protected:
 | 
						||
  virtual bool on_field_event(TOperable_field& o, TField_event fe, long jolly);
 | 
						||
  virtual bool can_be_closed() const;
 | 
						||
  virtual bool on_key(KEY key);
 | 
						||
 | 
						||
  const TToken_string& rec2key(const TRectype& rec) const;
 | 
						||
  void completa_conto(int r);
 | 
						||
  void aggiorna_saldo_riga(int r);
 | 
						||
  
 | 
						||
  // Lettura movimento contabile
 | 
						||
  TToken_string& get_rip_row(const TRectype& rrip);
 | 
						||
  void split_cg_row(const TRectype& row, const TAnal_ripartizioni_batch& rrip);
 | 
						||
  bool multi_split_cg_row(const TRectype& row, const TAnal_ripartizioni_batch& rrip);
 | 
						||
  void load_cg_row(const TRectype& row);
 | 
						||
  void load_cg_mov();
 | 
						||
  bool is_ripartible_movcg(bool& has_multirip);
 | 
						||
 | 
						||
  int create_sheet_fields(int lf, int& y, short& dlg, bool required);
 | 
						||
  void create_sheet();
 | 
						||
  int get_constant_columns(TToken_string& tok) const;
 | 
						||
 | 
						||
public:
 | 
						||
  void reset_saldi();
 | 
						||
  TImporto& saldo(const TRectype& row);
 | 
						||
  void show_locked_buttons();
 | 
						||
 | 
						||
  bool row2rec(int row, TRectype& rec) const;
 | 
						||
  void row2imp(const TToken_string& row, TImporto& imp) const;
 | 
						||
  bool row2imp(int r, TImporto& imp) const;
 | 
						||
 | 
						||
  void imp2row(const TImporto& imp, TToken_string& row) const;
 | 
						||
  TToken_string& rec2row(const TRectype& rec, int i) const;
 | 
						||
 | 
						||
  TMovanal_msk();
 | 
						||
  virtual ~TMovanal_msk() { }
 | 
						||
};
 | 
						||
 | 
						||
class TMovanal_app : public TRelation_application
 | 
						||
{
 | 
						||
  TRelation* _rel;
 | 
						||
  TMovanal_msk* _msk;
 | 
						||
 | 
						||
protected:
 | 
						||
  virtual const char* extra_modules() const { return "cm"; } //deve funzionare anche per le commesse
 | 
						||
 | 
						||
  virtual bool user_create();
 | 
						||
  virtual bool user_destroy();
 | 
						||
  virtual TMask* get_mask(int);
 | 
						||
  virtual TRelation* get_relation() const;
 | 
						||
  virtual bool get_next_key(TToken_string& key);
 | 
						||
  
 | 
						||
  void write_rows(const TMask& m);
 | 
						||
  void read_rows(const TMask& m);
 | 
						||
 | 
						||
  virtual bool protected_record(TRectype& rec);
 | 
						||
  virtual int write(const TMask& m);
 | 
						||
  virtual int rewrite(const TMask& m);
 | 
						||
  virtual int read(TMask& m);
 | 
						||
 | 
						||
  virtual void ini2sheet(TConfig& ini, TSheet_field& sheet);
 | 
						||
  virtual void sheet2ini(TSheet_field& sheet,TConfig& ini);
 | 
						||
 | 
						||
  virtual void init_query_mode(TMask& m);
 | 
						||
  virtual void init_insert_mode(TMask& m);
 | 
						||
  virtual void init_modify_mode(TMask& m);
 | 
						||
};
 | 
						||
 | 
						||
static TMovanal_app& app() { return (TMovanal_app&)main_app(); }
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMovanal_msk
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
bool TMovanal_msk::can_be_closed() const
 | 
						||
{
 | 
						||
  const bool lck = app().is_transaction() && mode() == MODE_INS;
 | 
						||
  return lck ? false : TAutomask::can_be_closed();
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_msk::on_key(KEY key)
 | 
						||
{
 | 
						||
  if (key == K_SHIFT + K_F12)
 | 
						||
  {
 | 
						||
    enable(F_BLOCCATO);
 | 
						||
    return true;
 | 
						||
  }
 | 
						||
  return TAutomask::on_key(key);
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::show_locked_buttons()
 | 
						||
{
 | 
						||
  const bool is_trans = app().is_transaction();
 | 
						||
  const bool modifying = mode() == MODE_MOD;
 | 
						||
  const bool inserting = mode() == MODE_INS;
 | 
						||
  const bool editing = modifying || inserting;
 | 
						||
  const bool unlocked = !(modifying && get_bool(F_BLOCCATO));
 | 
						||
  show  (F_BLOCCATO,  modifying);
 | 
						||
  enable(F_BLOCCATO,  unlocked);
 | 
						||
  enable(DLG_SAVEREC, unlocked && editing);
 | 
						||
  enable(DLG_DELREC,  unlocked && !inserting);
 | 
						||
  enable(DLG_QUIT,    !is_trans || !inserting);
 | 
						||
  enable(DLG_CANCEL,  !is_trans || !inserting);
 | 
						||
  enable(F_RESET,     unlocked && editing);
 | 
						||
}
 | 
						||
 | 
						||
TToken_string& TMovanal_msk::get_rip_row(const TRectype& rrip)
 | 
						||
{
 | 
						||
  TSheet_field& sheet = sfield(F_RIGHE);
 | 
						||
 | 
						||
  TToken_string keyrip; 
 | 
						||
  keyrip.add(rrip.get(RRIP_CODCOSTO));
 | 
						||
  keyrip.add(rrip.get(RRIP_CODCMS));
 | 
						||
  keyrip.add(rrip.get(RRIP_CODFASE));
 | 
						||
  keyrip.add(rrip.get(RRIP_CODCONTO));
 | 
						||
 | 
						||
  TRectype rmov(LF_RMOVANA);
 | 
						||
  const int totrows = sheet.items();
 | 
						||
  if (totrows > 0)
 | 
						||
  {
 | 
						||
    TToken_string keyrow; 
 | 
						||
    for (int i = 0; i < totrows; i++)
 | 
						||
    {
 | 
						||
      row2rec(i, rmov);
 | 
						||
      keyrow.cut(0);
 | 
						||
      keyrow.add(rmov.get(RMOVANA_CODCCOSTO));
 | 
						||
      keyrow.add(rmov.get(RMOVANA_CODCMS));
 | 
						||
      keyrow.add(rmov.get(RMOVANA_CODFASE));
 | 
						||
      keyrow.add(rmov.get(RMOVANA_CODCONTO));
 | 
						||
      if (keyrow == keyrip)
 | 
						||
        return sheet.row(i);  // Ho trovato una riga compatibile
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  // Devo creare una riga nuova
 | 
						||
  rmov.zero();
 | 
						||
  rmov.put(RMOVANA_CODCCOSTO, keyrip.get(0));
 | 
						||
  rmov.put(RMOVANA_CODCMS,    keyrip.get());
 | 
						||
  rmov.put(RMOVANA_CODFASE,   keyrip.get());
 | 
						||
  rmov.put(RMOVANA_CODCONTO,  keyrip.get());
 | 
						||
  TToken_string& row = rec2row(rmov, -1);
 | 
						||
  return row;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::split_cg_row(const TRectype& row, const TAnal_ripartizioni_batch& rrip)
 | 
						||
{
 | 
						||
  // Importo totale da distribuire arrotondato ai decimali della valuta di conto
 | 
						||
  TGeneric_distrib distrib(row.get_real(RMV_IMPORTO), TCurrency::get_firm_dec());
 | 
						||
 | 
						||
  // Calcolo tutte le percentuali da ripartire
 | 
						||
  int i;
 | 
						||
  for (i = 1; i <= rrip.rows(); i++)
 | 
						||
  {
 | 
						||
    const real quota = rrip[i].get_real(RRIP_RIPARTO);
 | 
						||
    distrib.add(quota);
 | 
						||
  }
 | 
						||
 | 
						||
  TString80 desc; // Variabile di appoggio per descrizione riga
 | 
						||
  for (i = 1; i <= rrip.rows(); i++)
 | 
						||
  {
 | 
						||
    TToken_string& riga = get_rip_row(rrip[i]); // Cerca o crea la riga cui sommare la quota
 | 
						||
    TImporto impriga; row2imp(riga, impriga);   // Legge l'importo della riga
 | 
						||
    const TImporto imp(row.get_char(RMV_SEZIONE), distrib.get()); // Legge la quota da distribuire
 | 
						||
    impriga += imp; impriga.normalize();        // Incrementa l'importo della riga e lo normalizza
 | 
						||
    imp2row(impriga, riga);                     // Aggiorna la riga
 | 
						||
    
 | 
						||
    riga.get(2, desc);                          // Legge descrizione riga corrente
 | 
						||
    if (desc.blank())                           // Se e' vuota allora ...
 | 
						||
      riga.add(row.get(RMV_DESCR), 2);          // ... ci copio la descrizione della riga contabile
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_msk::multi_split_cg_row(const TRectype& row, const TAnal_ripartizioni_batch& rrip)
 | 
						||
{
 | 
						||
  bool splitted = true;
 | 
						||
  
 | 
						||
  //crea l'array con tutte le ripartizioni compatibili (sorelle)
 | 
						||
 | 
						||
  //1) crea lo sheet con codice e descrizione delle ripartizioni possibile
 | 
						||
  TArray_sheet lista_rips(-1, -1, 64, 16, TR("Scelta ripartizioni"), HR("Codice@8|Descrizione@50"), 0, 6);
 | 
						||
  //2) trova quante sono le ripartizioni possibili
 | 
						||
  const long nrips = rrip.find_sister_rips(lista_rips.rows_array());
 | 
						||
  //3a) se le ripartizioni sono pi<70> di una mostra una maschera di scelta generata al volo con lo sheet dell'elenco..
 | 
						||
  //..ripartizioni possibili e i dati della riga che propone il dilemma di scelta; la riga pu<70> essere contabile o..
 | 
						||
  //..analitica in base al contesto in cui viene chiamata la multi_split_cg_row()
 | 
						||
  if (nrips > 1)
 | 
						||
  {
 | 
						||
    //campi comuni ai 2 casi
 | 
						||
    lista_rips.add_number(201, 0, "N.Riga   ", 1, 0, 3, "D");
 | 
						||
    lista_rips.add_string(202, 0, "Descriz. ", 1, 1, 50, "D");
 | 
						||
    lista_rips.add_string(209, 0, "Importo  ", 1, 3, 1, "D");
 | 
						||
    lista_rips.add_currency(210, 0, "", 14, 3, 18, "D");
 | 
						||
 | 
						||
    switch (row.num())
 | 
						||
    {
 | 
						||
    case LF_RMOV: //metodo chiamato in fase di registrazione del movimento in CG
 | 
						||
      {
 | 
						||
        lista_rips.add_number(203, 0, "Gruppo   ", 1, 2, 3, "D");
 | 
						||
        lista_rips.add_number(204, 0, "Conto ", 16, 2, 3, "D");
 | 
						||
        lista_rips.add_number(205, 0, "Sottoconto ", 30, 2, 6, "D");
 | 
						||
 | 
						||
        lista_rips.set(201, row.get(RMV_NUMRIG));
 | 
						||
        lista_rips.set(202, row.get(RMV_DESCR));
 | 
						||
        lista_rips.set(203, row.get(RMV_GRUPPO));
 | 
						||
        lista_rips.set(204, row.get(RMV_CONTO));
 | 
						||
        lista_rips.set(205, row.get(RMV_SOTTOCONTO));
 | 
						||
        lista_rips.set(209, row.get(RMV_SEZIONE));
 | 
						||
        lista_rips.set(210, row.get(RMV_IMPORTO));
 | 
						||
      }
 | 
						||
      break;
 | 
						||
 | 
						||
    case LF_RMOVANA:  //metodo chiamato in fase di registrazione del movimento in CA
 | 
						||
      {
 | 
						||
        lista_rips.add_string(203, 0, "Conto    ", 1, 2, 20, "D");
 | 
						||
        lista_rips.add_string(204, 0, "Commessa ", 1, 4, 20, "D");
 | 
						||
        lista_rips.add_string(205, 0, "C. Costo ", 1, 5, 20, "D");
 | 
						||
 | 
						||
        lista_rips.set(201, row.get(RMOVANA_NUMRIG));
 | 
						||
        lista_rips.set(202, row.get(RMOVANA_DESCR));
 | 
						||
        lista_rips.set(203, row.get(RMOVANA_CODCONTO));
 | 
						||
        lista_rips.set(204, row.get(RMOVANA_CODCMS));
 | 
						||
        lista_rips.set(205, row.get(RMOVANA_CODCCOSTO));
 | 
						||
        lista_rips.set(209, row.get(RMOVANA_SEZIONE));
 | 
						||
        lista_rips.set(210, row.get(RMOVANA_IMPORTO));
 | 
						||
      }
 | 
						||
      break;
 | 
						||
    default:
 | 
						||
      break;
 | 
						||
    }
 | 
						||
 | 
						||
 | 
						||
    splitted = lista_rips.run() == K_ENTER;
 | 
						||
    if (splitted)
 | 
						||
    {
 | 
						||
      TAnal_ripartizioni_batch selected_rip;
 | 
						||
      selected_rip.read('I', lista_rips.row().get(0));
 | 
						||
      split_cg_row(row, selected_rip);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  else
 | 
						||
    split_cg_row(row, rrip);
 | 
						||
 | 
						||
  return splitted;
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_msk::is_ripartible_movcg(bool& has_multirip)
 | 
						||
{
 | 
						||
  bool is_ripartible_movcg = true;
 | 
						||
 | 
						||
  const TString& numregcg = get(F_NUMREGCG);
 | 
						||
  TRecord_array cg(numregcg, LF_RMOV);
 | 
						||
 | 
						||
  TString query;
 | 
						||
  for (int r = cg.last_row(); r > 0; r--)
 | 
						||
  {
 | 
						||
    const TRectype& row = cg.row(r);
 | 
						||
    const TBill zio(row);
 | 
						||
    if (zio.is_analitico())
 | 
						||
    {
 | 
						||
      //se il conto <20> valido per l'analitica cerca,nell'annoes indicato, delle ripartizioni pertinenti a tale conto
 | 
						||
      const int annoes = row.get_int(RMV_ANNOES);
 | 
						||
      const TAnal_ripartizioni_batch& rrip = _cache_rip.righe_interattive(zio, annoes);
 | 
						||
      const long rrip_items = rrip.rows();  
 | 
						||
 | 
						||
      //solo per conti analitici (!_use_pdc)
 | 
						||
      if (!_use_pdc && rrip_items <= 0) // Non trovato una ripartizione valida per il povero conto
 | 
						||
      {
 | 
						||
        is_ripartible_movcg = error_box(FR("Non esiste una ripartizione del conto %d.%d.%ld\n"
 | 
						||
                       "presente sulla riga %d del movimento %ld"),
 | 
						||
                       zio.gruppo(), zio.conto(), zio.sottoconto(),
 | 
						||
                       r, atol(numregcg));
 | 
						||
        break;
 | 
						||
      } //if(rrip_items..
 | 
						||
 | 
						||
      //controlla se ci sono pi<70> ripartizioni sorelle; in questo caso deve avvisare chi lo chiama di questo fatto..
 | 
						||
      //..in modo da non utilizzare il metodo delle colonne costanti; alla prima multiripartizione deve uscire perch<63>..
 | 
						||
      //..is_ripartible_movcg sar<61> true (se ho una multiripartizione allora <20> ripartibile) e has_multirip potrebbe..
 | 
						||
      //..tornare a false nella riga successiva
 | 
						||
      has_multirip = rrip.has_multirip();
 | 
						||
      if (_use_pdc && has_multirip)
 | 
						||
        return is_ripartible_movcg;
 | 
						||
 | 
						||
    } //if(zio.is_analitico..
 | 
						||
  } //for(int r=cg.last_row..
 | 
						||
 | 
						||
  return is_ripartible_movcg;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::load_cg_row(const TRectype& row)
 | 
						||
{
 | 
						||
  //se il conto <20> valido per l'analitica cerca,nell'annoes indicato, delle ripartizioni pertinenti a tale conto
 | 
						||
  const TBill zio(row);
 | 
						||
  if (zio.is_analitico())
 | 
						||
  {
 | 
						||
    const int annoes = row.get_int(RMV_ANNOES);
 | 
						||
    const TAnal_ripartizioni_batch& rrip = _cache_rip.righe_interattive(zio, annoes);
 | 
						||
    const long rrip_items = rrip.rows(); 
 | 
						||
 | 
						||
    bool splitted = rrip_items > 0;
 | 
						||
    if (splitted)
 | 
						||
    {
 | 
						||
      //se sa che ci sono varie ripartizioni interattive relative a questo conto deve trovarne la lista e cercare la..
 | 
						||
      //..pi<70> adatta all'utonto
 | 
						||
      if (rrip.has_multirip())
 | 
						||
        splitted = multi_split_cg_row(row, rrip);
 | 
						||
      else  //se invece c'<27> una sola ripartizione possibile la applica e via!
 | 
						||
        split_cg_row(row, rrip);
 | 
						||
    }
 | 
						||
    if (!splitted)  // Non ho trovato nessuno schema di ripartizione valido
 | 
						||
    {
 | 
						||
      // Creo una riga nuova
 | 
						||
      TSheet_field& sheet = sfield(F_RIGHE);
 | 
						||
      TToken_string& riga = sheet.row(-1);
 | 
						||
      const TImporto imp(row.get_char(RMV_SEZIONE), row.get_real(RMV_IMPORTO));
 | 
						||
      imp2row(imp, riga);              // Ci copio l'importo
 | 
						||
      riga.add(row.get(RMV_DESCR), 2); // e la descrizione della riga contabile 
 | 
						||
 | 
						||
      if (_use_pdc)
 | 
						||
      {
 | 
						||
        TMask_field* f = sheet.sheet_mask().find_by_fieldname(RMOVANA_CODCONTO);
 | 
						||
        const int pos = sheet.cid2index(f->dlg());
 | 
						||
        TString8 str;
 | 
						||
        str = row.get(RMV_GRUPPO);     str.right_just(3, '0'); riga.add(str, pos-2);
 | 
						||
        str = row.get(RMV_CONTO);      str.right_just(3, '0'); riga.add(str, pos-1);
 | 
						||
        str = row.get(RMV_SOTTOCONTO); str.right_just(6, '0'); riga.add(str, pos);
 | 
						||
      }
 | 
						||
    } //else di rrip_items > 0...
 | 
						||
  } //if(zio.is_analitico(...
 | 
						||
}
 | 
						||
 | 
						||
// A partire dal movimento contabile calcola il totale documento ed eventualmente prepara lo sheet
 | 
						||
void TMovanal_msk::load_cg_mov()
 | 
						||
{
 | 
						||
  const TString& numregcg = get(F_NUMREGCG);
 | 
						||
  const TRectype& mov = cache().get(LF_MOV, numregcg);
 | 
						||
  set(F_DATAREG, mov.get(MOV_DATAREG));
 | 
						||
  if (mode() == MODE_INS)
 | 
						||
  {
 | 
						||
    set(F_DATACOMP, mov.get(MOV_DATACOMP));
 | 
						||
    set(F_DESCR, mov.get(MOV_DESCR));
 | 
						||
  }
 | 
						||
  set(F_CODCAUS, mov.get(MOV_CODCAUS), 0x2);
 | 
						||
  set(F_NUMDOC,  mov.get(MOV_NUMDOC));
 | 
						||
  set(F_DATADOC, mov.get(MOV_DATADOC));
 | 
						||
  set(F_TIPODOC, mov.get(MOV_TIPODOC));
 | 
						||
  set(F_TIPOCF, mov.get(MOV_TIPO));
 | 
						||
	set(F_CODCF, mov.get(MOV_CODCF), 0x3);
 | 
						||
 | 
						||
  TImporto totdoc;
 | 
						||
  TRecord_array cg(numregcg, LF_RMOV);
 | 
						||
  const bool autoinsert = sfield(F_RIGHE).empty(); 
 | 
						||
  for (int i = 1; i <= cg.rows(); i++)
 | 
						||
  {
 | 
						||
    const TRectype& row = cg.row(i);
 | 
						||
    const TBill zio(row);
 | 
						||
    if (zio.is_analitico())
 | 
						||
    {
 | 
						||
      const TImporto imp(row.get_char(RMV_SEZIONE), row.get_real(RMV_IMPORTO));
 | 
						||
      totdoc += imp;
 | 
						||
      if (autoinsert)
 | 
						||
        load_cg_row(row);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  set(F_TOTDOC, totdoc.valore());
 | 
						||
  const char sez[2] = { totdoc.sezione(), '\0' };
 | 
						||
  set(F_SEZIONE, sez);
 | 
						||
}
 | 
						||
 | 
						||
int TMovanal_msk::get_constant_columns(TToken_string& tok) const
 | 
						||
{
 | 
						||
  int n = 0;
 | 
						||
  TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
  const int items = sf.items();
 | 
						||
  if (items > 0)
 | 
						||
  {
 | 
						||
    TMask& m = sf.sheet_mask();
 | 
						||
    for (int f = 0; f < m.fields(); f++)
 | 
						||
    {
 | 
						||
      const TMask_field& mf = m.fld(f);
 | 
						||
      const TFieldref* fr = mf.field();
 | 
						||
      if (fr != NULL && !fr->name().starts_with(RMOVANA_CODCONTO))
 | 
						||
      {
 | 
						||
        const int i = sf.cid2index(mf.dlg());
 | 
						||
        if (i >= 2)
 | 
						||
        {
 | 
						||
          const TString campione = sf.row(0).get(i);
 | 
						||
          if (campione.full())
 | 
						||
          {
 | 
						||
            int j;
 | 
						||
            for (j = items-1; j > 0; j--)
 | 
						||
            {
 | 
						||
              if (campione != sf.row(j).get(i))
 | 
						||
                break;
 | 
						||
            }
 | 
						||
            if (j == 0)
 | 
						||
            {
 | 
						||
              tok.add(campione, i);
 | 
						||
              n++;
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return n;
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | 
						||
{
 | 
						||
	static TString __codcms;
 | 
						||
 | 
						||
  switch (o.dlg())
 | 
						||
  {
 | 
						||
  case F_DATAREG:
 | 
						||
    if ((e == fe_modify || e == fe_close) && !query_mode())
 | 
						||
    {
 | 
						||
      const TDate datareg = o.get();
 | 
						||
      const TEsercizi_contabili ec;
 | 
						||
      if (ec.date2esc(datareg) <= 0)
 | 
						||
        return error_box(((TEdit_field&)o).get_warning());
 | 
						||
      if (e == fe_close && field(F_DATACOMP).empty())
 | 
						||
        set(F_DATACOMP, datareg);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_DATACOMP:
 | 
						||
    if ((e == fe_modify || e == fe_close) && !query_mode())
 | 
						||
    {
 | 
						||
      const TDate datareg = get(F_DATAREG);
 | 
						||
      TDate datacomp = o.get();
 | 
						||
      if (!datacomp.ok())
 | 
						||
        datacomp = datareg;
 | 
						||
 | 
						||
      const bool preventivo = get(F_TIPO).full();
 | 
						||
      //i movimenti normali devono avere data competenza nel presente o passato!!
 | 
						||
      if (!preventivo && datacomp > datareg)
 | 
						||
        return error_box(TR("La data di competenza non puo' superare la data di registrazione"));
 | 
						||
 | 
						||
      const TEsercizi_contabili ec;
 | 
						||
      int ae = ec.date2esc(datacomp);
 | 
						||
 | 
						||
      //movimenti preventivi in esercizi futuri
 | 
						||
      if (ae <= 0 && preventivo && datacomp > datareg)
 | 
						||
        ae = ec.date2esc(datareg) + datacomp.year() - datareg.year();
 | 
						||
 | 
						||
      if (ae > 0)
 | 
						||
        set(F_ANNOES, ae, 0x1);
 | 
						||
      else
 | 
						||
        return error_box(((TEdit_field&)o).get_warning());
 | 
						||
 | 
						||
      const int ar = ec.date2esc(datareg);
 | 
						||
      const int ap = ec.pred(ar);
 | 
						||
      
 | 
						||
      //preventivi un anno indietro, nel presente o nel futuro
 | 
						||
      if (preventivo)
 | 
						||
      {
 | 
						||
        if (ae < ap)
 | 
						||
          return error_box(FR("La data di competenza non pu<70> precedere l'esercizio %d"), ap);
 | 
						||
      }
 | 
						||
      else  //normali solo un anno indietro o nel presente
 | 
						||
      {
 | 
						||
        if (ae != ar && ae != ap)
 | 
						||
          return error_box(FR("La data di competenza deve appartenere all'esercizio in corso o al precedente"));
 | 
						||
      }
 | 
						||
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_DATAFCOMP:
 | 
						||
    if (e == fe_modify || e == fe_close)
 | 
						||
    {
 | 
						||
      const TDate datacomp = get(F_DATACOMP);
 | 
						||
      const TDate datafcomp = o.get();
 | 
						||
      if (datafcomp.ok())
 | 
						||
      {
 | 
						||
        if (datafcomp < datacomp)
 | 
						||
          return error_box(((TEdit_field&)o).get_warning());
 | 
						||
      }
 | 
						||
      else
 | 
						||
        o.set(datacomp.string()); //se la data fine competenza viene lasciata vuota -> e' uguale alla datacomp
 | 
						||
    }
 | 
						||
    
 | 
						||
    break;
 | 
						||
  case F_RIGHE:
 | 
						||
    if (e == se_enter)
 | 
						||
    {
 | 
						||
      const int r = int(jolly);
 | 
						||
 | 
						||
			aggiorna_saldo_riga(r);      
 | 
						||
    }
 | 
						||
    if (e == se_notify_modify)
 | 
						||
    {
 | 
						||
			TSheet_field & s = sfield(F_RIGHE);
 | 
						||
		  TMask & m = s.sheet_mask(); 
 | 
						||
      const int r = int(jolly);
 | 
						||
 | 
						||
			completa_conto(r);
 | 
						||
			s.update_mask(r);
 | 
						||
		  const bool pdc_req = ca_config().get_bool("PdciRequired");
 | 
						||
			if (pdc_req)
 | 
						||
			{
 | 
						||
				for (short id = _pcon_start; id < _pcon_end; id++)
 | 
						||
				{
 | 
						||
					TEdit_field & e = m.efield(id);
 | 
						||
					
 | 
						||
					e.check_type(CHECK_REQUIRED);
 | 
						||
					e.set_dirty();
 | 
						||
					
 | 
						||
					const bool ok = e.check();
 | 
						||
 | 
						||
					e.check_type(CHECK_NORMAL);
 | 
						||
					if (!ok)
 | 
						||
						return error_box("Manca il conto analitico");
 | 
						||
				}
 | 
						||
			}
 | 
						||
    }
 | 
						||
    if (e == se_query_modify)
 | 
						||
    {
 | 
						||
			TSheet_field & s = sfield(F_RIGHE);
 | 
						||
      const int r = int(jolly);
 | 
						||
	
 | 
						||
			__codcms.cut(0);
 | 
						||
			if (_cms_start > 0)
 | 
						||
				for (short j = _cms_start; j <= _cms_end; j++)
 | 
						||
					__codcms << s.row(r).get(s.cid2index(j));
 | 
						||
		}
 | 
						||
    if (e == se_notify_modify)
 | 
						||
    {
 | 
						||
      // Ho la gestione commesse al primo livello ed i centri di costo al secondo?
 | 
						||
			if (_cms_start > 0 && _cms_start < _cdc_start) 
 | 
						||
			{
 | 
						||
        const int r = int(jolly);
 | 
						||
			  TSheet_field & s = sfield(F_RIGHE);
 | 
						||
			  TMask & m = s.sheet_mask(); 
 | 
						||
				const TRectype & curr = ((TEdit_field &) m.field(_cms_start)).browse()->cursor()->curr();
 | 
						||
				const TString & codcms = curr.get(COMMESSE_CODCMS);
 | 
						||
        // Cerco di proporre il centro di costo di default sulla commessa 
 | 
						||
				if (__codcms != codcms)
 | 
						||
				{
 | 
						||
					const TString codcosto = curr.get(COMMESSE_CODCOSTO);
 | 
						||
          if (codcosto.full())
 | 
						||
          {
 | 
						||
					  for (short i = _cdc_start; i <= _cdc_end; i++)
 | 
						||
					  {
 | 
						||
						  TEdit_field & e = m.efield(i);
 | 
						||
						  const TFieldref * f = e.field();
 | 
						||
 | 
						||
						  if (f != NULL)
 | 
						||
						  {
 | 
						||
							  const int from = f->from();
 | 
						||
							  const int to = f->to();
 | 
						||
 | 
						||
							  m.set(i, codcosto.sub(from, to), 0x2);
 | 
						||
							  s.update_row(r);
 | 
						||
							  s.force_update(r);
 | 
						||
						  }
 | 
						||
					  }
 | 
						||
				  }
 | 
						||
        }
 | 
						||
			}
 | 
						||
		}
 | 
						||
    if (e == fe_close)
 | 
						||
    {
 | 
						||
      const TImporto totdoc(get(F_SEZIONE)[0], get_real(F_TOTDOC));
 | 
						||
      TImporto totrig;
 | 
						||
      TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
      FOR_EACH_SHEET_ROW(sf, i, row)
 | 
						||
      {
 | 
						||
        TImporto imp; row2imp(*row, imp);
 | 
						||
        totrig += imp;
 | 
						||
        
 | 
						||
        //controlli sullo sheet in uscita!! Servono in quanto, anche scrivendo cazzate, l'utente potrebbe..
 | 
						||
        //..registrare lo stesso il movimento cliccando su FINE e rispondendo SI alla successiva richiesta..
 | 
						||
        //..di conferma registrazione!
 | 
						||
        if (sf.dirty())
 | 
						||
        {
 | 
						||
          sf.check_row(i, 0); //si usa 0 per simulare la row2mask senza check aggiuntivi che potrebbero sputtanare qualche campo (es. commessa al crpa)
 | 
						||
          TMask& rm = sf.sheet_mask();
 | 
						||
          FOR_EACH_MASK_FIELD(rm, j, fld)
 | 
						||
          {
 | 
						||
            if (fld->has_check() && !fld->check(FINAL_CHECK))
 | 
						||
            {
 | 
						||
              TString msg;
 | 
						||
              msg << TR("Valore errato nel campo ") << fld->prompt();
 | 
						||
              return error_box(msg);
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
 | 
						||
      if (totrig != totdoc)
 | 
						||
      {
 | 
						||
        if (yesno_box(FR("Il totale delle righe e' %s %s, mentre il totale documento e' %s %s.\n"
 | 
						||
                     "Si desidera allineare il totale di testata a quello delle righe?"),
 | 
						||
                     totrig.valore().string(), totrig.sezione() == 'D' ? TR("Dare") : TR("Avere"),
 | 
						||
                     totdoc.valore().string(), totdoc.sezione() == 'D' ? TR("Dare") : TR("Avere")))
 | 
						||
        {
 | 
						||
          set(F_SEZIONE, totrig.sezione());
 | 
						||
          set(F_TOTDOC, totrig.valore());
 | 
						||
        }
 | 
						||
        else
 | 
						||
          return false;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case S_DARE:
 | 
						||
  case S_AVERE:
 | 
						||
    if (e == fe_modify)
 | 
						||
    {
 | 
						||
      TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
      if (!o.empty())
 | 
						||
        o.mask().reset(o.dlg() == S_DARE ? S_AVERE : S_DARE);
 | 
						||
      const int r = sfield(F_RIGHE).selected();
 | 
						||
      sf.update_row(r);
 | 
						||
      aggiorna_saldo_riga(r);      
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_NUMREGCG:
 | 
						||
    if (e == fe_init)
 | 
						||
    {
 | 
						||
      const bool vuoto = o.empty();
 | 
						||
      enable(-5, vuoto);
 | 
						||
      if (!vuoto)
 | 
						||
        load_cg_mov();
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_BLOCCATO:
 | 
						||
    if (e == fe_modify)
 | 
						||
    {
 | 
						||
      enable(DLG_SAVEREC);  // Altrimenti non riesco a registrare la variazione di stato
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_RESET:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      bool has_multirip = false;
 | 
						||
      if (is_ripartible_movcg(has_multirip))
 | 
						||
      {
 | 
						||
        TToken_string constants;
 | 
						||
        const int cc = get_constant_columns(constants);
 | 
						||
        TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
        sf.destroy();
 | 
						||
        load_cg_mov();
 | 
						||
        if (cc > 0 && !has_multirip) // Se ci sono colonne costanti le recupera da quelle vecchie salvate
 | 
						||
        {
 | 
						||
          TString campione;
 | 
						||
          FOR_EACH_SHEET_ROW(sf, i, row)
 | 
						||
          {
 | 
						||
            for (int i = constants.items()-1; i > 0; i--)
 | 
						||
            {
 | 
						||
              constants.get(i, campione);
 | 
						||
              if (!campione.blank())
 | 
						||
                row->add(campione, i);
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
        sf.force_update();
 | 
						||
      }
 | 
						||
      else
 | 
						||
        disable(F_RESET);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  default:
 | 
						||
    if (e == fe_modify && o.dlg() >= S_CDC1 && o.dlg() <= S_CON4)
 | 
						||
    {
 | 
						||
      TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
      const int r = sf.selected();
 | 
						||
      sf.update_row(r);
 | 
						||
      aggiorna_saldo_riga(r);  
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
// Prende dalla riga r dello sheet i dati da scrivere nel record rec dei movimenti analitici
 | 
						||
bool TMovanal_msk::row2rec(int r, TRectype& rec) const
 | 
						||
{
 | 
						||
  TSheet_field& sheet = sfield(F_RIGHE);
 | 
						||
  if (r < 0 || r >= sheet.items())
 | 
						||
    return false;
 | 
						||
 | 
						||
  rec.put(RMOVANA_ANNOES,   get(F_ANNOES));
 | 
						||
  rec.put(RMOVANA_DATACOMP, get(F_DATACOMP));
 | 
						||
  
 | 
						||
  TToken_string& row = sheet.row(r);
 | 
						||
  const real dare = row.get(sheet.cid2index(S_DARE));
 | 
						||
  const real avere = row.get();
 | 
						||
  if (dare.is_zero())
 | 
						||
  {
 | 
						||
    rec.put(RMOVANA_SEZIONE, 'A');
 | 
						||
    rec.put(RMOVANA_IMPORTO, avere);
 | 
						||
  }
 | 
						||
  else
 | 
						||
  {
 | 
						||
    rec.put(RMOVANA_SEZIONE, 'D');
 | 
						||
    rec.put(RMOVANA_IMPORTO, dare);
 | 
						||
  }
 | 
						||
 | 
						||
  TMask& sm = sheet.sheet_mask();
 | 
						||
  for (int i = sm.fields()-1; i >= 0; i--)
 | 
						||
  {
 | 
						||
    const TMask_field& mf = sm.fld(i);
 | 
						||
    const TFieldref* fr = mf.field();
 | 
						||
    if (fr != NULL)
 | 
						||
    {
 | 
						||
      const int idx = sheet.cid2index(mf.dlg());
 | 
						||
      const char* s = row.get(idx);
 | 
						||
      if (s != NULL)
 | 
						||
        fr->write(s, rec);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::imp2row(const TImporto& imp, TToken_string& row) const
 | 
						||
{
 | 
						||
  row.add(imp.sezione() == 'D' ? imp.valore().string() : "", 0);
 | 
						||
  row.add(imp.sezione() == 'A' ? imp.valore().string() : "", 1);
 | 
						||
}
 | 
						||
 | 
						||
TToken_string& TMovanal_msk::rec2row(const TRectype& rec, int r) const
 | 
						||
{
 | 
						||
  CHECK(rec.num() == LF_RMOVANA, "Bad record type");
 | 
						||
  TSheet_field& sheet = sfield(F_RIGHE);
 | 
						||
  TMask& sm = sheet.sheet_mask();
 | 
						||
 | 
						||
  TToken_string& row = sheet.row(r);
 | 
						||
 | 
						||
  const TImporto imp(rec.get_char(RMOVANA_SEZIONE), rec.get_real(RMOVANA_IMPORTO));
 | 
						||
  imp2row(imp, row);
 | 
						||
 | 
						||
  // Carica tutti gli altri campi dopo le colonne Dare/Avere
 | 
						||
  for (int i = sm.fields()-1; i >= 0; i--)
 | 
						||
  {
 | 
						||
    TMask_field& mf = sm.fld(i);
 | 
						||
    const TFieldref* fr = mf.field();
 | 
						||
    if (fr != NULL)
 | 
						||
    {
 | 
						||
      const int idx = sheet.cid2index(mf.dlg());
 | 
						||
      row.add(fr->read(rec), idx);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  return row;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::row2imp(const TToken_string& row, TImporto& imp) const
 | 
						||
{
 | 
						||
  real dare; row.get(0, dare); 
 | 
						||
  real avere; row.get(1, avere);
 | 
						||
  if (dare.is_zero())
 | 
						||
    imp.set('A', avere);
 | 
						||
  else
 | 
						||
    imp.set('D', dare);
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_msk::row2imp(int r, TImporto& imp) const
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
  if (r >= 0 && r < sf.items())
 | 
						||
  {
 | 
						||
    const TToken_string& row = sf.row(r);
 | 
						||
    row2imp(row, imp);
 | 
						||
  }
 | 
						||
  else
 | 
						||
    imp.set('D', ZERO);
 | 
						||
  return !imp.is_zero();
 | 
						||
}
 | 
						||
 | 
						||
const TToken_string& TMovanal_msk::rec2key(const TRectype& rec) const
 | 
						||
{
 | 
						||
  TToken_string& key = get_tmp_string();
 | 
						||
  key = get(F_TIPO);
 | 
						||
  key.add(rec.get(RMOVANA_ANNOES));
 | 
						||
  key.add(rec.get(RMOVANA_CODCCOSTO));
 | 
						||
  key.add(rec.get(RMOVANA_CODCMS));
 | 
						||
  key.add(rec.get(RMOVANA_CODFASE));
 | 
						||
  key.add(rec.get(RMOVANA_CODCONTO));
 | 
						||
  return key;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::reset_saldi()
 | 
						||
{
 | 
						||
  _saldi.destroy();
 | 
						||
}
 | 
						||
 | 
						||
TImporto& TMovanal_msk::saldo(const TRectype& rec)
 | 
						||
{
 | 
						||
  const TToken_string& key = rec2key(rec);
 | 
						||
  TImporto* imp = (TImporto*)_saldi.objptr(key);
 | 
						||
  if (imp == NULL)
 | 
						||
  {
 | 
						||
    const TRectype& saldo = cache().get(LF_SALDANA, key);
 | 
						||
    const char* fld_sez = NULL;
 | 
						||
    const char* fld_val = NULL;
 | 
						||
    switch (get(F_TIPO)[0])
 | 
						||
    {
 | 
						||
    case 'P': fld_sez = SALDANA_SEZIONEP; fld_val = SALDANA_SALDOP; break;
 | 
						||
    case 'V': fld_sez = SALDANA_SEZIONEV; fld_val = SALDANA_SALDOV; break;
 | 
						||
    default : fld_sez = SALDANA_SEZIONE;  fld_val = SALDANA_SALDO;  break;
 | 
						||
    }
 | 
						||
    imp = new TImporto(saldo.get_char(fld_sez), saldo.get_real(fld_val));
 | 
						||
    _saldi.add(key, imp);
 | 
						||
  }
 | 
						||
  return *imp;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::completa_conto(int r)
 | 
						||
{
 | 
						||
  TRectype rec(LF_RMOVANA);
 | 
						||
  row2rec(r, rec);
 | 
						||
	TString conto = rec.get(RMOVANA_CODCONTO);
 | 
						||
 | 
						||
	if (conto.blank())
 | 
						||
	{
 | 
						||
		TToken_string key;
 | 
						||
		const TString4 livsup = ca_config().get("FathFasi");
 | 
						||
 | 
						||
		if (livsup.blank())
 | 
						||
			key.add("");
 | 
						||
		else
 | 
						||
			if (livsup == "CDC")
 | 
						||
				key.add(rec.get(RMOVANA_CODCCOSTO));
 | 
						||
			else
 | 
						||
				key.add(rec.get(RMOVANA_CODCMS));
 | 
						||
		key.add(rec.get(RMOVANA_CODFASE));
 | 
						||
		conto = cache().get(LF_FASI, key, FASI_CODCONTO);
 | 
						||
		if (conto.blank())
 | 
						||
		{
 | 
						||
			for (int i = 2; conto.blank()&& i > 0; i--)
 | 
						||
			{
 | 
						||
				const TString4 level = ca_config().get("Level", NULL, i);
 | 
						||
 | 
						||
				if (level == "CMS")
 | 
						||
					conto = cache().get(LF_COMMESSE, rec.get(RMOVANA_CODCMS), COMMESSE_CODCONTO);
 | 
						||
				else
 | 
						||
					if (level == "CDC")
 | 
						||
						conto = cache().get(LF_CDC, rec.get(RMOVANA_CODCCOSTO), CDC_CODCONTO);
 | 
						||
			}
 | 
						||
		}
 | 
						||
		if (conto.full())
 | 
						||
		{
 | 
						||
			rec.put(RMOVANA_CODCONTO, conto);
 | 
						||
			rec2row(rec, r);
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_msk::aggiorna_saldo_riga(int r)
 | 
						||
{
 | 
						||
  TRectype rec(LF_RMOVANA);
 | 
						||
  row2rec(r, rec);
 | 
						||
  const TToken_string& key = rec2key(rec);
 | 
						||
 | 
						||
  TImporto sld = saldo(rec);
 | 
						||
  
 | 
						||
  TSheet_field& sheet = sfield(F_RIGHE);
 | 
						||
  FOR_EACH_SHEET_ROW(sheet, i, row)
 | 
						||
  {
 | 
						||
    row2rec(i, rec);
 | 
						||
    const TToken_string& k = rec2key(rec);  
 | 
						||
    if (k == key)
 | 
						||
    {
 | 
						||
      real dare; row->get(0, dare); 
 | 
						||
      real avere; row->get(1, avere);
 | 
						||
      if (dare.is_zero())
 | 
						||
        sld += TImporto('A', avere);
 | 
						||
      else
 | 
						||
        sld += TImporto('D', dare);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  sld.normalize();
 | 
						||
  set(F_DARE,  sld.sezione() == 'D' ? sld.valore() : ZERO);
 | 
						||
  set(F_AVERE, sld.sezione() == 'A' ? sld.valore() : ZERO);
 | 
						||
}
 | 
						||
 | 
						||
int TMovanal_msk::create_sheet_fields(int lf, int& y, short& dlg, bool required)
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
  TMask& sm = sf.sheet_mask();
 | 
						||
  const int h = ca_create_fields(sm, 0, lf, 1, y, dlg, dlg+50);
 | 
						||
 | 
						||
  for (int i = 0; i < h; i++)
 | 
						||
  {
 | 
						||
    TEdit_field& fld = sm.efield(dlg+i);
 | 
						||
    int logic = lf;
 | 
						||
    if (logic == LF_FASI)
 | 
						||
    {
 | 
						||
      const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI);
 | 
						||
      if (fasinfo.parent() != 0)
 | 
						||
      {
 | 
						||
        const TMultilevel_code_info& parinfo = ca_multilevel_code_info(fasinfo.parent());
 | 
						||
        if (i < parinfo.levels())
 | 
						||
          logic = fasinfo.parent();
 | 
						||
      }
 | 
						||
    }
 | 
						||
 | 
						||
    if (logic == LF_PCON)
 | 
						||
    {
 | 
						||
      const TFieldref* f = fld.field();
 | 
						||
      const TString& fieldname = f->name();
 | 
						||
 | 
						||
      if (fieldname == "GRUPPO") 
 | 
						||
        fld.set_field("CODCONTO[1,3]"); else
 | 
						||
      if (fieldname == "CONTO") 
 | 
						||
        fld.set_field("CODCONTO[4,6]"); else
 | 
						||
      if (fieldname == "SOTTOCONTO") 
 | 
						||
        fld.set_field("CODCONTO[7,12]");
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      const char* fieldname = NULL;
 | 
						||
      switch(logic)
 | 
						||
      {
 | 
						||
      case LF_CDC     : fieldname = RMOVANA_CODCCOSTO; break;
 | 
						||
      case LF_COMMESSE: fieldname = RMOVANA_CODCMS;   break;
 | 
						||
      case LF_FASI    : fieldname = RMOVANA_CODFASE;  break;
 | 
						||
      default         : fieldname = RMOVANA_CODCONTO; break;
 | 
						||
      }
 | 
						||
      TFieldref* f = (TFieldref*)fld.field();
 | 
						||
      f->set_name(fieldname);
 | 
						||
    }
 | 
						||
    
 | 
						||
    fld.check_type(required ? CHECK_REQUIRED : CHECK_NORMAL);
 | 
						||
 | 
						||
    TEdit_field& dfld = sm.efield(dlg+50+i);
 | 
						||
    dfld.set_field(EMPTY_STRING); // Toglie campi che fan saltare gli output!
 | 
						||
  }
 | 
						||
 | 
						||
  y += h+1;
 | 
						||
  dlg += h;
 | 
						||
  return h;
 | 
						||
}
 | 
						||
 | 
						||
//metodo per la creazione delle righe dello sheet con le righe movimento analitico
 | 
						||
//si basa sulla configurazione
 | 
						||
void TMovanal_msk::create_sheet()
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_RIGHE);
 | 
						||
  TMask& sm = sf.sheet_mask();
 | 
						||
  sm.hide(-1);
 | 
						||
 | 
						||
  const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI);
 | 
						||
 | 
						||
	TConfig& ini = ca_config();
 | 
						||
  const bool fsc_req = ini.get_bool("FscRequired");
 | 
						||
 | 
						||
  int y = 3;
 | 
						||
  short dlg = S_CDC1+100; // id del primo campo da generare
 | 
						||
	_cdc_start = _cdc_end = -1;
 | 
						||
	_cms_start = _cms_end = -1;
 | 
						||
 | 
						||
  for (int i = 0; i < 2; i++)
 | 
						||
  {
 | 
						||
    const TString& level = ini.get("Level", NULL, i+1);  // Legge il livello 1 o 2
 | 
						||
    if (level == "CDC")                                  // Crea centro di costo 
 | 
						||
    {
 | 
						||
			_cdc_start = dlg;
 | 
						||
			_cdc_end = dlg + ca_multilevel_code_info(LF_CDC).levels()-1;
 | 
						||
      if (fasinfo.parent() == LF_CDC)
 | 
						||
        create_sheet_fields(LF_FASI, y, dlg, fsc_req);
 | 
						||
      else
 | 
						||
      {
 | 
						||
        const bool cdc_req = ini.get_bool("CdcRequired");
 | 
						||
        create_sheet_fields(LF_CDC, y, dlg, cdc_req);
 | 
						||
      }
 | 
						||
    }
 | 
						||
	else
 | 
						||
		if (level == "CMS")                                   // Crea commessa
 | 
						||
		{
 | 
						||
		  _cms_start = dlg;
 | 
						||
			_cms_end = dlg + ca_multilevel_code_info(LF_COMMESSE).levels()-1;
 | 
						||
		  if (fasinfo.parent() == LF_COMMESSE)
 | 
						||
			  create_sheet_fields(LF_FASI, y, dlg, fsc_req);
 | 
						||
		  else
 | 
						||
		  {
 | 
						||
				const bool cms_req = ini.get_bool("CmsRequired");
 | 
						||
				create_sheet_fields(LF_COMMESSE, y, dlg, cms_req);
 | 
						||
			}
 | 
						||
		}
 | 
						||
  }
 | 
						||
 | 
						||
  if (fasinfo.levels() > 0 && fasinfo.parent() <= 0)
 | 
						||
    create_sheet_fields(LF_FASI, y, dlg, fsc_req);
 | 
						||
 | 
						||
  _use_pdc = ini.get_bool("UsePdcc");
 | 
						||
	_pcon_start = dlg;
 | 
						||
  create_sheet_fields(_use_pdc ? LF_PCON : LF_PCONANA, y, dlg, false);
 | 
						||
	_pcon_end = dlg;
 | 
						||
  
 | 
						||
  for (short id = S_CON4+100; id >= S_CDC1+100; id--)
 | 
						||
  {
 | 
						||
    const int pos = sm.id2pos(id);
 | 
						||
    if (pos >= 0)
 | 
						||
    {
 | 
						||
      TMask_field& f = sm.fld(pos);
 | 
						||
      const int size = f.size();
 | 
						||
      const TString& prompt = f.prompt();
 | 
						||
      sf.set_column_header(id, prompt);
 | 
						||
      sf.set_column_justify(id, f.is_kind_of(CLASS_REAL_FIELD));
 | 
						||
      sf.set_column_width(id, (max(3+size, prompt.len()+1)) * CHARX);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      sf.delete_column(id);
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TMovanal_msk::TMovanal_msk() : TAutomask("ca2100a") 
 | 
						||
{
 | 
						||
  create_sheet();
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMovanal_app
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TMask* TMovanal_app::get_mask(int)
 | 
						||
{
 | 
						||
  return _msk;
 | 
						||
}
 | 
						||
 | 
						||
TRelation* TMovanal_app::get_relation() const
 | 
						||
{
 | 
						||
  return _rel;
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_app::get_next_key(TToken_string& key)
 | 
						||
{ 
 | 
						||
  long num = 1;
 | 
						||
  TLocalisamfile movana(LF_MOVANA);
 | 
						||
  if (movana.last() == NOERR)
 | 
						||
    num += movana.get_long(MOVANA_NUMREG);
 | 
						||
  key.format("%d|%ld", F_NUMREG, num);
 | 
						||
  return true; 
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::write_rows(const TMask& m)
 | 
						||
{
 | 
						||
  TAnal_mov& mov = (TAnal_mov&)_rel->curr();
 | 
						||
  mov.destroy_rows();
 | 
						||
 | 
						||
  // Scandisce lo sheet e riempie il recarray
 | 
						||
  TSheet_field& sheet = m.sfield(F_RIGHE);
 | 
						||
  FOR_EACH_SHEET_ROW(sheet, i, row)
 | 
						||
  {
 | 
						||
    const real dare = row->get(0), avere = row->get();
 | 
						||
    if (dare.is_zero() && avere.is_zero())  // Scarta righe vuote
 | 
						||
      continue;
 | 
						||
    
 | 
						||
    TRectype& rec = mov.new_row(); // Crea una riga nuova
 | 
						||
    _msk->row2rec(i, rec);
 | 
						||
 | 
						||
  } //FOR_EACH_SHEET...
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::read_rows(const TMask& m)
 | 
						||
{
 | 
						||
  const TAnal_mov& mov = (const TAnal_mov&)_rel->curr();
 | 
						||
  const TRecord_array& a = mov[LF_RMOVANA];
 | 
						||
  
 | 
						||
  TSheet_field& sheet = m.sfield(F_RIGHE);
 | 
						||
  sheet.destroy();
 | 
						||
  _msk->reset_saldi();
 | 
						||
  for (int i = 1; i <= a.rows(); i++)
 | 
						||
  {
 | 
						||
    const TRectype& rec = a.row(i);
 | 
						||
    _msk->rec2row(rec, i-1);
 | 
						||
 | 
						||
    TImporto imp; _msk->row2imp(i-1, imp);
 | 
						||
    TImporto& sld = _msk->saldo(rec);
 | 
						||
    sld -= imp;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_app::protected_record(TRectype& rec)
 | 
						||
{
 | 
						||
  return rec.get_bool(MOVANA_BLOCCATO);
 | 
						||
}
 | 
						||
 | 
						||
int TMovanal_app::write(const TMask& m)
 | 
						||
{
 | 
						||
  m.autosave(*_rel);
 | 
						||
  write_rows(m);
 | 
						||
  return _rel->write();
 | 
						||
}
 | 
						||
 | 
						||
int TMovanal_app::rewrite(const TMask& m)
 | 
						||
{
 | 
						||
  m.autosave(*_rel);
 | 
						||
  write_rows(m);
 | 
						||
  return _rel->rewrite();
 | 
						||
}
 | 
						||
 | 
						||
int TMovanal_app::read(TMask& m)
 | 
						||
{
 | 
						||
  const int err = TRelation_application::read(m);
 | 
						||
  if (err == NOERR)
 | 
						||
    read_rows(m);
 | 
						||
  return err;
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::init_query_mode(TMask& m)
 | 
						||
{
 | 
						||
  ((TMovanal_msk&)m).show_locked_buttons();
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::init_insert_mode(TMask& m)
 | 
						||
{
 | 
						||
  ((TMovanal_msk&)m).show_locked_buttons();
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::init_modify_mode(TMask& m)
 | 
						||
{
 | 
						||
  ((TMovanal_msk&)m).show_locked_buttons();
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::ini2sheet(TConfig& ini, TSheet_field& sheet)
 | 
						||
{
 | 
						||
  TString8 para; 
 | 
						||
  para.format("%d,1", LF_RMOVANA);
 | 
						||
  if (ini.set_paragraph(para))  // Esiste la prima riga?
 | 
						||
  {
 | 
						||
    TRectype rec(LF_RMOVANA); // Crea una riga di appoggio
 | 
						||
    sheet.destroy();          // Azzera lo sheet 
 | 
						||
    _msk->reset_saldi();      // Azzera i saldi 
 | 
						||
 | 
						||
    for (int r = 1; ; r++)
 | 
						||
    {
 | 
						||
      para.format("%d,%d", LF_RMOVANA, r);
 | 
						||
      if (!ini.set_paragraph(para))
 | 
						||
        break;
 | 
						||
 | 
						||
      // Riempie il record temporaneo coi dati del .ini
 | 
						||
      rec.zero();
 | 
						||
      for (int i = 0; i < rec.items(); i++)
 | 
						||
      {
 | 
						||
        const char* field = rec.fieldname(i);
 | 
						||
        const TString& str = ini.get(field);
 | 
						||
        if (str.full())
 | 
						||
          rec.put(field, str);
 | 
						||
      }
 | 
						||
      _msk->rec2row(rec, r-1);  // Riempie la riga dello sheet a partire da record
 | 
						||
 | 
						||
      // Aggiorna saldo in base all'importo della riga
 | 
						||
      TImporto imp; _msk->row2imp(r-1, imp);
 | 
						||
      TImporto& sld = _msk->saldo(rec);
 | 
						||
      sld -= imp;
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
void TMovanal_app::sheet2ini(TSheet_field& sheet,TConfig& ini)
 | 
						||
{
 | 
						||
  TRectype rec(LF_RMOVANA); // Crea una riga di appoggio
 | 
						||
  TString8 para;
 | 
						||
  
 | 
						||
  FOR_EACH_SHEET_ROW(sheet, i, row)
 | 
						||
  {
 | 
						||
    rec.zero();
 | 
						||
    rec.put(RMOVANA_NUMREG, _msk->get(F_NUMREG));
 | 
						||
    rec.put(RMOVANA_NUMRIG, i+1);
 | 
						||
    _msk->row2rec(i, rec);
 | 
						||
 | 
						||
    para.cut(0) << LF_RMOVANA << ',' << (i+1);
 | 
						||
    ini.set_paragraph(para);
 | 
						||
 | 
						||
    for (int i = 0; i < rec.items(); i++)
 | 
						||
    {
 | 
						||
      const char* field = rec.fieldname(i);
 | 
						||
      const TString& str = rec.get(field);
 | 
						||
      if (str.full())
 | 
						||
        ini.set(field, str);
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_app::user_create()
 | 
						||
{
 | 
						||
  _rel = new TRelation(LF_MOVANA);
 | 
						||
  _rel->file().set_curr(new TAnal_mov);
 | 
						||
  _msk = new TMovanal_msk;
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
bool TMovanal_app::user_destroy()
 | 
						||
{
 | 
						||
  delete _msk; _msk = NULL;
 | 
						||
  delete _rel; _rel = NULL;
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
int ca2100(int argc, char* argv[])
 | 
						||
{
 | 
						||
  TMovanal_app app;
 | 
						||
  app.run(argc, argv, TR("Movimenti analitici"));
 | 
						||
  return 0;
 | 
						||
}
 |