#include #include "velib04.h" #include "../cg/cgsaldac.h" #include "../ef/ef0101.h" #include #include #include #include #include /////////////////////////////////////////////////////////// // TGenerazione_effetti /////////////////////////////////////////////////////////// TGenerazione_effetti::TGenerazione_effetti(const char* cod) : TElaborazione(cod) { _valid_array.set(2); // tratta _valid_array.set(3); // riba _valid_array.set(5); // paghero' _valid_array.set(7); // tratta accettata _valid_array.set(8); // rapporti interbancari diretti (rid) _valid_array.reset(9); // bonifici _docfile = new TLocalisamfile(LF_DOC); _rdocfile = new TLocalisamfile(LF_RIGHEDOC); _occas = new TLocalisamfile(LF_OCCAS); _clifo = new TLocalisamfile(LF_CLIFO); _cfven = new TLocalisamfile(LF_CFVEN); _tab = new TLocalisamfile(LF_TAB); _efffile = new TLocalisamfile(LF_EFFETTI); _refffile = new TLocalisamfile(LF_REFFETTI); _can_write = TRUE; _error = no_error; _total_bills = 0L; } TGenerazione_effetti::TGenerazione_effetti(const TRectype& rec) : TElaborazione(rec) { _valid_array.set(2); // tratta _valid_array.set(3); // riba _valid_array.set(5); // paghero' _valid_array.set(7); // tratta accettata _valid_array.set(8); // rapporti interbancari diretti (rid) _valid_array.reset(9); // bonifici _docfile = new TLocalisamfile(LF_DOC); _rdocfile = new TLocalisamfile(LF_RIGHEDOC); _occas = new TLocalisamfile(LF_OCCAS); _clifo = new TLocalisamfile(LF_CLIFO); _cfven = new TLocalisamfile(LF_CFVEN); _tab = new TLocalisamfile(LF_TAB); _efffile = new TLocalisamfile(LF_EFFETTI); _refffile = new TLocalisamfile(LF_REFFETTI); _can_write = TRUE; _error = no_error; _total_bills = 0L; } TGenerazione_effetti::~TGenerazione_effetti() { delete _docfile; delete _rdocfile; delete _occas; delete _clifo; delete _cfven; delete _efffile; delete _refffile; delete _tab; } void TGenerazione_effetti::display_error(TDocumento& doc) { TString msg; TString numerazione = doc.numerazione(); const long numero = doc.numero(); switch (_error) { case nr_doc_error: msg.format("Rilevato un numero di documento errato contabilizzando il documento %s/%ld." "Verificare il numero documento e il codice numerazione inseriti in tabella.",(const char*)numerazione,numero); break; case chg_stat_error: msg.format("Rilevato un errore cambiando lo stato al documento %s/%ld." "Verificare l'integrita' del file documenti.",(const char*)numerazione,numero); break; case datadoc_error: msg.format("Rilevato una data documento vuota relativamente al documento %s/%ld." "Verificare l'informazione inserita.",(const char*)numerazione,numero); break; case codpag_error: msg.format("Rilevato un codice pagamento non esistente relativamente al documento %s/%ld." "Verificare l'esistenza del codice pagamento inserito.",(const char*)numerazione,numero); break; case scadenze_error: msg.format("Calcolate 0 scadenze relativamente al documento %s/%ld." "Verificare la correttezza del codice pagamento inserito.",(const char*)numerazione,numero); break; case write_error: if (_efffile->status() != NOERR) msg.format("Si e' verificato l' errore %d in scrittura sul file effetti relativamente al documento %s/%ld" "Verificare la consistenza del file.",_efffile->status(),(const char*)numerazione,numero); else msg.format("Si e' verificato l' errore %d in scrittura sul file righe effetti relativamente al documento %s/%ld" "Verificare la consistenza del file.",_refffile->status(),(const char*)numerazione,numero); break; default: msg.format("E' stato rilevato un errore generico contabilizzando il documento %s/%ld.", (const char*)numerazione,numero); break; } 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. } error_type TGenerazione_effetti::change_doc_status(TDocumento& doc) // Cambia lo stato del documento { doc.stato(get("S4")[0]); if (doc.rewrite() != NOERR) _error = chg_stat_error; return _error; } error_type TGenerazione_effetti::change_group_status(TDocumento& doc, TAssoc_array& group_array) // Cambia lo stato dei documenti raggruppati { const int items = group_array.items(); if (items > 0) { _error = no_error; TToken_string * group_element; int i=0; // Ciclo sugli elementi dell'assoc_array for (group_element = (TToken_string *) group_array.first_item(); group_element != NULL && i < items; i++,group_element = (TToken_string*)group_array.succ_item()) { group_element->restart(); const int doc_items = group_element->items(); for (int j=0;jget(j),'$'); char provv = t.get_char(0); int anno = t.get_int(1); TString codnum(t.get(2)); long numdoc = t.get_long(3); if (doc.read(provv,anno,codnum,numdoc) == NOERR) // Legge il documento { doc.put(DOC_STATO,get("S4")[0]); doc.rewrite(); } } } } return _error; } error_type TGenerazione_effetti::write_groups() { const int items = _effetti_array.items(); int err = NOERR; int i; _error = no_error; for (i = 0; i ZERO) // Gli effetti negativi non vanno scritti { const char tipocf = effetto.get_char(EFF_TIPOCF); const long codcf = effetto.get_long(EFF_CODCF); TString key; key.format("%c|%ld", tipocf, codcf); const real impmin(cache().get(LF_CFVEN, key, CFV_IMPMINEFF)); if (importo >= impmin) err = effetto.write(*_efffile); // Pensa a tutto lui per rinumerare... else _effetti_array.destroy(i); } } _effetti_array.pack(); if (err != NOERR) { i--; for (int j = 0; jrestart(); const int doc_items = group_element->items(); for (j=0;jget(j),'$'); const char provv = t.get_char(0); const int anno = t.get_int(1); const TString4 codnum(t.get(2)); const long numdoc = t.get_long(3); if (doc.read(provv,anno,codnum,numdoc) != NOERR) continue; // Legge il documento (giusto saltare e proseguire se non lo trova?) msg2 = TR("Documento: "); msg2 << codnum << "/" << numdoc; xvtil_statbar_set(msg2); do_events(); // Ricalcola le scadenze codpag = doc.get(DOC_CODPAG); const TRectype& cpg = cache().get("%CPG", codpag); if (cpg.empty()) { _error = codpag_error; display_error(doc); continue; } const real tot = doc.totale_doc() - doc.ritenute(); doc.put(DOC_CODPAG, codpag); //placeholder const TCurrency_documento totale_fatt(tot, doc); const bool valuta = doc.in_valuta(); const real change = doc.cambio(); const TDate datafatt = doc.get_date(DOC_DATADOC); const bool is_nota_credito = doc.is_nota_credito(); long numdocrif = doc.get_long(DOC_NUMDOCRIF); int annodocrif = doc.get_date(DOC_DATADOCRIF).year(); if (numdocrif > 0L && doc.get_char(DOC_TIPOCF) == 'C' && !doc.tipo().nota_credito()) { annodocrif = 0; numdocrif = 0L; } // Qui il controllo sul residuo da pagare per il documento corrente non va effettuato, // proprio perchč si sta effettuando un raggruppamento di effetti; eventuali documenti // con importo negativi (assimilati a note di credito) vanno presi in considerazione // per la composizione dell'importo finale dell'effetto. Un effetto puo' essere composto // anche da righe di valore negativo ma esso non verrą scritto solo nel caso in cui l'importo // totale (la somma delle singole righe) sia negativo a sua volta { calc_pagamento(doc); TPagamento& pag = doc.pagamento(); int numrate = pag.n_rate( ); if (numrate <= 0) continue; // Scorre le scadenze for (n = 1; n <= numrate && good(); n++) { if (valid_type(pag.tipo_rata(n-1))) { // Se non esiste effetto n-esimo (corrisponde al numero di rata corrente+offset) // lo genera con la relativa riga. Se esiste vi somma gli importi ed accoda la riga const int effitems = _effetti_array.items(); int index = offset; const TDate datascad = pag.data_rata(n-1); for (; index < effitems; index++) { TEffetto& effetto=(TEffetto&)_effetti_array[index]; if (datascad == effetto.get_date(EFF_DATASCAD)) break; } // const int index = n+j-1; // Nuovo effetto: crea effetto con i dati di questo documento (e' il primo che incontro nella scansione) if (index >= effitems) { TEffetto* effetto = new TEffetto; // Setta i dati della testata; effetto->put(EFF_DATASCAD, datascad); effetto->put(EFF_TIPOPAG,pag.tipo_rata(n-1)); effetto->put(EFF_ULTCLASS,pag.ulc_rata(n-1)); effetto->put(EFF_TIPOCF, doc.get_char(DOC_TIPOCF)); effetto->put(EFF_CODCF, doc.get_long(DOC_CODCF)); effetto->put(EFF_CODVAL, doc.get(DOC_CODVAL)); effetto->put(EFF_CAMBIO, change); effetto->put(EFF_DATACAMBIO,doc.get_date(DOC_DATACAMBIO)); effetto->put(EFF_CONTROEURO,doc.get_date(DOC_CONTROEURO)); effetto->put(EFF_CODABI,doc.get(DOC_CODABIA)); effetto->put(EFF_CODCAB,doc.get(DOC_CODCABA)); effetto->put(EFF_IBAN,doc.get(DOC_IBAN)); effetto->put(EFF_EFFCOMP,TRUE); _effetti_array.add(effetto); } // aggiorna totale effetto (testata) TEffetto& effetto=(TEffetto&)_effetti_array[index]; const int rows = effetto.rows_r(); importo = effetto.get_real(EFF_IMPORTO); imprata = pag.importo_rata(n-1,FALSE); imprataval = valuta ? pag.importo_rata(n-1,TRUE) : ZERO; if (is_nota_credito) { // Cerca fattura da pagare con la nota di credito int r; for (r = 1; r <= rows; r++) { const int annoeff = effetto.row_r(r).get_int(REFF_ANNODOC); const long codeff = effetto.row_r(r).get_long(REFF_NFATT); if (annoeff == annodocrif && codeff == numdocrif) break; } if (r <= rows) // Se l'ha trovata ... { const real importo_rata_lit = effetto.row_r(r).get_real(REFF_IMPORTO); const real importo_rata_val = valuta ? effetto.row_r(r).get_real(REFF_IMPORTOVAL) : ZERO; real delta_lit = imprata - importo_rata_lit; real delta_val = valuta ? imprataval - importo_rata_val : ZERO; // Controlla se l'importo della nota di credito supera quello della fattura if (delta_lit > ZERO || delta_val > ZERO) { // Detrae l'eccedenza dalla rata corrente e la sposta nella rata successiva imprata -= delta_lit; imprataval -= delta_val; if (n == numrate) { // Crea eventuale ultima rata mancante pag.add_rata(); numrate++; } else { // Incrementa importo rata delta_lit += pag.importo_rata(n, FALSE); delta_val += pag.importo_rata(n, TRUE); } const TDate oggi(TODAY); const int tiporata = pag.tipo_rata(n-1); pag.set_rata(n, delta_val, delta_lit, oggi, tiporata, "", FALSE); } } else break; // Esce dal ciclo delle rate imprata = -imprata; imprataval = -imprataval; } // Aggiorna importi in lire/valuta dell'effetto importo += imprata; effetto.put(EFF_IMPORTO,importo); if (valuta) { importoval = effetto.get_real(EFF_IMPORTOVAL); importoval += imprataval; effetto.put(EFF_IMPORTOVAL,importoval); } // Crea la nuova riga di questo effetto TRectype& riga = effetto.row_r(rows+1,TRUE); // reffetto.put(REFF_NPROGTR,nprog); riga.put(REFF_NRIGATR,rows+1); riga.put(REFF_NRATA,n); riga.put(REFF_DATAFATT, datafatt); riga.put(REFF_PROVV,provv); riga.put(REFF_ANNODOC,anno); riga.put(REFF_CODNUM,codnum); riga.put(REFF_NFATT,numdoc); riga.put(REFF_IMPFATT,totale_fatt.get_num()); riga.put(REFF_IMPORTO,imprata); riga.put(REFF_ANNO, annodocrif); riga.put(REFF_NUMPART, numdocrif); if (valuta) { riga.put(REFF_IMPFATTVAL,totale_fatt.get_num()); TCurrency_documento totfatlit(totale_fatt); totfatlit.change_to_firm_val(); riga.put(REFF_IMPFATT,totfatlit.get_num()); riga.put(REFF_IMPORTOVAL,imprataval); } if (n == numrate) effetto.put(EFF_ULTRATA, "X"); } } // Ciclo sulle scadenze } } // Ciclo sui documenti di questo gruppo offset=_effetti_array.items(); } // Ciclo sui gruppi // Cambia lo stato a tutti i documenti raggruppati long tot = 0L; if (_can_write) { xvtil_statbar_set("Scrittura effetti raggruppati in corso..."); do_events(); if (write_groups() == no_error) { tot = _effetti_array.items(); change_group_status(doc, group_array); } } _effetti_array.destroy(); group_array.destroy(); return tot; } bool TGenerazione_effetti::valid_type(int pag) const { return _valid_array[pag]; } void TGenerazione_effetti::calc_pagamento(TDocumento& doc) { TPagamento& pag = doc.pagamento(); // const real change = doc.cambio(); const real tot = doc.totale_doc() - doc.ritenute(); const TCurrency_documento tot_doc(tot, doc); const TCurrency_documento totspese(doc.spese(), doc); const TCurrency_documento totimposte(doc.imposta(TRUE), doc); const TCurrency_documento totimponibili(tot_doc - totimposte - totspese); TCurrency_documento anticipo(doc.get_real(DOC_IMPPAGATO), doc); const bool valuta = doc.in_valuta(); //Riaggiusta le rate a seconda del valore gia' pagato TGeneric_distrib d(anticipo.get_num(), doc.decimals()); d.add(totimponibili.get_num()); d.add(totimposte.get_num()); d.add(totspese.get_num()); const TCurrency_documento pagtotimponibili(totimponibili.get_num() - d.get(), doc); const TCurrency_documento pagtotimposte(totimposte.get_num() - d.get(), doc); const TCurrency_documento pagtotspese(totspese.get_num() - d.get(), doc); if (valuta) { TCurrency_documento val2(pagtotimposte); val2.change_to_firm_val(); TCurrency_documento val3(pagtotspese); val3.change_to_firm_val(); TCurrency_documento val1(tot_doc); val1.change_to_firm_val(); val1 -= val2 + val3; pag.set_total_valuta(pagtotimponibili, pagtotimposte, pagtotspese, val1, val2, val3); } else pag.set_total(pagtotimponibili, pagtotimposte, pagtotspese); pag.set_rate_auto(); const int numrate = pag.n_rate(); // Scorre all'indietro per rimuovere le rate a 0, evitando fastidiose // complicazioni dovute al pack delle rate effettuato dalla remove_rate() for (int i=numrate-1; i>=0; i--) { if (pag.importo_rata(i,valuta) == ZERO) pag.remove_rata(i); } } void TGenerazione_effetti::generate_bill(TDocumento& doc) // bill in inglese significa anche effetto eheheh ;-) { // That's my JOB! // Ogni rata della fattura (si parla di effetti attivi per ora) genera 1 effetto. // con almeno una riga. // Ad es. Se ho una fattura suddivisa in 3 rate essa generera' 3 effetti con una riga. // Nel caso si decida di raggruppare gli effetti (vedi criteri di raggruppamento) // avro' un effetto con tante righe quante scadenze di fattura sono raggruppabili // Le fatture possono generare effetti solo per i seguenti tipi di pagamento: // 2 - Tratta // 3 - Ri.Ba. // 5 - Paghero' // 7 - Tratta accettata // 8 - Rapporti interbancari diretti // Caso mai tale insieme risultasse incompleto od errato basta solo modificare l'enum posto all'inizio del programma if (!doc.is_nota_credito()) // I documenti immessi come note di credito non generano effetti...(che senso hanno gli effetti con importi negativi?) { const TString4 codpag(doc.get(DOC_CODPAG)); const TRectype& cpg = cache().get("%CPG", codpag); if (cpg.empty()) { _error = codpag_error; return; } // Totdoc inaffidabile: ne forzo il ricalcolo TVariable_field* tot_fld = doc.variable_field(doc.tipo().totale_doc()); if (tot_fld != NULL) tot_fld->set_dirty(); TString16 data(doc.get(DOC_DATAINSC)); if (data.empty()) data = doc.get(DOC_DATADOC); const real tot = doc.totale_doc() - doc.ritenute(); const TCurrency_documento totale_fatt(tot, doc); // Importo in valuta const TCurrency_documento imppagato(doc.get_real(DOC_IMPPAGATO), doc); // Anticipo pagamento if (totale_fatt > imppagato && !doc.get_bool(DOC_ACCSALDO)) // procede se non e' a saldo { const bool is_anticipo = imppagato.get_num() != ZERO; const bool valuta = doc.in_valuta(); const real change = doc.cambio(); // calcolo delle scadenze calc_pagamento(doc); TPagamento & pag = doc.pagamento(); // CHECK(pag,"Failed to create a TPagamento"); const int numrate = pag.n_rate( ); if (numrate > 0) { _efffile->last(); // Variabili per la scrittura dell'effetto long nprog = _efffile->get_long(EFF_NPROGTR)+1; const char tipocf = doc.get_char(DOC_TIPOCF); const long codcf = doc.get_long(DOC_CODCF); const TString4 codval(doc.get(DOC_CODVAL)); const TDate data_cambio = doc.get_date(DOC_DATACAMBIO); const bool contro_euro = doc.get_bool(DOC_CONTROEURO); const long codabi = doc.get_long(DOC_CODABIA); const long codcab = doc.get_long(DOC_CODCABA); const TString80 iban = doc.get(DOC_IBAN); const TString4 provv(doc.get(DOC_PROVV)); const int anno = doc.get_int(DOC_ANNO); const TString4 codnum(doc.get(DOC_CODNUM)); const long nfatt = doc.get_long(DOC_NDOC); const TDate datafatt = doc.get_date(DOC_DATADOC); TRectype& effetto = _efffile->curr(); TRectype& reffetto = _refffile->curr(); real importo; for (int i = 0; i < numrate && good(); i++) { const int nrata = is_anticipo ? i + 2: i + 1; if (valid_type(pag.tipo_rata(i))) { effetto.zero(); reffetto.zero(); effetto.put(EFF_NPROGTR,nprog); effetto.put(EFF_DATASCAD, pag.data_rata(i)); effetto.put(EFF_TIPOPAG,pag.tipo_rata(i)); effetto.put(EFF_ULTCLASS,pag.ulc_rata(i)); effetto.put(EFF_TIPOCF, tipocf); effetto.put(EFF_CODCF, codcf); effetto.put(EFF_CODVAL, codval); if (valuta) { effetto.put(EFF_CAMBIO, change); effetto.put(EFF_DATACAMBIO,data_cambio); effetto.put(EFF_CONTROEURO, contro_euro); } effetto.put(EFF_CODABI,codabi); effetto.put(EFF_CODCAB,codcab); effetto.put(EFF_IBAN,iban); effetto.put(EFF_EFFCOMP,TRUE); if (i == numrate - 1) effetto.put(EFF_ULTRATA,TRUE); // Put sulla riga dell'effetto reffetto.put(REFF_NPROGTR,nprog); reffetto.put(REFF_NRIGATR,1); reffetto.put(REFF_DATAFATT, datafatt); reffetto.put(REFF_NRATA,nrata); reffetto.put(REFF_PROVV,provv); reffetto.put(REFF_ANNODOC,anno); reffetto.put(REFF_CODNUM,codnum); reffetto.put(REFF_NFATT,nfatt); if (doc.get_char(DOC_TIPOCF) == 'F' || doc.tipo().nota_credito()) { reffetto.put(REFF_ANNO, doc.get_date(DOC_DATADOCRIF).year()); reffetto.put(REFF_NUMPART, doc.get(DOC_NUMDOCRIF)); } importo = pag.importo_rata(i,FALSE); effetto.put(EFF_IMPORTO,importo); reffetto.put(REFF_IMPFATT,totale_fatt.get_num()); reffetto.put(REFF_IMPORTO,importo); TString8 key; key.format("%c|%ld", tipocf, codcf); const real impmin(cache().get(LF_CFVEN, key, CFV_IMPMINEFF)); if (importo >= impmin) { if (valuta) { importo = pag.importo_rata(i, true); // Importo in valuta TCurrency_documento totfatlit(totale_fatt); totfatlit.change_to_firm_val(); effetto.put(EFF_IMPORTOVAL,importo); reffetto.put(REFF_IMPFATTVAL,totale_fatt.get_num()); reffetto.put(REFF_IMPFATT,totfatlit.get_num()); reffetto.put(REFF_IMPORTOVAL,importo); } if (_efffile->write() == NOERR && _refffile->write() == NOERR) { _total_bills++; nprog++; } else _error = write_error; } } } } } } if (good() && _can_write) change_doc_status(doc); } bool TGenerazione_effetti::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { TString msg; _error = no_error; _total_bills = 0L; pre_process_input(doc_in); const int items = doc_in.items(); // Numero dei documenti in questa elaborazione for (int i = 0; i < items ; i++) // Scorriamo tutti i documenti nella lista { TDocumento& doc = doc_in[i]; msg.format(FR("Generazione effetti documento %s/%ld."), (const char*) doc.numerazione(), doc.numero()); xvtil_statbar_set(msg); do_events(); generate_bill(doc); // Genera gli effetti corrispondenti if (!good()) display_error(doc); } post_process_input(doc_in); post_process(doc_out, doc_in); return _can_write; }