#include #include #include #include #include #include "../cg/cg2101.h" #include "../cg/cglib02.h" #include "celib.h" #include "ce2101.h" #include "ce4400a.h" #include "ammce.h" #include "cespi.h" #include "movam.h" #include "movce.h" //=============================================================================================== //maschera class TTrasf_mov_ce_cg_mask: public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TTrasf_mov_ce_cg_mask():TAutomask("ce4400a") { ditta_cespiti().init_mask(*this); } }; bool TTrasf_mov_ce_cg_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DATACALC: if (e == fe_close) { const TDate data_fine_es = get(F_FINE_ES); const TDate data_ini_es = get(F_INIZIO_ES); TDate datacalc = o.get(); if (datacalc < data_ini_es) return error_box("La data di calcolo deve essere pari o successiva alla data inizio dell'esercizio selezionato"); if (!datacalc.ok()) { datacalc = data_fine_es; o.set(datacalc.string()); } if (datacalc < data_ini_es || datacalc > data_fine_es) return error_box(TR("La data di calcolo deve appartenere all'esercizio selezionato!")); } break; case F_DATAREG: if (e == fe_modify || e == fe_close) { const int ese = get_int(F_ESERCIZIO); TDate datalim; TEsercizi_contabili esc; const int nesen = esc.next(ese); if (nesen > 0) { datalim = esc[nesen].fine(); } else { datalim = esc[ese].fine(); datalim.addyear(1); } TDate datareg = o.get(); if (datareg > datalim) return error_box(FR("La data registrazione deve essere inferiore al %s"), datalim.string()); } default: break; } return true; } //============================================================================================== // Metodi static che servono in giro static long get_new_numreg() { TLocalisamfile mov(LF_MOV); mov.last(); //primo numero libero da usare come numreg return mov.curr().get_long(MOV_NUMREG) + 1; } static void fill_head(TRectype& head, const TDate& datacomp, const TDate& datareg, const long numreg, const TString& codcaus, const bool definitivo, const TString& numdoc, const TString& tipodoc, const TDate& datadoc) { TEsercizi_contabili esc; const int codes = esc.date2esc(datacomp); head.put(MOV_ANNOES, codes); head.put(MOV_NUMREG, numreg); head.put(MOV_DATAREG, datareg); head.put(MOV_DATACOMP, datacomp); head.put(MOV_CODCAUS, codcaus); //campi dei soli movimenti di vendita/eliminazione head.put(MOV_NUMDOC, numdoc); head.put(MOV_TIPODOC, tipodoc); head.put(MOV_DATADOC, datadoc); if (!definitivo) head.put(MOV_PROVVIS, 'C'); } //=============================================================================================== //Rectype da utilizzare per la creazione delle righe movimento contabili. Deriva da LF_RMOV ma ha.. //..3 valori in piu' (gruppo,specie,categoria) che servono per gli ordinamenti in fase di generazione.. //..movimenti contabili class TRigamov : public TRectype { TString4 _spc; int _grp, _cat; public: virtual int compare(const TSortable& s) const; const TRectype& categoria() const; const TString& descr_categoria() const; TRigamov(const int grp, const TString& spc, const int cat) : TRectype(LF_RMOV) { _grp = grp; _spc = spc; _cat = cat; } }; const TRectype& TRigamov::categoria() const { return ditta_cespiti().categoria(_grp, _spc, _cat, true); } const TString& TRigamov::descr_categoria() const { TString& wrkstring = get_tmp_string(); wrkstring << _grp << ' ' << _spc << ' ' << _cat << ' ' ; wrkstring << ditta_cespiti().categoria(_grp, _spc, _cat, false).get("S0"); return wrkstring; } //confrontatore di saldi_per_codice int TRigamov::compare(const TSortable& s) const { int cmp = 0; const TRigamov& sc = (const TRigamov&)s; cmp = _grp - sc._grp; if (cmp == 0) { cmp = _spc.compare(sc._spc); if (cmp == 0) cmp = _cat - sc._cat; } return cmp; } //=============================================================================================== //Struct che serve per avere ammortamenti per categoria (Codcat|Qamm_tot|Qperse_tot) struct TSaldo_per_codice :public TSortable { TString4 _spc; int _grp, _cat; TString16 _idcespite; real _qnor, _qant, _qacc;//, _qperse; void add(const TRectype& rec_ammce); virtual int compare(const TSortable& s) const; const TRectype& categoria() const; const TString& descr_categoria() const; int compila_rmov(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log, const int movdett) const; int genera_righe(TArray& righe_mov, TLog_report& log, const int movdett) const; TSaldo_per_codice(const int grp, const TString& spc, const int cat, const char* idcespite = "") : _grp(grp),_spc(spc), _cat(cat), _idcespite(idcespite) {} }; void TSaldo_per_codice::add(const TRectype& rec_ammce) { //valore totale degli ammortamenti del cespite di tipo qnor,qant,qacc che trova in AMMCE const real qnor = rec_ammce.get_real(AMMCE_QNOR); const real qant = rec_ammce.get_real(AMMCE_QANT); const real qacc = rec_ammce.get_real(AMMCE_QACC); //valore totale delle qperse del cespite che trova in AMMCE //const real qperse = rec_ammce.get_real(AMMCE_QPERSE); _qnor += qnor; _qant += qant; _qacc += qacc; // _qperse += qperse; } //confrontatore di saldi_per_codice int TSaldo_per_codice::compare(const TSortable& s) const { int cmp = 0; const TSaldo_per_codice& sc = (const TSaldo_per_codice&)s; cmp = _grp - sc._grp; if (cmp == 0) { cmp = _spc.compare(sc._spc); if (cmp == 0) { cmp = _cat - sc._cat; if (cmp == 0) cmp = _idcespite.compare(sc._idcespite); } } return cmp; } bool str2bill(const TString& stringona, const int pos, TBill& zio) { const int gr = atoi(stringona.mid(pos, 3)); const int co = atoi(stringona.mid(pos+3, 3)); if (co <= 0) return false; const long so = atoi(stringona.mid(pos+6, 6)); zio.set(gr, co, so); return true; } int TSaldo_per_codice::compila_rmov(const int tipo, const int riga_nor, TArray& righe_mov, TLog_report& log, const int movdett) const { int pos = 0; const char* field = "S1"; real quota; switch (tipo) { case 1: quota = _qnor; pos = 24; break; case 2: quota = _qant; pos = 36; break; case 3: quota = _qacc; pos = 48; break; default: break; } if (quota <= ZERO) return -1; const TRectype& rec_ccc = categoria(); const TString& stringona = rec_ccc.get(field); TBill zio; if (!str2bill(stringona, pos, zio)) { pos = 24; if (tipo == 1 || !str2bill(stringona, pos, zio)) { TString msg; msg << TR("Manca il conto per le quote ammortamento normali della categoria ") << descr_categoria(); log.log(2, msg); return -1; } } if (pos == 24 && riga_nor >= 0) { TRectype& rmovnor = (TRectype&)righe_mov[riga_nor]; rmovnor.add(RMV_IMPORTO, quota); return riga_nor; } TRigamov* rmov = new TRigamov(_grp, _spc, _cat); rmov->put(RMV_SEZIONE, "D"); rmov->put(RMV_IMPORTO, quota); //conto e descrizione dipendono dal livello di dettaglio stabilito nella configurazione del collegamento CG/CE switch (movdett) { case 0: //dettaglio per categoria rmov->put(RMV_DESCR, rmov->descr_categoria()); break; case 1: //dettaglio per cespite { const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite); rmov->put(RMV_DESCR, rec_cespi.get(CESPI_DESC)); } break; case 2: //dettaglio per cespite con sottoconto=idcespite (idcespite numerico e di 6 cifre max!) { const TRectype& rec_cespi = cache().get(LF_CESPI, _idcespite); rmov->put(RMV_DESCR, rec_cespi.get(CESPI_DESC)); bool ok = real::is_natural(_idcespite); if (ok) { const long sottoc = atol(_idcespite); ok = sottoc > 0 && sottoc < 1000000; if (ok) { zio.set(zio.gruppo(), zio.conto(), sottoc); ok = zio.find(); } } if (!ok) { TString msg; msg.format(FR("Il codice cespite %s non e' un sottoconto valido"), (const char*)_idcespite); log.log(2, msg); } } break; default: break; } zio.put(*rmov); return righe_mov.add(rmov); } //metodo di alto livello per la compilazione delle righe contabili;chiama il metodo di basso livello.. //..compila_rmov con i parametri caso x caso int TSaldo_per_codice::genera_righe(TArray& righe_mov, TLog_report& log, const int movdett) const { const int righe_prima = righe_mov.items(); const int riga_nor = compila_rmov(1, -1, righe_mov, log, movdett); const int riga_ant = compila_rmov(2, riga_nor, righe_mov, log, movdett); const int riga_acc = compila_rmov(3, riga_nor, righe_mov, log, movdett); // const int riga_persa = compila_rmov(4, -1, righe_mov, log, movdett); const int righe_dopo = righe_mov.items(); return righe_dopo - righe_prima; //messo qui tanto per poter compilare } const TRectype& TSaldo_per_codice::categoria() const { //viene chiamato il metodo standard della ditta_cespiti con l'ultimo parametro true in modo che usi solo... //...le categorie valide per il collegamento alla contabilita' (tabella CCC) return ditta_cespiti().categoria(_grp, _spc, _cat, true); } const TString& TSaldo_per_codice::descr_categoria() const { TString& wrkstring = get_tmp_string(); wrkstring << _grp << ' ' << _spc << ' ' << _cat << ' ' ; wrkstring << ditta_cespiti().categoria(_grp, _spc, _cat, false).get("S0"); return wrkstring; } //=============================================================================================== //TMovimentoPN_CE class TMovimentoPN_CE : public TMovimentoPN { TSaldo_agg _sagg; protected: void salda_rmov(const bool add); public: virtual int read(TIsamop op = _isequal, TReclock lockop = _nolock); virtual int write(bool force = true); virtual int rewrite(bool force = true); virtual int remove(); TRectype& nuova_riga(); TRectype& nuova_riga(const TRectype& row); }; void TMovimentoPN_CE::salda_rmov(const bool add) { _sagg.set_anno_es(curr().get_int(MOV_ANNOES)); _sagg.set_movprovv(curr().get_char(MOV_PROVVIS) > ' '); _sagg.set_movimentato(true); TBill zio; TImporto imp; for (int i = 0; i < cg_items(); i++) { const TRectype& rmov = cg(i); //riga i-esima corrente zio.get(rmov); imp.set(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO)); _sagg.aggiorna(zio, imp, add); } } int TMovimentoPN_CE::read(TIsamop op, TReclock lockop) { int err = TMovimentoPN::read(op, lockop); if (err == NOERR) { _sagg.reset(); salda_rmov(false); } return err; } int TMovimentoPN_CE::remove() { int err = TMovimentoPN::remove(); if (err == NOERR) { _sagg.registra(); _sagg.reset(); } return err; } int TMovimentoPN_CE::write(bool force) { int err = TMovimentoPN::write(force); if (err == NOERR) { salda_rmov(true); _sagg.set_num_ulmov(curr().get_long(MOV_NUMREG)); _sagg.set_data_ulmov(curr().get_date(MOV_DATAREG)); _sagg.registra(); } return err; } int TMovimentoPN_CE::rewrite(bool force) { int err = TMovimentoPN::rewrite(force); if (err == NOERR) { salda_rmov(true); _sagg.registra(); } return err; } //nuova riga fondo TRectype& TMovimentoPN_CE::nuova_riga() { TRectype& riga = cg(-1); riga.put(RMV_NUMRIG, cg_items()); riga.put(RMV_ANNOES, curr().get(MOV_ANNOES)); return riga; } //nuova riga normale TRectype& TMovimentoPN_CE::nuova_riga(const TRectype& row) { TRectype& riga = cg(-1); riga = row; riga.put(RMV_NUMRIG, cg_items()); riga.put(RMV_ANNOES, curr().get(MOV_ANNOES)); //resettatore del saldo ad ogni nuovo movimento (righe tot presenti 1 = nuovo movimento) if (cg_items() == 1) _sagg.reset(); return riga; } //=============================================================================================== //TAmmortamento_per_cespite class TPlus_minus : public TSaldo_per_codice { TArray _ammmv, _movam, _movce; public: void genera_mov_elim_ven(TConfig& config_ditta_ce, const TDate& datacomp, const TDate& datareg, const bool definitivo, TLog_report& log) const; TPlus_minus(const int gruppo, const TString& specie, const int categoria, const TArray& ammmv, const TArray& movam, const TArray& movce) : TSaldo_per_codice(gruppo, specie, categoria), _ammmv(ammmv), _movam(movam), _movce(movce) {} }; //metodo per la generazione dei movimenti dovuti a plus/minus void TPlus_minus::genera_mov_elim_ven(TConfig& config_ditta_ce, const TDate& datacomp, const TDate& datareg, const bool definitivo, TLog_report& log) const { //parametri da utilizzare piu' volte TString4 codcaus; //conti fondo, immobilizzo, sopravenienza passiva, plusvalenza, minusvalenza cespite const TString& stringona = categoria().get("S1"); TBill zio_fondo; str2bill(stringona, 12, zio_fondo); if (!zio_fondo.find()) { TString msg; msg << TR("Conto del fondo errato o mancante per la categoria ") << descr_categoria(); log.log(2, msg); return; } TBill zio_immobilizzo; str2bill(stringona, 0, zio_immobilizzo); if (!zio_immobilizzo.find()) { TString msg; msg << TR("Conto di immobilizzo errato o mancante per la categoria ") << descr_categoria(); log.log(2, msg); return; } //Riempie i campi della testata movimento long numreg = get_new_numreg(); //attenzione!! ci possono essere piu' movimenti per lo stesso cespite!!! -> ciclo sui movce.items() for (int i = 0; i < _movce.items(); i++) { const TRectype& movce = (const TRectype&)_movce[i]; const TRectype& movam = (const TRectype&)_movam[i]; //causale movimento const real impven = movce.get_real(MOVCE_IMPVEN); const bool eliminazione = impven == ZERO; //estremi documento di vendita const TString& numdoc = movce.get(MOVCE_NDOC); const TString& tipodoc = movce.get(MOVCE_TPDOC); const TDate& datadoc = movce.get_date(MOVCE_DTDOC); if (eliminazione) codcaus = config_ditta_ce.get("COAUEL"); else codcaus = config_ditta_ce.get("COAUCH"); if (codcaus.empty()) { TString msg; msg << TR("Causale di vendita o eliminazione mancante"); log.log(2, msg); return; } //movimento contabile TMovimentoPN_CE pn; TRectype& head = pn.curr(); fill_head(head, datacomp, datareg, numreg, codcaus, definitivo, numdoc, tipodoc, datadoc); head.put(MOV_DESCR, movce.get(MOVCE_DESC)); numreg ++; //incrementa il numreg per l'eventuale testata successiva //Aggiunge le righe //le prime 2 righe sono comuni a tutti i tipi di movimento (esistono solo con importo non nullo) //riga 1: fondo const real val_fondo_cesp = movam.get_real(MOVAM_QNOR) + movam.get_real(MOVAM_QANT) + movam.get_real(MOVAM_QACC); if (!val_fondo_cesp.is_zero()) { TRectype& riga_fondo = pn.nuova_riga(); riga_fondo.put(RMV_SEZIONE, 'D'); riga_fondo.put(RMV_IMPORTO, val_fondo_cesp); //somma qnor+qant+qacc in movam); zio_fondo.put(riga_fondo); riga_fondo.put(RMV_DESCR, TR("Fondo")); } //riga 2: immobilizzo const real val_imm_cesp = movce.get_real(MOVCE_CSTO); if (!val_imm_cesp.is_zero()) { TRectype& riga_immobilizzo = pn.nuova_riga(); riga_immobilizzo.put(RMV_SEZIONE, 'A'); riga_immobilizzo.put(RMV_IMPORTO, val_imm_cesp); zio_immobilizzo.put(riga_immobilizzo); riga_immobilizzo.put(RMV_DESCR, TR("Immobilizzo")); } //le successive righe dipendono dai parametri del config_ditta_ce e dalla differenza di importi riga2-riga1 const real val_sopravv_pass = val_imm_cesp - val_fondo_cesp; if (eliminazione) //caso di ELIMINAZIONE cespite: { //riga 3: sopravenienza passiva (SOLO se movimento sbilanciato!) if (!val_sopravv_pass.is_zero()) { TRectype& riga_sopravv = pn.nuova_riga(); riga_sopravv.put(RMV_SEZIONE, 'D'); riga_sopravv.put(RMV_IMPORTO, val_sopravv_pass); TBill zio_sopravv(config_ditta_ce.get_int("GRCOTELI"), config_ditta_ce.get_int("COCOTELI"), config_ditta_ce.get_long("SOCOTELI")); if (!zio_sopravv.find()) { TString msg; msg << TR("Conto di sopravvenienza errato o mancante"); log.log(2, msg); return; } zio_sopravv.put(riga_sopravv); riga_sopravv.put(RMV_DESCR, TR("Sopravenienza passiva")); } } else //caso di VENDITA cespite: { //riga 3: vendita; parte comune (anche questa, come le altre, deve avere importo non nullo) if (!impven.is_zero()) { TRectype& riga_ven = pn.nuova_riga(); riga_ven.put(RMV_SEZIONE, 'D'); riga_ven.put(RMV_IMPORTO, impven); const bool tiposcrit = config_ditta_ce.get_bool("COR5PM"); if (tiposcrit) //tipo scrittura per vendita: su conto cespite (conto in categoria CCC) { zio_immobilizzo.put(riga_ven); riga_ven.put(RMV_DESCR, TR("Vendita su conto cespite")); } else //tipo scrittura per vendita: su conto vendita (conto in configurazione ditta) { TBill zio_vendita(config_ditta_ce.get_int("GRCOTVEN"), config_ditta_ce.get_int("COCOTVEN"), config_ditta_ce.get_long("SOCOTVEN")); if (!zio_vendita.find()) { TString msg; msg << TR("Conto di vendita cespite errato o mancante"); log.log(2, msg); return; } zio_vendita.put(riga_ven); riga_ven.put(RMV_DESCR, TR("Vendita su conto vendita")); } } //if(!impven.is_zero... //riga 4: plus/minus-valenza TImporto imp_fondo('D', val_fondo_cesp); TImporto imp_immobilizzo('A', val_imm_cesp); TImporto imp_ven('D', impven); TImporto imp_valenza = imp_fondo; imp_valenza += imp_immobilizzo; imp_valenza += imp_ven; if (!imp_valenza.is_zero()) //SOLO se movimento sbilanciato dopo le prime 3 righe, ovvero come le precedenti { imp_valenza.swap_section(); imp_valenza.normalize(); TRectype& riga_valenza = pn.nuova_riga(); const char sezione_valenza = imp_valenza.sezione(); riga_valenza.put(RMV_SEZIONE, sezione_valenza); riga_valenza.put(RMV_IMPORTO, imp_valenza.valore()); if (sezione_valenza == 'A') //plusvalenza { TBill zio_plus(config_ditta_ce.get_int("GRCOTPLU"), config_ditta_ce.get_int("COCOTPLU"), config_ditta_ce.get_long("SOCOTPLU")); if (!zio_plus.find()) { TString msg; msg << TR("Conto di plusvalenza errato o mancante"); log.log(2, msg); return; } zio_plus.put(riga_valenza); riga_valenza.put(RMV_DESCR, TR("Plusvalenza")); } else //minusvalenza { TBill zio_minus(config_ditta_ce.get_int("GRCOTMIN"), config_ditta_ce.get_int("COCOTMIN"), config_ditta_ce.get_long("SOCOTMIN")); if (!zio_minus.find()) { TString msg; msg << TR("Conto di minusvalenza errato o mancante"); log.log(2, msg); return; } zio_minus.put(riga_valenza); riga_valenza.put(RMV_DESCR, TR("Minusvalenza")); } } //if(!imp_valenza.is_zero... } //else di if(eliminazione... //finalmente scrive sul file qesti movimenti... int err = pn.write(); if (err != NOERR) { TString msg; msg << TR("Impossibile registrare il movimento ") << numreg << "\n"; log.log(2, msg); } else { TString msg; msg << TR("Registrato movimento ") << numreg << TR(" da movimento cespite ") << movce.get_long(MOVCE_IDMOV) << "\n"; log.log(0, msg); } } //for(int i=0;... (ciclo sui movimenti di un cespite) } //=============================================================================================== //Applicazione class TTrasf_mov_ce_cg : public TSkeleton_application { TTrasf_mov_ce_cg_mask* _mask; protected: virtual void main_loop(); virtual bool create(); virtual bool destroy(); void elabora(); void genera_mov(TArray& righe_mov, const TDate& datareg, const TDate& datacomp, const TString& codcaus, const int movdett, const bool definitivo, TLog_report& log); void delete_old_movs(const TDate& ini_es); public: }; void TTrasf_mov_ce_cg::delete_old_movs(const TDate& ini_es) { TMovimentoPN_CE pn; TRectype darec(LF_MOV); darec.put(MOV_DATAREG, ini_es); TString filtro; filtro.format("(PROVVIS==\"C\")"); TCursor cur_mov (&pn, filtro, 2, &darec); const long items = cur_mov.items(); cur_mov.freeze(); TProgind progind(items, "Eliminazione vecchi movimenti provvisori cespiti in corso...", false, true); for (cur_mov = 0; cur_mov.pos() < items; ++cur_mov) { progind.addstatus(1); pn.read(); pn.remove(); } } //metodo per la generazione di movimenti con righe per categoria (chiamata se movdett=0) void TTrasf_mov_ce_cg::genera_mov(TArray& righe_mov, const TDate& datareg, const TDate& datacomp, const TString& codcaus, const int movdett, const bool definitivo, TLog_report& log) { //Riempie i campi della testata movimento long numreg = get_new_numreg(); TMovimentoPN_CE pn; TRectype& head = pn.curr(); fill_head(head, datacomp, datareg, numreg, codcaus, definitivo, "", "", NULLDATE); head.put(MOV_DESCR, TR("Rilevazione quote amm. cespiti per categoria")); //Procedura di inserimento delle righe del movimento TImporto fondo; //aggiunge all'array con tutte le righe mov determinate con il calcolo una riga senza gr/sp/cat righe_mov.add(new TRigamov(0, EMPTY_STRING, 0)); //Ciclo su tutte le righe dell'array delle righe mov. Ad ogni cambio di categoria dovra' inserire la riga.. //..fondo per bilanciare la categoria, quindi scrivere sul movimento le righe ammortamento (da 1 a 3, ovvero.. //..qnor,qant,qacc) e la riga fondo di quella categoria, quindi passare alla categoria successiva. for (int i = 0; i < righe_mov.items(); i++) { //record di righe_mov const TRigamov& rigamov = (const TRigamov&)righe_mov[i]; //Controllo dell'eventuale cambio di categoria. Lo fa confrontando la riga iesima appena caricata con.. //..la riga i-1esima (la precedente,insomma) //Se la categoria e' cambiata... if (i > 0 && (rigamov.compare((const TRigamov&)righe_mov[i-1]) != 0 || pn.cg_items() > 95)) { //crea una nuova riga per metterci il fondo;in questo momento la riga e' aggiunta ma va riempita!! TRectype& riga_fondo = pn.nuova_riga(); //Inverte la sezione del fondo calcolato per il bilancamento fondo.swap_section(); //inverte la sezione fondo.normalize(); //normalizza il segno riga_fondo.put(RMV_SEZIONE, fondo.sezione()); //inserisce nella riga fondo le sezione.. riga_fondo.put(RMV_IMPORTO, fondo.valore()); //..ed il valore //Deve mettere nella riga fondo gr/co/sot che stanno nella categoria in CCC //Serve la categoria precedente, perche' in questo momento l'ha cambiata! Quindi [i-1] const TRigamov& prev_riga_mov = (const TRigamov&)righe_mov[i-1]; const TString& stringone = prev_riga_mov.categoria().get("S1"); riga_fondo.put(RMV_GRUPPO, stringone.mid(12,3)); riga_fondo.put(RMV_CONTO, stringone.mid(15,3)); riga_fondo.put(RMV_SOTTOCONTO, stringone.mid(18,6)); const TString descat = prev_riga_mov.descr_categoria(); riga_fondo.put(RMV_DESCR, descat); //se il movimento supera le 95 righe va salvato sul file MOV, poi distrutto per poter costruirne uno nuovo.. //..con le righe di righe_mov che sono rimaste if (pn.cg_items() > 95 || i == righe_mov.last() || movdett > 0) { if (movdett > 0) //se va per cespite la descrizione cambia per ogni movimento in base alla categoria { TString desc; desc << TR("Quote amm. ") << descat; desc.cut(50); head.put(MOV_DESCR, desc); } int err = pn.write(); //scrive il movimento sul file if (err != NOERR) { TString msg; msg << TR("Impossibile registrare il movimento ") << numreg << "\n"; log.log(2, msg); } else { TString msg; msg << TR("Registrato movimento ") << numreg << TR(" categoria ") << descat << "\n"; log.log(0, msg); } pn.destroy_rows(numreg); //ne elimina le righe per poter ricominciare head.put(MOV_NUMREG, ++numreg); //nuova testata per nuovo movimento } //azzera il valore del fondo in modo da ricominciare a calcolarlo con la nuova categoria fondo.reset(); } //if i>0&&rigamov.compare... //Se la categoria non e' cambiata crea normalmente la nuova riga //Aggiorna l'importo del fondo che e' pari alla somma di tutte le righe della stessa categoria TImporto imp_riga(rigamov.get_char(RMV_SEZIONE), rigamov.get_real(RMV_IMPORTO)); fondo += imp_riga; pn.nuova_riga(rigamov); } //for(inti=0;... } //metodo per gestire la successione degli eventi ad alto livello void TTrasf_mov_ce_cg::elabora() { //gettiamo un po' di parametri dalla maschera const long codes = _mask->get_long(F_ESERCIZIO); const TDate ini_es = _mask->get_date(F_INIZIO_ES); const TDate fine_es = _mask->get_date(F_FINE_ES); //deve accoppare i movimenti provvisori di prima nota da inizio esercizio ad oggi? if (_mask->get_bool(F_KILLOLD)) delete_old_movs(ini_es); //ragionamenti sulle date const TDate datareg = _mask->get_date(F_DATAREG); const TDate datacomp = min(fine_es, datareg); //se il trasferimento e' definitivo la data di calcolo e' quella finale dell'esercizio selezionato, senno'... //...e' quella indicata in F_DATACALC TDate datacalc; const bool definitivo = _mask->get_bool(F_PROVDEF); if (definitivo) datacalc = _mask->get_date(F_FINE_ES); else datacalc = _mask->get_date(F_DATACALC); //report con log errori TLog_report cont_cesp_log(TR("Contabilizzazione cespiti")); cont_cesp_log.kill_duplicates(); //Legge un po' di parametri dal ditta.ini che servono al tipo di calcolo TConfig config_ditta_ce(CONFIG_DITTA, "ce"); //Situazione fiscale (99,99%) o civilistica (1 suora su 1.000.000)? const int tpamm = config_ditta_ce.get_int("TPAMM"); //Tipo di calcolo da eseguire in base al dettaglio const int movdett = config_ditta_ce.get_int("MOVDETT"); //Codice causale da mettere nei movimenti generati const TString4 codcaus = config_ditta_ce.get("COAUQU"); //Genera movimenti plus/minus? Parametro decisivo per poter generare movimenti cg da movimenti ce const bool mov_plusmin = config_ditta_ce.get_bool("COPLMN"); //********************************************************************************** // 1) Generazione movimenti CG da ammortamenti //********************************************************************************** //programma vero e proprio (calcolo ammortamenti, selezione cespiti validi, trasferimento) TISAM_recordset cespiti("USE CESPI"); const TRecnotype nrec = cespiti.items(); //Assoc_array Categoria-QammTot TAssoc_array quote_per_codice; TArray ammo_plus_minus; TProgind pi(nrec, TR("Ricalcolo ammortamenti in corso..."), true, true); for (int i = 0; cespiti.move_to(i); i++) { if (!pi.addstatus(1)) break; //id e categoria del cespite corrente const TString& idcespite = cespiti.get(CESPI_IDCESPITE).as_string(); const int gruppo = cespiti.get(CESPI_CODCGRA).as_int(); const TString4 specie = cespiti.get(CESPI_CODSPA).as_string(); const int codcat = cespiti.get(CESPI_CODCAT).as_int(); //calcola gli ammortamenti di tutti i cespiti; situazione presa dal config_ditta poco prima //la calc_amm pensa da sola a calcolare gli ammortamenti solo per i cespiti validi //l'ultimo parametro e' true x' il calcolo viene fatto in memoria! TCespite cespite(idcespite); if (cespite.calc_amm(tpamm, datacalc, false, true)) { //controlla le quote del cespite in questione su AMMCE const TRectype& rec_ammce = cespite.amm_pro(); //in base al tipo di dettaglio sceglie il codice dell'assoc_array //movdett=0 -> codice=codice categoria (assoc_array con record per categorie) //movdett=1;2 -> codice=idcespite (assoc_array con record per cespite) TToken_string gsc; gsc.add(gruppo); gsc.add(specie); gsc.add(codcat); if (movdett != 0) gsc.add(idcespite); TSaldo_per_codice* sc = (TSaldo_per_codice*)quote_per_codice.objptr(gsc); //se non trova il codice (categoria o cespite) lo aggiunge... if (sc == NULL) { sc = new TSaldo_per_codice(gruppo, specie, codcat, idcespite); quote_per_codice.add(gsc, sc); } //..e poi somma i valori comunque sc->add(rec_ammce); //Parte relativa ad AMMMV (per generazione movimenti cg da movim. cespiti) if (mov_plusmin) { const TArray& ammmv = cespite.ammmv(); const TArray& movam = cespite.movam(); const TArray& movce = cespite.movce(); TPlus_minus* pm = new TPlus_minus(gruppo, specie, codcat, ammmv, movam, movce); ammo_plus_minus.add(pm); } } } //for(int i... TArray saldi_ordinati; //riempie l'array saldi_ordinati con gli elementi dell'assoc quote_per_codice FOR_EACH_ASSOC_OBJECT(quote_per_codice, h, k, obj) saldi_ordinati.add(h->remove_obj()); //accoppa l'assoc quote_per_codice.destroy(); //e ordina l'array per categorie e cespite (questo assurdo giro serve perche' l'assoc non e' ordinabile) saldi_ordinati.sort(); //array con le righe movimento CG TArray righe_mov; //riempie l'array delle righe movimento CG FOR_EACH_ARRAY_ITEM(saldi_ordinati, riga, sldobj) { const TSaldo_per_codice& sld = *(const TSaldo_per_codice*)sldobj; sld.genera_righe(righe_mov, cont_cesp_log, movdett); } //controllo sul numero righe dell'array (serve solo per controllo al sagace programmatore...) const int nrighemov = righe_mov.items(); //a questo punto ha l'array con le righe movimento CG completo (righe_mov); da queste righe deve costruire.. //..uno o piu' movimenti di prima nota //In base al movdett li creera' con righe per categoria o per cespite ma con fondi per categoria //E' un metodo semimagico! genera_mov(righe_mov, datareg, datacomp, codcaus, movdett, definitivo, cont_cesp_log); //********************************************************************************** // 2) Generazione movimenti CG da movimenti cespiti di vendita/eliminazione //********************************************************************************** //solo se in configurazione ditta cespiti e' attivo il flag di generazione movimenti plus/minus... if (mov_plusmin) { //controllo sul numero righe dell'array (serve solo per controllo al sagace programmatore...) const int nrigheammo = ammo_plus_minus.items(); //scandisce l'array con i valori per i movimenti di plus/minus creando un movimento cg per ognuno FOR_EACH_ARRAY_ITEM(ammo_plus_minus, riga, pmobj) { const TPlus_minus& pm = *(const TPlus_minus*)pmobj; pm.genera_mov_elim_ven(config_ditta_ce, datacomp, datareg, definitivo, cont_cesp_log); } } //*************************************** // 3) stampa il log degli errori //*************************************** TReport_book book; book.add(cont_cesp_log); book.preview(); } bool TTrasf_mov_ce_cg::create() { _mask = new TTrasf_mov_ce_cg_mask; return TSkeleton_application::create(); } bool TTrasf_mov_ce_cg::destroy() { delete _mask; return true; } void TTrasf_mov_ce_cg::main_loop() { KEY k = K_ENTER; while (k != K_QUIT) { k = _mask->run(); switch (k) { case K_ENTER: elabora(); break; default: break; } } } int ce4400(int argc, char* argv[]) { TTrasf_mov_ce_cg a; a.run(argc,argv,TR("Trasferimento cespiti in contabilita'")); return 0; }