Effettua la scrittura dei movimenti in modo un poco piu' coerente ed efficiente. git-svn-id: svn://10.65.10.50/trunk@5770 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			468 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			468 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| // mg1400.cpp : Chiusura/Apertura esercizi di magazzino
 | |
| #include <applicat.h>
 | |
| #include <mask.h>
 | |
| #include <progind.h>
 | |
| #include <tabutil.h>
 | |
| #include <modaut.h>
 | |
| #include <progind.h>
 | |
| #include "mglib.h"
 | |
| #include "..\cg\cglib01.h"
 | |
| 
 | |
| #include "mg1400.h"
 | |
| #include "movmag.h"
 | |
| 
 | |
| #define MAX_ROWS 500
 | |
| 
 | |
| enum action 
 | |
| {
 | |
|   provvisoria,
 | |
|   definitiva
 | |
| };
 | |
| 
 | |
| class TApp_openclose;
 | |
| 
 | |
| class TMask_openclose: public TMask 
 | |
| {
 | |
|   bool                ordaut;
 | |
|   TEsercizi_contabili esercizi;
 | |
|   static bool handle_close(TMask_field &, KEY);
 | |
|   static bool handle_open(TMask_field &, KEY);
 | |
|   static bool handle_what(TMask_field &, KEY);
 | |
| public:
 | |
|   TEsercizi_contabili& exercise() { return (TEsercizi_contabili&) esercizi; }
 | |
|   TMask_openclose(const bool ord) ;
 | |
|   virtual ~TMask_openclose() {}
 | |
| };
 | |
| 
 | |
| TMask_openclose::TMask_openclose(const bool ord)
 | |
|   : TMask("mg1400")
 | |
| {
 | |
|   ordaut = ord;
 | |
|   if (ordaut)
 | |
|     disable(-1);
 | |
|   set_handler(F_DATECLOSE, handle_close);
 | |
|   set_handler(F_DATEOPEN,  handle_open);
 | |
|   set_handler(F_WHAT,      handle_what);
 | |
| }
 | |
| 
 | |
| bool TMask_openclose::handle_close(TMask_field &fld, KEY k)
 | |
| {
 | |
|   TMask_openclose& mask = (TMask_openclose&)fld.mask();
 | |
|   if (k == K_ENTER || fld.to_check(k))
 | |
|   {
 | |
|     TEsercizi_contabili& ex = mask.esercizi;
 | |
|     TDate d(fld.get());
 | |
|     
 | |
|     const int es_close = ex.date2esc(d);
 | |
|     mask.set(F_ESTOCLOSE, es_close);
 | |
|     if (es_close == 0)
 | |
|       return fld.error_box("La data indicata non appartiene a nessun esercizio.");
 | |
|       
 | |
|     if (k == K_ENTER && ex.esercizio(es_close).chiusura_mag() != TDate(NULLDATE))
 | |
|       return fld.error_box("L'esercizio risulta gia' chiuso. Selezionare"
 | |
|                            " un altro esercizio o togliere il flag di chiusura.");
 | |
|     else
 | |
|     {
 | |
|       int pred = ex.pred(es_close);
 | |
|       if (k == K_ENTER && pred != 0 && ex.esercizio(pred).chiusura_mag() == TDate(NULLDATE))
 | |
|         return fld.error_box("L'esercizio precedente a quello indicato non e' ancora stato chiuso.");
 | |
|     }
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TMask_openclose::handle_open(TMask_field &fld, KEY k)
 | |
| {
 | |
|   TMask_openclose& mask = (TMask_openclose&)fld.mask();
 | |
|   if (k == K_ENTER || fld.to_check(k))
 | |
|   {
 | |
|     TDate in(mask.get(F_DATEOPEN));
 | |
|     TDate fi(mask.get(F_DATECLOSE)); 
 | |
|     if (k == K_ENTER && in <= fi )
 | |
|       return fld.warning_box ("La data di apertura del nuovo esercizio deve essere superiore alla data di chiusura dell'esercizio precedente");
 | |
|     const int es_open = mask.esercizi.date2esc(in);
 | |
|     
 | |
|     mask.set(F_ESTOOPEN, es_open);
 | |
|     if (es_open == 0)
 | |
|       return fld.error_box("La data indicata non appartiene a nessun esercizio");
 | |
|     
 | |
|     const int es_close = mask.esercizi.pred(es_open);
 | |
|     if (es_close == 0)
 | |
|       return fld.error_box("Non esiste l'esercizio precedente per la data indicata.");
 | |
|     
 | |
|     // Setta data ed esercizio di chiusura  
 | |
|     mask.set(F_ESTOCLOSE,es_close);
 | |
|     mask.set(F_DATECLOSE, mask.esercizi.esercizio(es_close).fine());
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TMask_openclose::handle_what(TMask_field &fld, KEY k)
 | |
| {
 | |
|   if (k == K_SPACE)
 | |
|   {
 | |
|     TMask_openclose& mask = (TMask_openclose&)fld.mask();
 | |
|     const int x =  atoi(fld.get());
 | |
|     const action w = (action) x;
 | |
|     mask.enable(-4, w == definitiva); // Se oper. provv. disabilita tutte le causali
 | |
|     // Le causali degli ordini sono abilitate solo se NON c'e' il modulo ordini
 | |
|     if (mask.ordaut)
 | |
|       mask.disable(-1);
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| // Corrispondenza elementi di _movimenti:
 | |
| /* elemento 0 : movimento con causale di rimanenze iniziali
 | |
|    elemento 1 :  "              "      "  In conto lav.
 | |
|    elemento 2 :  "              "      "  A  conto lav.
 | |
|    elemento 3 :  "              "      "  In prod. fin.
 | |
|    elemento 4 :  "              "      "  In prod. comp.
 | |
|    elemento 5 :  "              "      "  Ordinato fornitori
 | |
|    elemento 6 :  "              "      "  Ordinato clienti
 | |
|    elemento 7 e successivi: tutte le righe in eccesso a MAX_ROWS
 | |
| */
 | |
| 
 | |
| class TApp_openclose : public TSkeleton_application
 | |
| {
 | |
|   TLocalisamfile   *_anamag,
 | |
|                    *_umart,
 | |
|                    *_mag,
 | |
|                    *_movmag,
 | |
|                    *_rmovmag,
 | |
|                    *_stomag;
 | |
|   TMask_openclose  *_msk;
 | |
|   TArray           _movimenti; // Array di movimenti di TMov_mag
 | |
|   TString_array    _causali;   // Array delle causali per i movimenti d'apertura (7)
 | |
|   TString          _es_to_close;
 | |
|   TString          _es_to_open;
 | |
|   TString          _catven;
 | |
|   TString          _codlis;
 | |
|   TDate            _date_to_close;
 | |
|   TDate            _date_to_open;
 | |
|   action           _what;   
 | |
|   TTipo_valorizz   _calctype, _stotype; // Stotype sta per sto-cazzo
 | |
|   
 | |
| protected:
 | |
|   virtual bool create();
 | |
|   virtual bool destroy();
 | |
|   virtual void main_loop();
 | |
|   //void  scrivi_movimenti(TCursor&);
 | |
|   //void  aggiorna_saldi();
 | |
|   void compila_movimento(TMov_mag& currmov, TArticolo_giacenza& art, TRectype& rec, const int caus);
 | |
|   void chiudi_esercizio();
 | |
|   
 | |
| public:
 | |
|   TApp_openclose() {};
 | |
|   virtual ~TApp_openclose() {};
 | |
| };
 | |
| 
 | |
| bool TApp_openclose::create()
 | |
| {
 | |
|   _msk = new TMask_openclose(has_module(ORAUT));
 | |
|   _anamag  = new TLocalisamfile(LF_ANAMAG);
 | |
|   _umart   = new TLocalisamfile(LF_UMART);
 | |
|   _mag     = new TLocalisamfile(LF_MAG);
 | |
|   _movmag  = new TLocalisamfile(LF_MOVMAG);
 | |
|   _rmovmag = new TLocalisamfile(LF_RMOVMAG);
 | |
|   _stomag  = new TLocalisamfile(LF_STOMAG);
 | |
|   return TSkeleton_application::create();
 | |
| }
 | |
| 
 | |
| bool TApp_openclose::destroy()
 | |
| {
 | |
|   delete _msk;
 | |
|   delete _anamag;
 | |
|   delete _umart;
 | |
|   delete _mag;
 | |
|   delete _movmag;
 | |
|   delete _rmovmag;
 | |
|   delete _stomag;
 | |
|   return TSkeleton_application::destroy();
 | |
| }
 | |
| 
 | |
| void TApp_openclose::compila_movimento(TMov_mag& currmov, TArticolo_giacenza& art, TRectype& rec, const int caus)
 | |
| {
 | |
|   // Aggiorna la testata se il movimento e' nuovo (non ha righe)
 | |
|   if (currmov.rows() == 0)
 | |
|   {
 | |
|     TRectype& head = currmov.head();
 | |
|     head.put(MOVMAG_ANNOES, _es_to_open);
 | |
|     head.put(MOVMAG_DATAREG, _date_to_open);
 | |
|     head.put(MOVMAG_DATACOMP, _date_to_open);
 | |
|     head.put(MOVMAG_CODCAUS, _causali.row(caus));
 | |
|   } 
 | |
|   
 | |
|   // Aggiunge una nuova riga al movimento corrente
 | |
|   TString codmag(rec.get(MAG_CODMAG));
 | |
|   TString codart(rec.get(MAG_CODART));
 | |
|   TString livello(rec.get(MAG_LIVELLO));
 | |
| 
 | |
|   real qta, prezzo, val;
 | |
|   // switch sul tipo di causale per settare quantita' e prezzo:
 | |
|   switch (caus)
 | |
|   {
 | |
|     case 0: // Rimanenze iniziali
 | |
|       {
 | |
|         qta = rec.get_real(MAG_GIAC) + rec.get_real(MAG_PRODFIN)-rec.get_real(MAG_PRODCOMP)
 | |
|             + rec.get_real(MAG_ACL)  - rec.get_real(MAG_INCL); // ??corretta da AcL, IncL e InProdF ??
 | |
|         switch (_calctype)
 | |
|         {
 | |
|           case valorizz_costmedio:
 | |
|             val = art.costo_medio(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_ultcos: 
 | |
|             val = art.ultimo_costo(_es_to_close);
 | |
|             break;
 | |
|           case valorizz_mediacos:
 | |
|             val = art.media_costi(_es_to_close);
 | |
|             break;
 | |
|           case valorizz_przlist:
 | |
|             val = art.prezzo_listino(_es_to_close, _catven, _codlis);
 | |
|             break;
 | |
|           case valorizz_coststd:
 | |
|             val = art.costo_standard(_es_to_close);
 | |
|             break;
 | |
|           case valorizz_LIFOa:
 | |
|             val = art.LIFO_annuale(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_FIFOa:
 | |
|             val = art.FIFO_annuale(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_LIFO:
 | |
|             val = art.LIFO(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_FIFO:
 | |
|             val = art.FIFO(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_LIFOr:
 | |
|             val = art.LIFO_ragionieristico(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           case valorizz_FIFOr:
 | |
|             val = art.FIFO_ragionieristico(_es_to_close, codmag, livello);
 | |
|             break;
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
|         prezzo = val/qta;
 | |
|       }
 | |
|       break;
 | |
|     case 1: // In conto lav.
 | |
|       qta = rec.get_real(MAG_INCL);
 | |
|       break;
 | |
|     case 2: // A conto lav.
 | |
|       qta = rec.get_real(MAG_ACL);
 | |
|       break;
 | |
|     case 3: // In prod. fin.
 | |
|       qta = rec.get_real(MAG_PRODFIN);
 | |
|       break;
 | |
|     case 4: // In prod. com.
 | |
|       qta = rec.get_real(MAG_PRODCOMP);
 | |
|       break;
 | |
|     case 5: // Ord. forn.
 | |
|       qta = rec.get_real(MAG_ORDF);
 | |
|       val = rec.get_real(MAG_VALORDF);
 | |
|       prezzo = val/qta;
 | |
|       break;
 | |
|     case 6: // Ord. cli.
 | |
|       qta = rec.get_real(MAG_ORDC);
 | |
|       val = rec.get_real(MAG_VALORDC);
 | |
|       prezzo = val/qta;
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
|   if (qta != 0.0)
 | |
|   {
 | |
|     TRectype& riga = currmov.new_row();
 | |
|     TRecord_array& ums = art.um();
 | |
|     const int r = ums.first_row();
 | |
|     if (r > 0)
 | |
|       riga.put(RMOVMAG_UM, (ums[r]).get(UMART_UM));
 | |
|     riga.put(RMOVMAG_CODMAG, codmag);
 | |
|     riga.put(RMOVMAG_CODART, codart);
 | |
|     riga.put(RMOVMAG_LIVGIAC, livello);
 | |
|     // La causale di riga va messa solo se e' diversa da quella di testata!
 | |
|     riga.put(RMOVMAG_QUANT, qta);
 | |
|     riga.put(RMOVMAG_PREZZO, prezzo);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Chiude l'esercizio selezionato (in base al flag lo fa provvisoriamente o definitivamente)
 | |
| // L'unica differenza sta nella creazione dei movimenti d'apertura nel caso di chiusura definitiva
 | |
| void TApp_openclose::chiudi_esercizio()
 | |
| {
 | |
|   TArticolo_giacenza artgiac;
 | |
|   TRelation rel(LF_ANAMAG);
 | |
|   TCursor   cur(&rel);
 | |
|   TString descr1, descr2;
 | |
|   int err = NOERR;
 | |
|   TTable esc("ESC");
 | |
|   
 | |
|   rel.lfile().set_curr((TRectype*)&artgiac);
 | |
|   const long items = cur.items();
 | |
| 
 | |
|   rebuild_balances(_es_to_close);  // Cosi' ci assicuriamo che i saldi dell'esercizio vecchio siano a posto
 | |
|   descr1.format(_what == definitiva ? "Apertura esercizio %s" : "Aggiornamento saldi esercizio %s", (const char*) _es_to_open);
 | |
|   descr2 << descr1 << " in corso...";
 | |
|   
 | |
|   TProgind *prog = new TProgind(items, descr2, FALSE, TRUE, 10);
 | |
|   
 | |
|   // cose specifiche per chiusura definitiva...
 | |
|   // Reperisce l'ultimo movimento di magazzino per il numero di registrazione
 | |
|   _movmag->last();
 | |
|   long numreg = _movmag->get_long(MOVMAG_NUMREG) +1;
 | |
|   // Indici per i movimenti. Crea i movimenti di base (uno per ogni causale)
 | |
|   int indici[7], last = 6;
 | |
|   if (_what == definitiva)
 | |
|     for (int j=0; j < 7; j++)
 | |
|     {
 | |
|       _movimenti.add(new TMov_mag);
 | |
|       TRectype& h = ((TMov_mag&) _movimenti[j]).head();
 | |
|       h.put(MOVMAG_NUMREG, numreg++);
 | |
|       h.put(MOVMAG_DESCR,  descr1);
 | |
|       indici[j] = j;
 | |
|     }
 | |
| 
 | |
|   // Ciclo per i fottuti articoli
 | |
|   for (cur = 0L; cur.ok(); cur +=1)
 | |
|   {
 | |
|     if (_what == definitiva)
 | |
|     {
 | |
|       // Scorre i saldi del vecchio esercizio per questo TArticolo_giacenza
 | |
|       // compilando un array di almeno 7 TMov_mag
 | |
|       // Almeno 7 perche' 7 sono le causali; fissiamo il limite di righe per movimento a 500 (MAXROWS)
 | |
|       // quindi i movimenti possono essere di piu'.
 | |
|       
 | |
|       // I saldi per questo articolo
 | |
|       TArticolo_giacenza& art = (TArticolo_giacenza&)cur.curr();
 | |
|       TRecord_array& rec_arr = art.mag(_es_to_close);
 | |
|       // Scorriamo le righe...
 | |
|       const int lastrow = rec_arr.last_row();
 | |
|       for (int r = lastrow; r > 0; r = rec_arr.pred_row(r))
 | |
|       {
 | |
|         TRectype& rec = rec_arr[r];
 | |
|         for (int i = 0; i < 7; i++)
 | |
|         {
 | |
|           if (_causali.row(i).empty())
 | |
|             continue; // Salta eventuali causali vuote
 | |
|           // se il numero di righe di questo movimento eccede le 500 ne crea uno nuovo e 
 | |
|           // setta il nuovo indice
 | |
|           const int rows = ((TMov_mag&) _movimenti[indici[i]]).rows() ;
 | |
|           if (rows > MAX_ROWS)
 | |
|           {
 | |
|             _movimenti.add(new TMov_mag);
 | |
|             last++;
 | |
|             indici[i] = last;
 | |
|             TRectype& h = ((TMov_mag&) _movimenti[last]).head();
 | |
|             h.put(MOVMAG_NUMREG, numreg++); // Aggiorna il nr. reg per il prossimo movimento
 | |
|             h.put(MOVMAG_DESCR,  descr1);
 | |
|           }
 | |
|           TMov_mag& currmov = (TMov_mag&) _movimenti[indici[i]];
 | |
|           compila_movimento(currmov, art, rec, i);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       // calcola il valore delle rimanenze finali dell'esercizio vecchio
 | |
|       // e riporta il record con l'anno esercizio nuovo.
 | |
|       ((TArticolo_giacenza&)cur.curr()).riporta_saldi(_es_to_close, _es_to_open, _calctype, _catven, _codlis);
 | |
|     }
 | |
|     // Aggiornamento storico....
 | |
|     prog->addstatus(1L);
 | |
|   }
 | |
|   delete prog;    
 | |
| 
 | |
|   // Vi sarebbe  l'azzeramento saldi dell'esercizio nuovo, (in caso di chiusura definitiva)
 | |
|   // ma e' gia' fatta alla fine perche' dopo la ricostruzione movimenti l'esercizio vecchio 
 | |
|   // e' marcato come chiuso.
 | |
|     
 | |
|   if (_what == definitiva)
 | |
|   {
 | |
|     // Scorre i movimenti generati ed effettua la scrittura
 | |
|     const int items = _movimenti.items();
 | |
|     prog = new TProgind(items, "Scrittura movimenti in corso...",FALSE,TRUE,10);
 | |
|     for (int i=0; err == NOERR && i<items;i++)
 | |
|     {
 | |
|       prog->addstatus(1L);
 | |
|       TMov_mag& mov = (TMov_mag&) _movimenti[i];
 | |
|       if (mov.rows() == 0)
 | |
|         continue; // Salta eventuali movimenti senza righe (OrdC e OrdF)
 | |
|       // Effettua la rinumerazione del movimento se esso esiste gia'?
 | |
|       err = mov.write(*_movmag); 
 | |
|     }
 | |
|     delete prog;
 | |
|     
 | |
|     if (err == NOERR)
 | |
|     {
 | |
|       // Marca l'esercizio come chiuso
 | |
|       esc.put("CODTAB", _es_to_close);
 | |
|       err = esc.read();
 | |
|       if (err == NOERR)
 | |
|       {
 | |
|         esc.put("D4", _date_to_close);
 | |
|         err = esc.rewrite();
 | |
|         if (err != NOERR)
 | |
|           error_box("Errore %d in fase di chiusura esercizio %s.", err, (const char*) _es_to_close);
 | |
|       }
 | |
|       else
 | |
|         error_box("Error %d in fase di lettura esercizio %s.", err, (const char*) _es_to_close);
 | |
|     }
 | |
|     else
 | |
|       error_box("Errore %d durante la scrittura dei movimenti.",err);
 | |
|     _movimenti.destroy();
 | |
|   }
 | |
|   
 | |
|   // La ricostruzione dei saldi e' comune in entrambi i casi (definitiva o provvisoria)
 | |
|   // la rebuild_balances() deve sapere da sola se azzerare o meno le giacenze
 | |
|   // a seconda che l'esercizio precedente sia chiuso (AZZERA) o no (NON AZZERARE).
 | |
|   rebuild_balances(_es_to_open); 
 | |
| }
 | |
| 
 | |
| 
 | |
| void TApp_openclose::main_loop()
 | |
| {
 | |
|   //Preimposta valori di apertura e chiusura esercizio
 | |
|   TDate d(TODAY);
 | |
|   TEsercizi_contabili& ex = _msk->exercise();
 | |
|   const int es_open  = ex.date2esc(d);
 | |
|   if (es_open != 0)
 | |
|   {
 | |
|     _msk->set(F_DATEOPEN,ex.esercizio(es_open).inizio());
 | |
|     _msk->set(F_ESTOOPEN,es_open);
 | |
|   }
 | |
|   const int es_close = ex.pred(es_open);
 | |
|   if (es_close != 0)
 | |
|   {
 | |
|     _msk->set(F_DATECLOSE,ex.esercizio(es_close).fine());
 | |
|     _msk->set(F_ESTOCLOSE,es_close);
 | |
|   }
 | |
|   
 | |
|   while (_msk->run() == K_ENTER)
 | |
|   {
 | |
|     // Here is
 | |
|     _causali.destroy();
 | |
|     _date_to_close = _msk->get_date(F_DATECLOSE);
 | |
|     _date_to_open = _msk->get_date(F_DATEOPEN);
 | |
|     _es_to_close   = _msk->get(F_ESTOCLOSE);
 | |
|     _es_to_open    = _msk->get(F_ESTOOPEN);
 | |
|     _calctype      = (TTipo_valorizz) _msk->get_int(F_VALORIZZAZIONE);
 | |
|     _stotype       = (TTipo_valorizz) _msk->get_int(F_STOMET);
 | |
|     _what          = (action) _msk->get_int(F_WHAT); //Provvisoria o definitiva?
 | |
|     _codlis = _msk->get(F_LIST);
 | |
|     _catven = _msk->get(F_CATVEN);
 | |
|     for (short xx = F_CAURIM; xx <= F_CAUORC; xx++) // legge le causali impostate
 | |
|       _causali.add(_msk->get(xx));
 | |
|     chiudi_esercizio(); // Chiusura esercizio
 | |
|   }
 | |
| }
 | |
| 
 | |
| int mg1400(int argc, char* argv[])
 | |
| {
 | |
|   TApp_openclose a;
 | |
| 
 | |
|   a.run(argc, argv, "Apertura/Chiusura esercizio");
 | |
|   return 0;
 | |
| }
 |