/* ef0800.cpp: programma di contabilizzazione effetti Ho visto ombre di sconforto riemergere dal passato... al largo dei bastioni di Orione _|_|_ ^/ . ..\^ ___[=========]___ ___-==++""" . /. . . \ . """++==-___ __-+"" __\ .. . . | .. . | . . . /__ ""+-__ /\__+-"" `-----=====\_ _/=====-----' ""-+__/\ _/_/ ""="" \_\_ _________ .-~~~-..---..-~~~-. __________ -~.--<<<<<<<`-...--'.---.`--...-'>>>>>>>--.~- =~~.-~ ````\\_`(`._.')'_//'''' ~-.~~= [(o)/ ``.._..'' \(o) .___________________ _-_ .\==============_=_/ ____.---'---`---.____ . \_ \ \----._________.----/ . \ \ / / `-_-' . __,--`.`-'..'-_ . /____ || . `--.____,-' Did you see my apogee ? */ #include #include #include #include #include #include "../cg/cg2101.h" #include "../cg/cg2103.h" #include "../cg/cgsaldac.h" #include "../cg/cglib02.h" #include "../ve/velib04.h" #include "ef0301.h" #include "ef0800a.h" #include #include #include #include #include #include #include #define CGROWS_LIMIT 96 // Limite imposto da invii/ricezioni #define DIST_INCASSO 'I' #define DIST_SBF 'B' #define DIST_SCONTO 'S' // TContabilizzazione_mask class TContabilizzazione_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly); public: TContabilizzazione_mask(); }; // TContabilizzazione_effetti_app // Applicazione di contabilizzazione effetti class TContabilizzazione_effetti_app : public TSkeleton_application { TDate _data_op; // Data operazione TString16 _cod_caus; // Codice causale TString16 _cod_caus_pag; // Codice causale pagamenti int _cod_es; // Codice/anno esercizio bool _sc_enabled; // se TRUE il saldaconto di ditta e' abilitato bool _can_write; // se TRUE e' abilitata la scrittura. Non appena rileva un errore rimane a FALSE for this instance real _total_mov, // Totale del movimento corrente _total_mov_val;// Same as above but in valuta TString _desc_inc, _desc_pag; // Descrizioni movimento generato TMask *_msk; // maschera di selezione dati // TLocalisamfile *_attiv, // file delle attivita' (per far funzionare TRegistro) // *_fcaus, // file delle causale (per far funzionare TCausale) // *_frcaus, // file delle righe causali (per far funzionare TCausale) // *_effetti, // file degli effetti (per TDistinta) // *_reffetti, // file delle righe effetti (per TDistinta) // *_cessionari, // file dei cessionari (per TDistinta) // *_part, // file delle partite (per far funzionare TPartita) // *_scad, // file delle scadenze (per far funzionare TPartita) // *_pags, // file dei pagamenti (per far funzionare TPartita) // *_clifo, // file dei clienti // *_doc, // file dei documenti // *_pcon; // file piano dei conti TBill _banca, // conto di contropartita della banca _cliente, // conto di contropartita del cliente _trandiffcam; // conto di transizione per differenze cambi TArray_sheet *_dist_sheet; // array_sheet di distinte selezionabili per la conatabilizzazione TDistinta *_distinta; // Distinta per le elaborazioni TPartite_array *_part_array; // Array di partite da scrivere TMovimentoPN *_movimento; // Movimento di prima nota TSaldo_agg _saldo; // Saldo da aggiornare TCausale *_caus; // Causale contabile per le elaborazioni error_type _error; // Errore rilevato durante l'elaborazione long _total_bills; // Totale distinte contabilizzate. int _cur_dist_row;// Numero di riga distinta corrente (per visualizzazione errore) bool _dett_rate_att;// Dettaglia le rate su effetti attivi bool _dett_rate_pas;// Dettaglia le rate su effetti passivi protected: // TApplication // Compila la testata del movimento void compile_head_mov(); // Compila la riga di partita void compile_riga_partita(TRiga_partite& riga, const TEffetto& effetto, const TRectype& riga_effetto, int numrig); // Compila la riga di pagamento void compile_riga_pagamento(TRectype& riga_pagamento, const TEffetto& effetto, const TRectype& riga_effetto, char acc_sal); // Funzione di aggiornamento saldi una volta generato il movimento void aggiorna_saldi(); // scrive il movimento e le scadenze error_type write_all(bool chage_status = TRUE); // cerca il conto di contropartita per la distinta corrente (setta _banca) error_type search_bank_counter_bill(int tipopag=0); // cerca il conto clienti error_type search_clifo_bill(char tipo, const long codcf); // ritorna la sezione corretta per la riga di partita char sezione() const; // Ordina le righe di un effetto int sort_eff(TRecord_array& sorted); // aggiunge una riga all'array dei clienti da una riga effetto bool add_cg_row(const TEffetto& eff, const TRectype& reff, TArray& customers, TAssoc_array& banks, bool add_desc); // somma ad una riga all'array dei clienti una riga effetto void sum_cg_row(const TRectype& reff, TArray& customers, TAssoc_array& banks); // aggiunge le righe spese al movimento bool add_spese_rows(const real& spese); // aggiunge riga pagamento da riga effetto void compile_saldac(const TEffetto& eff, const TRectype& reff, TImporto& abbuoni_att, TImporto& abbuoni_pas, TArray& differenze_cam, TArray& customers); // Controlla se il pagamento dell'effetto avra' differenze cambio bool has_diffcam(const TEffetto& eff) const; // Aggiunge una riga contabile al movimento void join_row(const TRectype& row); // unisce gli array clienti/banche nel record array delle righe contabili void join_rows(TArray& customers, TAssoc_array& banks, const TImporto& abbuoni_att, const TImporto& abbuoni_pas, const TArray& differenze_cam, const real& spese); // Visualizza l'ultimo errore rilevato void display_error(); // Contabilizza l'effetto corrente void contabilize_bill(const char tipo, const long numero); // Contabilizza gli effetti void contabilize(); // costruisce lo sheet delle distinte void build_dist_sheet(); // Handler della selezione distinte static bool handle_select(TMask_field& f, KEY k); // Handler del pulsante di reset static bool handle_reset(TMask_field& f, KEY k); // Le 4 seguenti non hanno bisogno di commenti virtual void main_loop(); virtual bool create(); virtual bool destroy(); virtual void on_config_change(); public: // Verifica se non ci sono stati errori bool good() const { return _error == no_error;} error_type status() { return _error; } void set_status(error_type e) { _error = e; } TArray_sheet& dist_sheet() { return *_dist_sheet; } TContabilizzazione_effetti_app() : _msk(NULL) {} virtual ~TContabilizzazione_effetti_app() { } }; inline TContabilizzazione_effetti_app& app() { return (TContabilizzazione_effetti_app&) main_app(); } // TContabilizzazione_mask bool TContabilizzazione_mask::on_field_event(TOperable_field& f, TField_event e, long jolly) { switch (f.dlg()) { case F_DATA_OP: if (e == fe_modify || e == fe_close) { const TDate data = f.get(); TEsercizi_contabili esc; if (esc.date2esc(data) <= 0) return error_box(TR("La data deve appartenere ad un esercizio valido")); } break; case F_RESET: if (e == fe_button) { app().dist_sheet().check(-1, FALSE); reset(F_DISTINTE); } break; case F_SELECT: if (e == fe_button) { TArray_sheet& sh = app().dist_sheet(); if (sh.run() == K_ENTER) set(F_DISTINTE,sh.checked()); } break; default: break; } return TRUE; } TContabilizzazione_mask::TContabilizzazione_mask() : TAutomask("ef0800a") { } // TContabilizzazione_effetti_app void TContabilizzazione_effetti_app::build_dist_sheet() { TRelation eff_rel(LF_EFFETTI); TCursor cur_dist(&eff_rel,"TIPODIST!=\"\"",4); TRectype& rec = cur_dist.curr(); const long items = cur_dist.items(); _dist_sheet->destroy(); // resetta lo sheet delle distinte if (items > 0) { cur_dist.freeze(); cur_dist = 0; long ndist_prec = rec.get_long(EFF_NDIST); char tipo_prec = rec.get_char(EFF_TIPODIST); TDate data_prec(rec.get(EFF_DATADIST)); TString8 codabi, codcab, codprg, codval; char tipocf; bool enabled = true; int num_eff = 0; for (long i = 0; i < items; i++) { cur_dist = i; const long ndist = rec.get_long(EFF_NDIST); const char tipo = rec.get_char(EFF_TIPODIST); TDate data_dist(rec.get(EFF_DATADIST)); if (ndist != ndist_prec || tipo != tipo_prec) { TToken_string * t = new TToken_string; t->add(" ");t->add(tipo_prec); t->add(ndist_prec); t->add(num_eff); t->add(codabi); t->add(codcab); t->add(codprg); t->add(codval); t->add(tipocf); t->add(data_prec); const long pos = _dist_sheet->add(t); //aggiunge una riga allo sheet delle distinte _dist_sheet->enable_row(pos, enabled); ndist_prec = ndist; tipo_prec = tipo; data_prec = data_dist; enabled = true; num_eff = 0; } if (num_eff == 0) { codabi = rec.get(EFF_CODABIP); // Memorizza dati della prima riga codcab = rec.get(EFF_CODCABP); codprg = rec.get(EFF_PROGBNP); if (real::is_null(codprg)) codprg.cut(0); else codprg.right_just(2, '0'); codval = rec.get(EFF_CODVAL); tipocf = rec.get_char(EFF_TIPOCF); } num_eff++; // numero di effetti che compongono la distinta if (rec.get_bool(EFF_EFFCONT)) // Disabilito le distinte contabilizzate enabled = false; } TToken_string * t = new TToken_string; t->add(" "); t->add(tipo_prec); t->add(ndist_prec); t->add(num_eff); t->add(codabi); t->add(codcab); t->add(codprg); t->add(rec.get(EFF_CODVAL)); t->add(rec.get(EFF_TIPOCF)); t->add(rec.get(EFF_DATADIST)); const long pos = _dist_sheet->add(t); //aggiunge una riga allo sheet delle distinte _dist_sheet->enable_row(pos, enabled); } } bool TContabilizzazione_effetti_app::handle_reset(TMask_field& f, KEY k) { if (k == K_SPACE) { app()._dist_sheet->check(-1, FALSE); f.mask().reset(F_DISTINTE); } return TRUE; } bool TContabilizzazione_effetti_app::handle_select(TMask_field& f, KEY k) { if (k==K_SPACE) // ricerca { TArray_sheet* sh = app()._dist_sheet; if (sh->run() == K_ENTER) f.mask().set(F_DISTINTE,sh->checked()); } return TRUE; } void TContabilizzazione_effetti_app::on_config_change() { TPartita::carica_allineamento(); TConfig conf(CONFIG_DITTA, "ef"); _cod_caus = conf.get("CODCAUS"); // implementare programma di gestione parametri effetti _cod_caus_pag = conf.get("CODCAUSPAG"); // implementare programma di gestione parametri effetti _desc_inc = conf.get("DESCINC", NULL, -1, "Distinta d'incasso"); _desc_pag = conf.get("DESCPAG", NULL, -1, "Ordine di pagamento"); _dett_rate_att = conf.get_bool("DETRATATT"); // Dettaglio rate su effetti attivi _dett_rate_pas = conf.get_bool("DETRATPAS"); // Dettaglio rate su effetti passivi const long trans = conf.get_long("DIFFCAMS"); if (trans > 0) _trandiffcam.set(conf.get_int("DIFFCAMG"), conf.get_int("DIFFCAMC"), trans); _sc_enabled = conf.get_bool("GesSal","cg"); if (!has_module(CGAUT) && _sc_enabled) { error_box(TR("Impossibile contabilizzare gli effetti se il modulo Contabilita' Generale non e' abilitato")); stop_run(); } } bool TContabilizzazione_effetti_app::create() { open_files(LF_TAB, LF_TABCOM, LF_CAUSALI, LF_RCAUSALI, LF_EFFETTI, LF_REFFETTI, LF_CESS, LF_MOV, LF_RMOV, LF_PARTITE, LF_SCADENZE, LF_PAGSCA, LF_DOC, LF_CLIFO, LF_ATTIV, LF_PCON, LF_SALDI, 0); _caus = NULL; _error = no_error; _can_write = TRUE; _msk = new TContabilizzazione_mask(); _distinta = new TDistinta; _movimento = new TMovimentoPN; _dist_sheet = new TArray_sheet(-1, -1, -4, -6, TR("Selezione distinte"), HR("@1|Tipo|Numero distinta@R|Numero effetti@R|ABI@5|CAB@5|Prg.|Valuta|C/F|Data Dist.")); _part_array = new TPartite_array; return TSkeleton_application::create(); } bool TContabilizzazione_effetti_app::destroy() { if (_msk) delete _msk; if (_caus) delete _caus; if (_distinta) delete _distinta; if (_movimento) delete _movimento; if (_dist_sheet) delete _dist_sheet; if (_part_array) delete _part_array; return TApplication::destroy(); } void TContabilizzazione_effetti_app::main_loop() { build_dist_sheet(); // Preselezione della distinta specificata sulla riga di comando if (argc() >= 4) { const char tip = *argv(2); const long num = atol(argv(3)); for (int r = 0; r < _dist_sheet->items(); r++) { TToken_string& row = _dist_sheet->row(r); if (row.get_char(1) == tip && row.get_long(2) == num) { _dist_sheet->check(r); break; } } _msk->set(F_DISTINTE, _dist_sheet->checked()); } _msk->set(F_DETT_RATE_ATT, _dett_rate_att ? "X" : ""); _msk->set(F_DETT_RATE_PAS, _dett_rate_pas ? "X" : ""); while (_msk->run() == K_ENTER) { if (!_dist_sheet->one_checked()) { error_box(TR("Nessuna distinta selezionata")); continue; } _data_op = _msk->get_date(F_DATA_OP); TEsercizi_contabili esc; _cod_es = esc.date2esc(_data_op); _dett_rate_att = _msk->get_bool(F_DETT_RATE_ATT); _dett_rate_pas = _msk->get_bool(F_DETT_RATE_PAS); // Salva parametri per la prossima volta { TConfig conf(CONFIG_DITTA, "ef"); conf.set("DETRATATT", _dett_rate_att ? "X" : ""); conf.set("DETRATPAS", _dett_rate_pas ? "X" : ""); } contabilize(); _msk->reset(F_DISTINTE); build_dist_sheet(); } } void TContabilizzazione_effetti_app::display_error() { TString msg; switch (_error) { case clifo_error: msg.format(FR("Non e' possibile reperire il cliente/fornitore relativamente alla distinta %c %ld. " "Controllare la riga %d"),_distinta->tipodist(), _distinta->ndist(),_cur_dist_row+1); break; case bank_error: msg.format(FR("Non e' possibile reperire i conti di contropartita per la banca di presentazione " "relativamente alla distinta %c %ld. Controllare la tabella e la causale."),_distinta->tipodist(), _distinta->ndist()); break; case cau_abb_error: msg.format(FR("Non e' possibile reperire i conti per gli abbuoni\n" "o le differenze cambi dalla causale '%s'"), _caus->codice()); break; case cau_spe_error: msg.format(FR("Non e' possibile reperire il conto per le spese\n" "dalla causale '%s'"), _caus->codice()); break; case datadoc_error: msg.format(FR("La data distinta %s non appartiene ad un esercizio valido"), (const char*)_distinta->data_dist().string()); break; default: // Errori generici o non indicati vengono visualizzati nel punto dell'errore break; } if (!msg.blank()) warning_box(msg); _error = no_error; // reset error, as any other one would do, so you can show me the other ones. _can_write = FALSE; // But from now on u cannot write anymore. U must exit this program and repair errors occurred. } bool TContabilizzazione_effetti_app::add_cg_row(const TEffetto& eff, const TRectype& reff, TArray& customers, TAssoc_array& banks, bool add_desc) { const long numreg = _movimento->curr().get_long(MOV_NUMREG); real imp = reff.get_real(REFF_IMPORTO); TRectype* c_rec = new TRectype(LF_RMOV); // setta i valori per la riga cliente c_rec->put(RMV_ANNOES,_cod_es); c_rec->put(RMV_DATAREG,_data_op); c_rec->put(RMV_NUMREG,numreg); c_rec->put(RMV_SEZIONE,_caus->sezione_clifo()); _cliente.put(*c_rec); if (_sc_enabled) c_rec->put(RMV_ROWTYPE,"K"); TString80 desc; if (_cliente.tipo() == 'F') { if (imp >= ZERO) desc = TR("Pag. ft."); else desc = TR("Nota cr."); } else { if (imp >= ZERO) desc = TR("Inc. ft."); else desc = TR("Nota cr."); } desc << ' ' << reff.get(REFF_NFATT); if (_cliente.tipo() == 'C') desc << TR(" sc. ") << eff.get(EFF_DATASCAD); c_rec->put(RMV_DESCR, desc); if (add_desc) { TString80 head_desc = _movimento->curr().get(MOV_DESCR); head_desc << ' ' << desc; _movimento->curr().put(MOV_DESCR, head_desc); } // setta i valori per la riga banca TRectype b_r(*c_rec); TString16 key; key.format("%3d%3d%6ld",_banca.gruppo(),_banca.conto(),_banca.sottoconto()); const bool is_present = banks.is_key(key); TRectype& b_rec = is_present ? (TRectype&)banks.find(key) : b_r; // setta i valori if (!is_present) // nuova banca? allora setta la sezione ed il conto { const int tipopag = eff.get_int(EFF_TIPOPAG); int nriga = 2; if (_sc_enabled && tipopag>1 && tipopag<8) nriga = tipopag+1; b_rec.put(RMV_SEZIONE,_caus->sezione(nriga)); b_rec.put(RMV_TIPOC,_banca.tipo()); b_rec.put(RMV_GRUPPO,_banca.gruppo()); b_rec.put(RMV_CONTO,_banca.conto()); b_rec.put(RMV_SOTTOCONTO,_banca.sottoconto()); if (_sc_enabled) b_rec.put(RMV_ROWTYPE,"I"); b_rec.zero(RMV_DESCR); } real b_imp = b_rec.get_real(RMV_IMPORTO) + imp; // aggiorna l'importo per questa banca b_rec.put(RMV_IMPORTO,b_imp); banks.add(key,b_rec,is_present); c_rec->put(RMV_IMPORTO,imp); c_rec->put(RMV_CUP, eff.get(EFF_CUP)); c_rec->put(RMV_CIG, eff.get(EFF_CIG)); customers.add(c_rec); return !is_present; } void TContabilizzazione_effetti_app::sum_cg_row(const TRectype& reff, TArray& customers, TAssoc_array& banks) { const real imp = reff.get_real(REFF_IMPORTO); // setta i valori per la riga cliente TRectype& c_rec = (TRectype&)customers[customers.last()]; c_rec.add(RMV_IMPORTO, imp); // setta i valori per la riga banca TString16 key; key.format("%3d%3d%6ld",_banca.gruppo(),_banca.conto(),_banca.sottoconto()); TRectype& b_rec = (TRectype&)banks.find(key); b_rec.add(RMV_IMPORTO, imp); // aggiorna l'importo per questa banca } void TContabilizzazione_effetti_app::join_row(const TRectype& row) { const int n = _movimento->cg_items(); TRectype& riga = _movimento->cg(n); riga = row; riga.put(RMV_NUMRIG, n+1); riga.put(RMV_ANNOES,_cod_es); riga.put(MOV_DATAREG,_data_op); } bool TContabilizzazione_effetti_app::add_spese_rows(const real& spese) { if (spese.is_zero()) return false; TRectype& row_spese = _movimento->cg(-1); TRectype& row_banca = _movimento->cg(-1); TBill conto_spese; _caus->bill(11, conto_spese); const char sez_spese = _caus->sezione(11); const char sez_banca = sez_spese == 'D' ? 'A' : 'D'; row_spese.put(RMV_ANNOES,_cod_es); row_spese.put(RMV_DATAREG,_data_op); row_spese.put(RMV_SEZIONE, sez_spese); row_spese.put(RMV_IMPORTO, spese); conto_spese.put(row_spese); _banca.put(row_spese, true); row_spese.put(RMV_DESCR, _caus->desc_agg(11)); if (_sc_enabled) row_spese.put(RMV_ROWTYPE, 'G'); row_banca.put(RMV_ANNOES,_cod_es); row_banca.put(RMV_DATAREG,_data_op); row_banca.put(RMV_SEZIONE, sez_banca); row_banca.put(RMV_IMPORTO, spese); _banca.put(row_banca); conto_spese.put(row_banca, true); if (_sc_enabled) row_banca.put(RMV_ROWTYPE, 'L'); return true; } void TContabilizzazione_effetti_app::join_rows(TArray& customers, TAssoc_array& banks, const TImporto& abbuoni_att, const TImporto& abbuoni_pas, const TArray& differenze_cam, const real& spese) { // aggiunge prima i record delle righe relative ai clienti const int customer_items = customers.items(); int j; for (j = 0; j < customer_items; j++) join_row((const TRectype&) customers[j]); // e poi i record delle righe relative alle banche const int bank_items = banks.items(); TRectype* row; for (j = 0, row = (TRectype*)banks.first_item(); row != NULL && j < bank_items; j++, row = (TRectype *)banks.succ_item()) join_row(*row); // infine abbuoni e differenze cambio if (_sc_enabled) { TBill zio; TRectype riga(_movimento->cg(0)); if (!abbuoni_pas.is_zero()) { _caus->bill(9, zio); zio.put(riga); if (!zio.ok()) _error = cau_abb_error; riga.put(RMV_SEZIONE, abbuoni_pas.sezione()); riga.put(RMV_IMPORTO, abbuoni_pas.valore()); riga.put(RMV_ROWTYPE, "P"); join_row(riga); } if (!abbuoni_att.is_zero()) { _caus->bill(10, zio); zio.put(riga); if (!zio.ok()) _error = cau_abb_error; riga.put(RMV_SEZIONE, abbuoni_att.sezione()); riga.put(RMV_IMPORTO, abbuoni_att.valore()); riga.put(RMV_ROWTYPE, "A"); join_row(riga); } if (differenze_cam.items() > 0) { TImporto diffcam; for (int i = differenze_cam.items()-1; i >= 0; i--) { const TRectype& rec = (const TRectype&)differenze_cam[i]; TImporto dc(rec.get_char(RMV_SEZIONE), rec.get_real(RMV_IMPORTO)); diffcam += dc; } _caus->bill(13, zio); if (!zio.ok()) _error = cau_abb_error; zio.put(riga); riga.put(RMV_SEZIONE, diffcam.sezione()); riga.put(RMV_IMPORTO, diffcam.valore()); riga.put(RMV_ROWTYPE, "C"); join_row(riga); if (_trandiffcam.ok() && (customers.items() > 1 || differenze_cam.items() > 1)) { TRectype& rec = _movimento->cg(_movimento->cg_items()-1); _trandiffcam.put(rec); _trandiffcam.put(rec, TRUE); riga.put(RMV_SEZIONE, diffcam.sezione() == 'D' ? 'A' : 'D'); _trandiffcam.put(riga); _trandiffcam.put(riga, true); riga.zero(RMV_ROWTYPE); join_row(riga); for (int i = 0; i < differenze_cam.items(); i++) { const TRectype& rec = (const TRectype&)differenze_cam[i]; join_row(rec); } } } } if (add_spese_rows(spese)) { const char tipocf = ((const TRectype&)customers[0]).get_char(RMV_TIPOC); if (tipocf == 'C') _total_mov -= spese; else _total_mov += spese; } } error_type TContabilizzazione_effetti_app::search_clifo_bill(char tipo, const long codcf) { _error = no_error; TString8 key; key.format("%c|%ld", tipo, codcf); const TRectype & clifo = cache().get(LF_CLIFO, key); if (clifo.empty()) _cliente.set(0,0,0); else _cliente.set(clifo.get_int(CLI_GRUPPO), clifo.get_int(CLI_CONTO), codcf, tipo); if (!_cliente.ok()) // se non e' valido, reperiscilo dalla riga #1 della causale { _caus->bill(1,_cliente); // conto della riga 1 _cliente.codclifo() = codcf; if (!_cliente.ok()) _error = clifo_error; } return _error; } error_type TContabilizzazione_effetti_app::search_bank_counter_bill(int tipopag) { // reperisce i codici ABI e CAB della banca presentazione effetti dalla // distinta e va a cercarli sulla tabella BNP di ditta. // La banca di presentazione effetti e' una unica per tutta la distinta // e non puo' essere vuota _error = no_error; if (tipopag <= 0) // cerca sulla tabella e poi sulla 2a riga di causale { _banca.set(0,0,0); // resetta il conto... TString16 codtab(_distinta->abip()); codtab << _distinta->cabp(); TString4 prog = _distinta->progbnp(); if (!real::is_null(prog)) { prog.right_just(2, '0'); codtab << prog; } const TRectype& bnp = cache().get("BNP", codtab); if (!bnp.empty()) { const char* fg = NULL; const char* fc = NULL; const char* fs = NULL; const char tipodist = _distinta->tipodist(); switch (tipodist) { case DIST_SBF: fg = "I3"; fc = "I4"; fs = "I5"; break; case DIST_SCONTO: fg = "I6"; fc = "I7"; fs = "I8"; break; case DIST_INCASSO: // Default default: if (_distinta->tipocf() == 'F') { fg = "I9"; fc = "I10"; fs = "I11"; } else { fg = "I0"; fc = "I1"; fs = "I2"; } break; } const int g = bnp.get_int(fg); const int c = bnp.get_int(fc); const long s = bnp.get_long(fs); _banca.set(g,c,s); } // se non ha trovato la banca oppure il conto, verifica che vi sia // il conto sulla riga 2 della causale (solo se SC non abilitato) if (!_banca.ok()) _caus->bill(2,_banca); // conto della riga 2 // se il saldaconto non e' abilitato, il conto di contropartita sulla causale // va verificato per ogni riga di distinta, a seconda del tipo di pagamento. } else { // cerca il conto relativo alla riga di causale: // 1 Rimessa diretta o contanti (banca) riga 2 // 2 Tratta riga 3 // 3 Ricevuta bancaria riga 4 // 4 Cessione riga 5 // 5 Paghero' riga 6 // 6 Lettera di credito riga 7 // 7 Tratta accettata riga 8 // 8 Rapporti interban. diretti riga 2 // 9 Bonifici riga 2 _caus->bill(tipopag>0 && tipopag<8 ? tipopag+1:2,_banca); } if (!_banca.ok()) _error = bank_error; return _error; } char TContabilizzazione_effetti_app::sezione() const { char sezione = ' '; const char tipoc = _cliente.tipo(); tipo_movimento tm = (tipo_movimento)_caus->tipomov(); sezione = _caus->sezione(1); // Usa la sezione della causale if (sezione <= ' ') // Se non c'e' la sezione bell'e' ch'e' pronta { if (tm == tm_fattura || tm == tm_insoluto) // calcola in base al tipo movimento e sezione = (tipoc == 'C') ? 'D' : 'A'; // al tipo cliente/fornitore else sezione = (tipoc == 'C') ? 'A' : 'D'; } return sezione; } void TContabilizzazione_effetti_app::compile_head_mov() { CHECK(_caus,"Causale non allocata"); TLocalisamfile& mov = _movimento->lfile(); mov.last(); const long numreg = mov.get_long(MOV_NUMREG)+1; // Calcola il numero di registrazione const TDate datadist(_distinta->data_dist()); const TDate datacam(_distinta->data_cam()); const TString4 codval(_distinta->codval()); const real cambio(_distinta->cambio()); const long ndist = _distinta->ndist(); TEsercizi_contabili esc; if (esc.date2esc(datadist) <= 0) { if (!yesno_box(FR("Attenzione: la data distinta %s non appartiene ad un esercizio valido:\n" "Si desidera proseguire ugualmente?"), (const char*)datadist.string())) { _can_write = FALSE; return; } } TString des; des = (_distinta->tipocf() == 'F') ? _desc_pag : _desc_inc; des << ' '; switch (_distinta->tipopag()) { case 1: des << TR("rimessa diretta"); break; case 2: des << TR("tratta"); break; case 3: des << TR("ricevuta bancaria"); break; case 4: des << TR("cessione"); break; case 5: des << TR("paghero'"); break; case 6: des << TR("lettera di credito"); break; case 7: des << TR("tratta accettata"); break; case 8: des << TR("rapp. interb. dir."); break; case 9: des << TR("bonifico"); break; default: des.rtrim(); break; } des << TR(" n.") << ndist; mov.zero(); mov.put(MOV_DESCR,des); mov.put(MOV_NUMREG,numreg); mov.put(MOV_ANNOES,_cod_es); mov.put(MOV_DATAREG,_data_op); mov.put(MOV_DATACOMP,_data_op); mov.put(MOV_DATADOC,datadist); mov.put(MOV_NUMDOC,ndist); mov.put(MOV_TIPODOC,_caus->tipo_doc()); mov.put(MOV_CODCAUS,_caus->codice()); mov.put(MOV_TIPOMOV,_caus->tipomov()); if (is_true_value(codval)) { mov.put(MOV_CODVAL, codval); mov.put(MOV_DATACAM, _distinta->data_cam()); real cambio = _distinta->cambio(); const bool eurocambio = _distinta->contro_euro(); const TExchange chg(codval, cambio, eurocambio ? _exchange_contro : _exchange_base); if (eurocambio && mov.curr().exist(MOV_CONTROEURO)) { mov.put(MOV_CONTROEURO, eurocambio); cambio = chg.get_contro_change(); } else { cambio = chg.get_base_change(); } mov.put(MOV_CAMBIO, cambio); } // MOV_TOTDOC e MOV_TOTDOCVAL vengono completati prima della scrittura del movimento // e solo nel caso di saldaconto abilitato } void TContabilizzazione_effetti_app::compile_riga_partita(TRiga_partite& riga, const TEffetto& effetto, const TRectype& riga_effetto, int numrig) { const TRectype& head_mov = _movimento->curr(); riga.put(PART_TIPOMOV,_caus->tipomov()); riga.put(PART_TIPOPAG,effetto.get(EFF_TIPOPAG)); riga.put(PART_NREG,head_mov.get(MOV_NUMREG)); riga.put(PART_NUMRIG,numrig); riga.put(PART_DATAREG,head_mov.get(MOV_DATAREG)); riga.put(PART_DATADOC,head_mov.get(MOV_DATADOC)); riga.put(PART_DATAPAG,effetto.get(EFF_DATASCAD)); riga.put(PART_CODCAUS,head_mov.get(MOV_CODCAUS)); riga.put(PART_NUMDOC,head_mov.get(MOV_NUMDOC)); // Sarebbe il numero della distinta... riga.put(PART_DESCR, head_mov.get(MOV_DESCR)); riga.put(PART_SEZ,sezione()); const real imp = riga_effetto.get(REFF_IMPORTO); const real imp_val = riga_effetto.get(REFF_IMPORTOVAL); riga.put(PART_CODVAL,effetto.get(EFF_CODVAL)); riga.put(PART_DATACAM,effetto.get_date(EFF_DATACAMBIO)); real cambio = effetto.get(EFF_CAMBIO); riga.put(PART_CAMBIO, cambio); if (effetto.get_bool(EFF_CONTROEURO)) { if (!((TRectype&)riga).exist(PART_CONTROEURO)) { const TExchange chg(effetto.get(EFF_CODVAL), cambio, _exchange_contro); const real cc = chg.get_base_change(); riga.put(PART_CAMBIO, cc); } else riga.put(PART_CONTROEURO, TRUE); } riga.put(PART_TIPOCF,_cliente.tipo()); riga.put(PART_SOTTOCONTO,_cliente.sottoconto()); riga.put(PART_IMPTOTDOC,effetto.get(EFF_IMPORTO)); riga.put(PART_IMPTOTVAL,effetto.get(EFF_IMPORTOVAL)); // PART_GRUPPOCL e PART_CONTOCL sono gia' compilati dalla TPartita::new_row() // Aggiorna il totale movimento in lire e totale movimento in valuta (solo con saldaconto abilitato) if (_sc_enabled) { _total_mov += imp; _total_mov_val += imp_val; } } void TContabilizzazione_effetti_app::compile_riga_pagamento(TRectype& riga_pagamento, const TEffetto& effetto, const TRectype& riga_effetto, char acc_sal) { // ANNO, NUMPART, NRIGA, NRATA, NRIGP dovrebbero essere gia' compilati riga_pagamento.put(PAGSCA_TIPOC,_cliente.tipo()); riga_pagamento.put(PAGSCA_SOTTOCONTO,_cliente.sottoconto()); riga_pagamento.put(PAGSCA_ACCSAL,acc_sal); riga_pagamento.put(PAGSCA_IMPORTO,riga_effetto.get_real(REFF_IMPORTO)); riga_pagamento.put(PAGSCA_IMPORTOVAL,riga_effetto.get_real(REFF_IMPORTOVAL)); riga_pagamento.put(PAGSCA_TIPOCC,_banca.tipo()); riga_pagamento.put(PAGSCA_GRUPPOC,_banca.gruppo()); riga_pagamento.put(PAGSCA_CONTOC,_banca.conto()); riga_pagamento.put(PAGSCA_SOTTOCONTC,_banca.sottoconto()); riga_pagamento.put(PAGSCA_CODABI, effetto.get(EFF_CODABI)); riga_pagamento.put(PAGSCA_CODCAB, effetto.get(EFF_CODCAB)); riga_pagamento.put(PAGSCA_CODABIPR, effetto.get(EFF_CODABIP)); riga_pagamento.put(PAGSCA_CODCABPR, effetto.get(EFF_CODCABP)); // Cerca l'eventuale codice agente sul documento TString key(30); key << riga_effetto.get(REFF_PROVV) << "|"; key << riga_effetto.get(REFF_ANNODOC) << "|"; key << riga_effetto.get(REFF_CODNUM) << "|"; key << riga_effetto.get(REFF_NFATT); const TRectype & doc = cache().get(LF_DOC, key); if (!doc.empty()) riga_pagamento.put(PAGSCA_CODAG, doc.get(DOC_CODAG)); } void TContabilizzazione_effetti_app::compile_saldac(const TEffetto& eff, const TRectype& reff, TImporto& abbuoni_att, TImporto& abbuoni_pas, TArray& differenze_cam, TArray& customers) { int anno = reff.get_int(REFF_ANNO); TString16 numpart = reff.get(REFF_NUMPART); // Ricava il numero della fattura. TString16 numdoc_to_search = reff.get(REFF_CODNUM); TString16 nfatt = reff.get(REFF_NFATT); TCodice_numerazione cn; if (numdoc_to_search.not_empty() && nfatt.not_empty() && real::is_natural(nfatt)) { cn.read(numdoc_to_search); const long nf = atol(nfatt); cn.complete_num(nf, numdoc_to_search); } else // se gli estremi della fattura non sono compilati si piglia il numero della partita if (nfatt.full()) numdoc_to_search = nfatt; else numdoc_to_search = numpart; if (anno == 0 || numpart.empty()) // Se non sono gia' settati sulla riga effetto... { anno = reff.get_int(REFF_ANNODOC);// ... li va a prendere dagli estremi fattura... if (numdoc_to_search.not_empty()) { numpart = numdoc_to_search; } else // ...oppure dalla testata movimento. { // Appunto: da verificare se facciamo cosi' o generiamo un errore... anno = eff.get_date(EFF_DATADIST).year(); const char all = TPartita::allineamento_richiesto(eff.get_char(EFF_TIPOCF)); if (all == 'R') numpart.format("%7ld", eff.get_long(EFF_NDIST)); else numpart.format("%ld", eff.get_long(EFF_NDIST)); numdoc_to_search = numpart; // A mali estremi... estremi rimedi } } TPartita * partita = _part_array->exist(_cliente,anno,numpart); if (partita == NULL) // Se la partita non esiste nell'array la aggiunge { partita = new TPartita(_cliente,anno,numpart); _part_array->insert(partita); } TRiga_partite& riga_part = partita->new_row(); // Compila la riga di partita const int numrig = customers.items(); compile_riga_partita(riga_part,eff,reff, numrig); // Compila la riga di pagamento: // reperire il numero della riga partita (nrigp) appena aggiunta const int nrigp = riga_part.get_int(PART_NRIGA); ((TRectype&)reff).put(REFF_NRIGP, nrigp); // scorrere le righe della partita (nriga) per trovare il riferimento alla fattura di cui si sta effettuando il pagamento // se non la si trova allora... nriga = UNASSIGNED const int uns = (int)TPartita::UNASSIGNED; int nriga = reff.get_int(REFF_NRIGA); if (nriga == 0 || nriga == uns) { nriga = uns; for (int r = partita->last(); r > 0; r = partita->pred(r)) { const TRiga_partite& rpart = partita->riga(r); const TString16 numdoc = rpart.get(PART_NUMDOC); if (numdoc == numdoc_to_search && rpart.is_fattura()) { nriga = r; break; } } } // reperire il numero di rata (nrata) dalla riga effetto const int nrata = reff.get_int(REFF_NRATA); char acc_sal = 'A'; if (partita->esiste(nriga,nrata)) // calcola se e' a saldo o in acconto della rata { acc_sal = reff.get_char(REFF_ACCSAL); if (acc_sal != 'S' && acc_sal != 'A') acc_sal = 'A'; // Potrebbe succedere che il ACCSAL sia vuoto } else { if (nriga != uns) nriga = uns; // E' praticamente impossibile che si trovi la fattura // senza le proprie scadenze. Al limite settiamo il numero di riga per non assegnati. } // Creo una nuova riga di pagamento TRectype& old_riga_pagamento = partita->pagamento(nriga,nrata,nrigp); // compilo i campi di riga_pagamento TRectype riga_pagamento(old_riga_pagamento); compile_riga_pagamento(riga_pagamento,eff,reff, acc_sal); // Aggiorno il pagamento generando eventuali abbuoni char old_ap, new_ap; TImporto old_abb, new_abb, old_diffcam, new_diffcam; const TString4 codval = eff.get(EFF_CODVAL); const TDate datacam = eff.get(EFF_DATACAMBIO); real cambio = eff.get(EFF_CAMBIO); exchange_type et = eff.get_bool(EFF_CONTROEURO) ? _exchange_contro : _exchange_base; if (et == _exchange_contro) { if (!((TRectype&)riga_part).exist(PART_CONTROEURO)) { const TExchange chg(codval, cambio, et); cambio = chg.get_base_change(); et = _exchange_base; riga_part.put(PART_CAMBIO, cambio); } } const TValuta valuta_eff(codval, datacam, cambio, et); partita->modifica_pagamento(riga_pagamento, valuta_eff, old_ap, old_abb, old_diffcam, new_ap, new_abb, new_diffcam, TRUE); // Se ci sono abbuoni o differenze cambio... if (!new_abb.is_zero() || !new_diffcam.is_zero()) { if (new_ap == 'A') { abbuoni_att -= new_abb; // Sottraggo perche' va in sezione opposta abbuoni_att.normalize(); } if (new_ap == 'P') { abbuoni_pas -= new_abb; // Sottraggo perche' va in sezione opposta abbuoni_pas.normalize(); } if (!new_diffcam.is_zero()) { // Sottraggo perche' va in sezione opposta TImporto dc = new_diffcam; dc.normalize(); dc.swap_section(); TRectype* row = new TRectype(LF_RMOV); differenze_cam.add(row); row->put(RMV_SEZIONE, dc.sezione()); row->put(RMV_IMPORTO, dc.valore()); TBill zio; _caus->bill(13, zio); zio.put(*row); TString80 str; str << TR("ft. ") << nfatt; row->put(RMV_DESCR, str); } TRectype& last = (TRectype&)customers[customers.last()]; TImporto imp(last.get_char(RMV_SEZIONE), last.get_real(RMV_IMPORTO)); imp += new_abb; // Incremento con abbuoni imp += new_diffcam; // Incremento con differenze cambi last.put(RMV_SEZIONE, imp.sezione()); last.put(RMV_IMPORTO, imp.valore()); } } void TContabilizzazione_effetti_app::aggiorna_saldi() { CHECK(_movimento, "Movimento non valido passato ad aggiorna_saldi()"); TLocalisamfile& mov = _movimento->lfile(); const TDate datareg(mov.get_date(MOV_DATAREG)); tiposal tsal = _caus->apertura() ? apertura : (_caus->chiusura() ? chiusura : normale); _saldo.reset(); // Inizializza saldi _saldo.set_movprovv(FALSE); _saldo.set_tipo_saldo(tsal); _saldo.set_anno_es(mov.get_int(MOV_ANNOES)); _saldo.set_num_ulmov(mov.get_long(MOV_NUMREG)); _saldo.set_data_ulmov(datareg); _saldo.set_movimentato(TRUE); const int cgitems = _movimento->cg_items(); for (int i = 0; i < cgitems; i++) { const TRectype& r = _movimento->cg(i); TImporto import(r.get_char("SEZIONE"), r.get_real("IMPORTO")); TBill conto; conto.get(r); _saldo.aggiorna(conto, import, TRUE); } _saldo.registra(); } error_type TContabilizzazione_effetti_app::write_all(bool change_status) { TRectype& head = _movimento->lfile().curr(); long numreg = head.get_long(MOV_NUMREG); if (_movimento->cg_items() > 0) // puo' succedere nell'ultima write { if (_movimento->cg_items() >= 2) // Non ha senso un movimento di una riga sola { TRectype& head = _movimento->lfile().curr(); head.put(MOV_TOTDOC,_total_mov); head.put(MOV_TOTDOCVAL,_total_mov_val); const long orig_numreg = numreg; while (_movimento->write() == _isreinsert) head.put(MOV_NUMREG,++numreg); if (_movimento->status() != NOERR) { error_box(FR("E' stato rilevato l'errore %d scrivendo il movimento %ld."),_movimento->status(),numreg); _error = generic_error; } if (good()) // nessun errore ? { aggiorna_saldi(); if (_sc_enabled) // Debbo scrivere anche le partite ? { if (numreg > orig_numreg) // Ha effettuato una rinumerazione ? { // Allora scorre le partite in _part_array e aggiorna il campo NREG delle righe di ognuna for (TPartita * p = _part_array->first(); p != NULL; p = _part_array->next()) // Scorre le righe della partita corrente for (int n = p->last(); n > 0; n = p->pred(n)) { TRiga_partite& riga = p->riga(n); if (riga.get_long(PART_NREG) == orig_numreg) // sostituisce il numero registrazione con quello nuovo riga.put(PART_NREG, numreg); } } if (!_part_array->write()) // L'errore viene gia' segnalato dalla partita _error = generic_error; } } } else { error_box(FR("Il movimento deve contenere almeno 2 righe contabili e non %d"), _movimento->cg_items()); _error = generic_error; } } if (good() && change_status) // deve anche cambiare lo stato alla distinta ? { TDistinta& distinta = *_distinta; const int items = distinta.items(); for (int n = 0; n < items; n++) { TRectype& eff = distinta[n]; eff.put(EFF_EFFCONT, TRUE); eff.put(EFF_NUMREG, numreg); } int err = distinta.rewrite(); if (err != NOERR) { error_box(FR("E' stato rilevato l'errore %d aggiornando lo stato della distinta %c %ld."),err,distinta.tipodist(),distinta.ndist()); _error = generic_error; } } return _error; } bool TContabilizzazione_effetti_app::has_diffcam(const TEffetto& eff) const { bool yes = FALSE; if (eff.in_valuta()) // Considera solo effetti in valuta { const TExchange cambio(eff); TLocalisamfile partite(LF_PARTITE); for (int n = 1; yes == FALSE && n <= eff.rows_r(); n++) { const TRectype& riga = eff.row_r(n); if (riga.get_char(REFF_ACCSAL) != 'S') // Ignora righe non saldanti continue; partite.put(PART_TIPOCF, eff.get(EFF_TIPOCF)); partite.put(PART_GRUPPO, 0); partite.put(PART_CONTO, 0); partite.put(PART_SOTTOCONTO, eff.get(EFF_CODCF)); partite.put(PART_ANNO, riga.get(REFF_ANNO)); partite.put(PART_NUMPART, riga.get(REFF_NUMPART)); partite.put(PART_NRIGA, riga.get(REFF_NRIGA)); int err = partite.read(); if (err == NOERR) { const TExchange cambiofatt(partite.curr()); yes = cambiofatt != cambio; } else NFCHECK("Effetto pagante fattura fantasma"); } } return yes; } static void build_eff_key(const TRectype& row, TString& str, int level) { int anno = row.get_int(REFF_ANNO); if (anno <= 0) anno = row.get_int(REFF_ANNODOC); TString16 part = row.get(REFF_NUMPART); if (part.blank() || part == "0") part = row.get(REFF_NFATT); int riga = row.get_int(REFF_NRIGA); if (riga <= 0) riga = 1; if (level > 0) { const int rata = row.get_int(REFF_NRATA); str.format("%04d|%s|%04d|%04d", anno, (const char*)part, riga, rata); if (level > 1) { // Devo fare in modo che le fatture precedano le note doi credito nell'array delle righe effetto int tipo = 2; if (row.get_real(REFF_IMPORTO) <= ZERO) tipo = 1; // Nota di credito str << '|' << tipo; } } else str.format("%04d|%s|%04d", anno, (const char*)part, riga); } static int sort_eff_func(const TObject** o1, const TObject** o2) { const TRectype& r1 = *((TRectype*)*o1); const TRectype& r2 = *((TRectype*)*o2); TString80 s1, s2; build_eff_key(r1, s1, 2); build_eff_key(r2, s2, 2); return s2.compare(s1); } int TContabilizzazione_effetti_app::sort_eff(TRecord_array& rows) { rows.sort(sort_eff_func); // Ordina per anno/partita/fattura/rata // Raggruppa le righe riferite alla stessa rata TString last_key, curr_key; for (int i = rows.last_row(); i > 0; i--) { TRectype& row = rows[i]; build_eff_key(row, curr_key, 1); if (curr_key == last_key) // Hanno la stessa rata per cui sommo e cancello l'ultima riga { real importo = rows[i+1].get(REFF_IMPORTO); importo += row.get_real(REFF_IMPORTO); row.put(REFF_IMPORTO, importo); rows.destroy_row(i+1, TRUE); } else last_key = curr_key; } return rows.rows(); } void TContabilizzazione_effetti_app::contabilize_bill(const char tipo, const long numero) { TDistinta& distinta = *_distinta; TLocalisamfile& mov = _movimento->lfile(); // tiene 2 array di record separati: uno per i clienti ed uno per le banche, // alla fine, prima di scrivere il movimento, li riunisce nel record array di // _movimento, per metterli in ordine, prima le righe clienti e poi le righe delle banche // L'array delle banche e' un assoc_array, con indice sul gruppo/conto/sottoconto // per effettuare il raggruppamento TArray customers; TAssoc_array banks; TArray differenze_cam; TImporto abbuoni_att, abbuoni_pas; bool reset_bank = FALSE; _total_mov = 0.0; _total_mov_val = 0.0; distinta.read(tipo,numero,_lock); // Sblocca da solo quella precedente if (_caus != NULL) delete _caus; const TString& cc = distinta.tipocf() == 'F' ? _cod_caus_pag : _cod_caus; _caus = new TCausale(cc, _data_op.year()); if (!_caus->ok()) { _error = generic_error; error_box(FR("Causale '%s' non valida o non presente in parametri effetti"), cc); return; } //Cerca il conto della contropartita della banca di presentazione. //Nel caso in cui sia presente sulla tabella BNP (selezione anche per //tipo distinta) il conto sara' unico per tutti; se invece non e' presente sul file oppure il conto //di contropartita e' vuoto, andra' reperito per ogni effetto, a seconda della causale //impostata e del tipo di pagamento (quest'ultimo solo nel caso di saldaconto abilitato); altrimenti si //terra' per buono sempre quello della seconda riga della casuale . //E' chiaro che nella maggioranza dei casi si avra' sempre un unico conto di contropartita, definito //nella tabella BNP. //Non meno importante: nel caso avessimo piu' conti di contropartita per le banche //si dovra' procedere ad un raggruppamento, sommando gli importi (mentre invece le righe //clienti non dovranno subire tale procedimento. //Infine: a causa del cazzutissimo limite di 99 righe contabili settato in invii/ricezioni //si dovranno generare piu' movimenti per un stessa distinta se le righe eccedono tale //valore (come avere le palle sopra un'incudine ed una mazza ferrata che sta per piombare a tutta forza...) search_bank_counter_bill(); if (!good()) return; // _error's already set real spese = distinta[0].get(EFF_SPESE); TBill conto_cassa, conto_spese; if (!spese.is_zero()) { _caus->bill(11, conto_spese); if (!conto_spese.ok()) { _error = cau_spe_error; return; } } bool dettaglio_rate = FALSE; if (distinta.tipocf() == 'F') dettaglio_rate = _dett_rate_pas; else dettaglio_rate = _dett_rate_att; const int items = distinta.items(); // Perche' sul file effetti il numero riga distinta e' un long ?? // compila la testata compile_head_mov(); // _cur_dist_row e' un int sebbene su file sia un long: TArray::items() ritorna un int!! for (_cur_dist_row = 0; _cur_dist_row 0 && force_break) // Se ci sono differenze cambio ... nrows = CGROWS_LIMIT; // ... allora forza cambio movimento if (nrows >= CGROWS_LIMIT) // se sono arrivato al limite massimo, scrivo questo movimento { // Unisce le righe banche e clienti nel record_array delle righe contabili if (good() && _can_write) { join_rows(customers, banks, abbuoni_att, abbuoni_pas, differenze_cam, spese); if (good()) write_all(FALSE); // non cambiare lo stato della distinta, cambialo solo alla fine } if (good()) { _movimento->destroy_rows(mov.get_long(MOV_NUMREG)); // azzera le righe.. _part_array->destroy(); // e l'array delle partite customers.destroy(); banks.destroy(); differenze_cam.destroy(); abbuoni_att = abbuoni_pas = TImporto('A', ZERO); _total_mov = ZERO; _total_mov_val = ZERO; spese = ZERO; // compila la testata del nuovo movimento compile_head_mov(); } } if (!good()) break; } } // Ciclo su effetti if (good() && _can_write) // scrive il movimento residuo ... { if (customers.items() > 0) join_rows(customers, banks, abbuoni_att, abbuoni_pas, differenze_cam, spese); if (good() && write_all() == no_error) // Se la scrittura e' andata ok... _total_bills++; // incrementa il numero di distinte contabilizzate } _movimento->destroy_rows(mov.get_long(MOV_NUMREG)); // azzera le righe.. _part_array->destroy(); // e l'array delle partite } void TContabilizzazione_effetti_app::contabilize() { _total_bills = 0; const long cur_items = _dist_sheet->items(); // Quante distinte in totale ? TProgind p(cur_items, TR("Contabilizzazione effetti"), FALSE, TRUE); for (long j = 0; j < cur_items; j++) { p.setstatus(j+1); if (_dist_sheet->checked(j)) { TToken_string& t = _dist_sheet->row(j); const char tipo = t.get_char(1); const long numero = t.get_long(2); contabilize_bill(tipo,numero); if (!good()) display_error(); } } if (_total_bills > 0) message_box(FR("Totale distinte contabilizzate: %ld"),_total_bills); } int ef0800 (int argc, char* argv[]) { TContabilizzazione_effetti_app a; a.run(argc,argv,TR("Contabilizzazione effetti")); return TRUE; }