campo-sirio/mg/mg1400.cpp
angelo 67efe69bfc Corretto programma di apertura/chiusura.
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
1997-12-18 17:34:10 +00:00

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;
}