#include #include #include #include #include #include #include "lvlib.h" #include "lv2500a.h" #include "../pr/agenti.h" #include "../pr/percprov.h" #include "clifo.h" #include "../cg/cfban.h" #include "comuni.h" #include "cfven.h" #include "lvcondv.h" #include "lvrcondv.h" #include "doc.h" #include "rdoc.h" #include "../db/dblib.h" #include "../mg/mglib.h" #include "../ve/ve6200.h" #include "../ve/ve6200a.h" #define DOC_DEST "DEST" //c campo virtuale per la destinazone class TFatturazione_lavanderie; //////////////////////////////////////// //// classe TFatturazione_msk //// //////////////////////////////////////// class TFatturazione_msk: public TAutomask { protected: virtual bool on_field_event(TOperable_field& o,TField_event e,long jolly){return true;} public: TFatturazione_msk(); }; //////////////////////////////////////// //// TFatturazione_lavanderie app //// //////////////////////////////////////// //Classe TFatturazione_lavanderie_app class TFatturazione_lav_app: public TSkeleton_application { TFatturazione_msk* _msk; TLog_report * _log; bool _solototali; protected: virtual void main_loop(); void genera_bolle_nolo(TAssoc_array& cliela, TFatturazione_lavanderie& elab, int& numdocgen, real& totimp, real& imposta, real& totdoc, real& spese); bool controlli_preliminari(); bool copy_file(const TFilename& src, const TFilename& dst) const; bool copy_tree(const char* src_study, const char* dst_study) const; }; TFatturazione_lav_app & app() { return (TFatturazione_lav_app &) main_app();} //////////////////////////////////////// //// TCalc_02_data //// //////////////////////////////////////// //Classe TCalc_02_data class TCalc_02_data : public TObject { TString _key; TGeneric_distrib _distr; TGeneric_distrib _distr_rit; TAssoc_array _bol_rows; virtual TObject* dup() const; void copy(const TCalc_02_data & d); public: TCalc_02_data & operator = (const TCalc_02_data & d) { copy(d); return *this; } const TString & key() const { return _key; } TGeneric_distrib & distr() { return _distr; } TGeneric_distrib & distr_rit() { return _distr_rit; } TAssoc_array & bol_rows() { return _bol_rows; } TCalc_02_data(const char * key) : _key(key) {} TCalc_02_data(const TCalc_02_data & d) {copy(d);} }; void TCalc_02_data::copy(const TCalc_02_data & d) { _key = d._key; _distr = d._distr; _bol_rows = d._bol_rows; } TObject* TCalc_02_data::dup() const { TCalc_02_data* o = new TCalc_02_data(*this); return o; } //////////////////////////////////////// //// TFatturazione_lavanderie //// //////////////////////////////////////// //Classe TFatturazione_lavanderie class TFatturazione_lavanderie:public TFatturazione_bolle { TDate _data_elab; TToken_string _campi_raggruppamento; TAssoc_array _output_rows_02; TAssoc_array _doc_grouped; bool _prova; long _last_cli_damn; int _art_damn; int _cli_damn; protected: virtual void add_rows(TRiga_documento & rout, TRiga_documento & rin); virtual void create_row(TDocumento& doc_out, const TRiga_documento & rin); virtual void pre_process_input(TLista_documenti& doc_in); virtual void post_process_input(TLista_documenti& doc_in) {} virtual void post_process(TLista_documenti& doc_out, TLista_documenti& doc_in); virtual bool da_raggruppare(const TRiga_documento & rin); virtual bool doc_raggruppabili(const TDocumento& doc_in, const TDocumento& doc_out, TToken_string& campi) const ; virtual bool doc_raggruppabile(const TDocumento & doc) const { return true; } virtual void campi_raggruppamento_righe(TToken_string& campi_riga) const; virtual bool gestione_riferimenti() const { return true; } virtual bool riferimenti_in_testa() const { return true; } virtual TRiga_documento& find_or_create_row(TDocumento& doc_out, const TRiga_documento & rin,const char lavtype); void aggiorna_fattura(TDocumento & doc, int codcont); bool fatt_02() const { return !_prova &&lv_is_02_active(); } void add_doc_to_list(const TString & key, const TDocumento & doc); real get_percprovv(const TRiga_documento & row, char tipoprovv, const TString & codpr, bool first, const TRectype & age) const; public: bool is_document_compatible(const TRectype & doc) const; int write_fatt_ragg(const bool solotot); void set_perc_provv(TRiga_documento & row, bool prima = true); virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo = false); long & last_cli_damn() {return _last_cli_damn;} int & cli_damn() {return _cli_damn;} int & art_damn() {return _art_damn;} TFatturazione_lavanderie(const char* cod, bool prova = false); ~TFatturazione_lavanderie() {} }; TFatturazione_lavanderie::TFatturazione_lavanderie(const char* cod, bool prova) : TFatturazione_bolle(cod), _prova(prova) { } bool TFatturazione_lavanderie::is_document_compatible(const TRectype & doc) const { bool ok = false; const TString4 codnum(doc.get(DOC_CODNUM)); const TString4 tipodoc(doc.get(DOC_TIPODOC)); const char stato(doc.get_char(DOC_STATO)); const TString& codnumel = codice_numerazione_iniziale(); if (codnumel.blank() || codnum == codnumel) { for (int i = 0; !ok && i < TElaborazione::_max_tipi_doc_elab; i++) { const TString & tipel = tipo_iniziale(i); if (tipel.blank()) break; if (tipodoc == tipel) ok = true; } } return ok; } //DOC_RAGGRUPPABILI: metodo che restituisce true se i documenti sono raggruppabili sulla base dei campi //contenuti nella stringa campi bool TFatturazione_lavanderie::doc_raggruppabili(const TDocumento& doc_in, const TDocumento& doc_out, TToken_string& campi) const { if (doc_in.ha_riga_esenzione() != doc_out.ha_riga_esenzione()) return false; bool ok = true; TString campo; //scorro tutti i campi contenuti nella TToken_string //se sto controllando i campi CODABI e CODCAB, allora il controllo //deve essere numerico e non tra stringhe for (const char* c = campi.get(0); c && ok; c = campi.get()) { if (strncmp(c, "CODABI", 6) == 0 || strncmp(c, "CODCAB", 6) == 0) { long cod = doc_in.get_long(c); ok &= (cod == doc_out.get_long(c)); } else { campo = doc_in.get(c); ok &= campo == doc_out.get(c); } } return ok; } //DA_RAGGRUPPARE: per adesso segnaposto: resituisce sempre false bool TFatturazione_lavanderie::da_raggruppare(const TRiga_documento & rin) { /* const long clifo = rin.doc().get_long(DOC_CODCF); const int indsped = rin.doc().get_int(DOC_CODINDSP); TLaundry_contract contr(clifo, indsped, _data_elab); const TString80 codart = rin.get(RDOC_CODART); const TRectype & rcont = contr.row(codart); const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF); // return tipoforf > 1; // Test originale if (tipoforf > 1) return true; // Da qui in poi e' sottinteso tipoforf == 1 if (ini_get_int(CONFIG_DITTA, "lv", "TipoPr") == 1) return false; // Test GUY const TString8 causale = rin.get(RDOC_CODAGG1); const TCausale_lavand cau = cache().get("&CAU", causale); if (cau.get_bool("B1")) { const TCausale_magazzino& con = cached_causale_magazzino(cau.get("S2")); if (con.sgn(s_dottm)) // Causale di incremento sotazione temporanea return true; } if (cau.get_bool("B4")) // Causale di rotto return true; */ return false; } void TFatturazione_lavanderie::pre_process_input(TLista_documenti& doc_in) { for (int id = 0; id < doc_in.items(); id++) { TDocumento& doc = doc_in[id]; const int rows = doc.physical_rows(); for (int i = 1; i <= rows; i++) { TRiga_documento & row = doc[i]; TString str_real = row.get(RDOC_QTAREALE); if (str_real.full()) { real qta_real(decode(str_real)); row.put(RDOC_QTA, qta_real); row.zero(RDOC_QTAREALE); } str_real = row.get(RDOC_QTARITREALE); if (str_real.full()) { real qta_real(decode(str_real)); row.put(RDOC_QTAGG1, qta_real); row.zero(RDOC_QTARITREALE); } } } } //aggiunge una riga fittizia al documento con qta a zero per gli articoli per cui è previsto il forfait //e che non sono stati consegnati void TFatturazione_lavanderie::aggiorna_fattura(TDocumento& doc, int codcont) { const int nrows = doc.physical_rows(); const long codcf = doc.get_long(DOC_CODCF); TString str; str << "USE LVRCONDV\n" << "FROM CODCF=" << codcf << " CODCONT=" << codcont << "\n" << "TO CODCF=" << codcf << " CODCONT=" << codcont; TISAM_recordset rcont(str); for(bool ok = rcont.move_first(); ok; ok = rcont.move_next()) { TRectype& riga = rcont.cursor()->curr(); int forfait = riga.get_int(LVRCONDV_TIPOFORF); const TString & codart = riga.get(LVRCONDV_CODART); bool to_add = forfait != 0; for (int i = 1; to_add && i <= nrows ; i++) { TRiga_documento& rout = doc[i]; const TString80 codart_contr = rout.get(RDOC_CODART); if (codart == codart_contr) to_add = false; } if (to_add) { TRiga_documento& rdoc = doc.new_row("21"); rdoc.put(RDOC_CODART, codart); rdoc.put(RDOC_CODARTMAG, codart); rdoc.put(RDOC_DESCR, cached_article(codart).get(ANAMAG_DESCR)); rdoc.put(RDOC_CHECKED, true); rdoc.put(RDOC_QTA, 0); rdoc.put(RDOC_QTAGG1, 0); rdoc.put(RDOC_UMQTA, cached_article(codart).first_um()); TToken_string key; key.add('C'); key.add(codcf); TString8 codiva = cache().get(LF_CFVEN, key, CFV_ASSFIS); if (codiva.blank()) codiva = cache().get(LF_ANAMAG, riga.get(LVRCONDV_CODART), ANAMAG_CODIVA); rdoc.put(RDOC_CODIVA, codiva); rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV")); set_perc_provv(rdoc); set_perc_provv(rdoc, false); } } } void TFatturazione_lavanderie::add_doc_to_list(const TString& key, const TDocumento& doc) { TDocumento * doc_cli = (TDocumento *) _doc_grouped.objptr(key); if (doc_cli == NULL) _doc_grouped.add(key, doc); else { const int nrows = doc.physical_rows(); for (int r = 1; r <=nrows; r++) { const TRiga_documento & row = doc[r]; TRiga_documento & new_row = doc_cli->new_row(row.get(RDOC_TIPORIGA)); doc_cli->copy_data(new_row, row); } } } real TFatturazione_lavanderie::get_percprovv(const TRiga_documento & row, char tipoprovv, const TString & codpr, bool first, const TRectype & age) const { real val = ZERO; const TDocumento & doc = row.doc(); const TRectype & anamag = cache().get(LF_ANAMAG, row.get(RDOC_CODARTMAG)); switch (tipoprovv) { case 'A': val = age.get_real(AGE_PERCPROVV); break; case 'M': val = anamag.get_real(ANAMAG_PERCPROVV); break; case 'C': val = doc.clifor().vendite().get_real(first ? CFV_PERCPROVV : CFV_PERCPROVV1); break; case 'V': { const TString16 catven = doc.get(DOC_CATVEN); if (catven.not_empty()) val = real(cache().get("CVE", catven, "R0")); } break; case 'O': // val = _rcondv.get_real("PERCPROVV"); break; case '1': case '2': case '3': case '4': { const TString16 ord = cache().get("APR", codpr, "S3"); int len = ord.len(); TString key; TString80 campo; for (int i = 0; i < len; i++) { switch (ord[i]) { case 'C': campo = doc.clifor().get(CLI_CODCF); campo.lpad(doc.clifor().length(CLI_CODCF)); break; case 'V': campo = doc.get(DOC_CATVEN); campo.rpad(doc.length(DOC_CATVEN)); break; case 'A': campo = doc.get(DOC_CODAG); campo.rpad(doc.length(DOC_CODAG)); break; case 'P': campo = doc.get(DOC_CODPAG); campo.rpad(doc.length(DOC_CODPAG)); break; case 'S': campo = doc.clifor().vendite().get(CFV_CODSCC); campo.rpad(doc.clifor().length(CFV_CODSCC)); break; case 'Z': campo = doc.get(DOC_ZONA); campo.rpad(doc.length(DOC_ZONA)); break; case 'M': campo = row.get( RDOC_CODARTMAG ); campo.rpad(row.length(RDOC_CODARTMAG)); break; case 'E': campo = anamag.get(ANAMAG_GRMERC); campo.rpad(anamag.length(ANAMAG_GRMERC)); campo.cut(3); break; case 'R': campo = anamag.get(ANAMAG_GRMERC); campo.rpad(anamag.length(ANAMAG_GRMERC)); break; case 'F': campo = anamag.get(ANAMAG_RAGGFIS); campo.rpad(anamag.length(ANAMAG_RAGGFIS)); break; default: campo.cut(0); break; } key << campo; } TLocalisamfile perc(LF_PERCPROV); perc.put(PER_CODPR, codpr); perc.put(PER_KEYORD, key); if (perc.read() == NOERR) val= perc.get_real(PER_PERCPROVV); } break; default: break; } return val; } void TFatturazione_lavanderie::set_perc_provv(TRiga_documento & row, bool prima) { const TString & codage = row.doc().get(prima ? DOC_CODAG : DOC_CODAGVIS); if (codage.full()) { const TRectype & age = cache().get(LF_AGENTI, codage); if (!age.empty()) { TString16 seqric(age.get(AGE_SEQRIC)); real percprovv; if (seqric[0] == '-') seqric = ini_get_string(CONFIG_DITTA, "ve", "AGETIPOPERC"); int len = seqric.len(); int i; for (i = 0; percprovv.is_zero() && seqric[i] != '\0' && seqric[i] != '-'; i++) { TString16 codric; if (isdigit(seqric[i])) codric = age.get(format("CODRICPR%d", i+1)); percprovv = get_percprovv(row, seqric[i], codric, prima, age); } real percalt; seqric = age.get(AGE_SEQALT); for (i = 0; percalt.is_zero() && seqric[i] != '\0' && seqric[i] != '-'; i++) { TString16 codric; if (isdigit(seqric[i])) codric = age.get(format("CODALTPR%d", i+1)); percalt = get_percprovv(row, seqric[i], codric, prima, age); } percprovv += percalt; row.put(prima ? RDOC_PERCPROV : RDOC_PERCPROV1, percprovv); } } } int TFatturazione_lavanderie::write_fatt_ragg(const bool solotot) { int items = _doc_grouped.items(); TString_array kl; _doc_grouped.get_keys(kl); kl.sort(); FOR_EACH_ARRAY_ROW(kl, r, key) { TDocumento* d = (TDocumento*)_doc_grouped.objptr(*key); if (d != NULL && !solotot) d->write(); } _doc_grouped.destroy(); return items; } //POST_PROCESS: metodo che elabora i documenti di output dopo che si sono svolte //le operazioni di base sugli stessi, in modo da raggruppare le righe raggruppabili //e/o eliminare quelle inutili e/o aggiungere quelle per il ciclaggio su 2 linee void TFatturazione_lavanderie::post_process(TLista_documenti& doc_out, TLista_documenti& doc_in) { bool use_indsp = ini_get_bool(CONFIG_DITTA, "mg", "MOV_INDSPED"); //scorro tutti i documenti di output generati precedentemente for (int id = 0; id < doc_out.items(); id++) { //instanzio il documento e recupero le variabili di interesse per recuperare //il contratto del cliente in questione TDocumento& doc = doc_out[id]; const long clifo = doc.get_long(DOC_CODCF); const int indsped = doc.get_int(DOC_CODINDSP); TLaundry_contract contr(clifo,indsped,_data_elab); //flag per il calcolo sul valore convenzionale e sul fisso per dotazione iniziale bool valconvcli = false; bool fixdotin = false; bool elcons = contr.get_bool(LVCONDV_ELCONS); bool rifbol = contr.get_bool(LVCONDV_RIFBOL); bool riftest = ini_get_bool(CONFIG_DITTA, "lv", "RifTest"); bool liqdiff = doc.clifor().get_int(CLI_ALLEG) == 7 && doc.clifor().vendite().get_bool(CFV_FATTSOSP); real consvconv; real impvconv; TAssoc_array nolo_computed; if (liqdiff) doc.put(DOC_LIQDIFF, "X"); else doc.zero(DOC_LIQDIFF); if (doc.physical_rows() > 0 && doc[1].is_descrizione()) { if (elcons) { TRiga_documento& rout = doc[1]; rout.put(RDOC_DESCR, "COME DA ELENCO CONSEGNE"); rout.put(RDOC_DESCLUNGA, false); rout.put(RDOC_DESCEST, ""); } else if (!rifbol) doc.destroy_row(1, true); } //se devo mettere i riferimenti della bolla in testata, prendo la descrizione della prima riga //e la metto sulla testata del documento, poi cancello la prima riga del documento if (rifbol && riftest) { TRiga_documento& rout = doc[1]; TString descr = rout.get(RDOC_DESCR); descr << ' ' << rout.get(RDOC_DESCEST); descr.ltrim(21); //sostituisco la stringa " - n. " e la sostituisco con la stringa " - " su tutta la stringa descrizione int pos = descr.find(" - n. "); while (pos > 0) { descr.overwrite(" - ", pos, 7); pos = descr.find(" - n. ", pos + 1); } descr.strip_double_spaces(); const TString original_notes = doc.get(DOC_NOTE); if (original_notes.full()) descr << '\n' << original_notes; doc.put(DOC_NOTE, descr); doc.destroy_row(1, true); } aggiorna_fattura(doc, contr.get_int(LVCONDV_CODCONT)); if (doc.physical_rows() > 0) doc.sort_rows(RDOC_CODART "|LVTYPE"); const bool ragart = contr.get_bool(LVCONDV_RAGART); // leggo il flag di testata raggruppa su unico articolo const int tipocan = contr.get_int(LVCONDV_TIPOCAN); // leggo il tipo canone const real redditivita = contr.get_real(LVCONDV_REDDI); if (ragart) { real totmerc; const int rows = doc.physical_rows(); for (int i=1; i <= rows; i++) //calcolo totale merce { const TRiga_documento& riga = doc[i]; if (riga.is_merce()) totmerc += riga.importo(true,false); } const int rigamerce = doc[1].is_descrizione() ? 2 : 1; for (int i=rigamerce; i <= rows; i++) doc.destroy_row(i); TRiga_documento& riga = doc.new_row("01"); const TString80 codartcfg = ini_get_string(CONFIG_DITTA, "lv", "Codartcafix"); const TString80 descart = cache().get(LF_ANAMAG, codartcfg, ANAMAG_DESCR); const TString descragg = cache().get(LF_ANAMAG, codartcfg, ANAMAG_DESCRAGG); // istanzio una token string e poi una cache per estrarre l'unità di misura dell articolo in configurazione da UMART TToken_string key; key.add(codartcfg); key.add(1); const TRectype& umart = cache().get(LF_UMART,key); const TString4 umcodart = umart.get(UMART_UM); /* estraggo il codice IVA istanziando in primis una cache su CFVEN per analizzare il codice esenzione iva del cliente in questione. Se è >0 imposto il codiva a tale valore, altrimenti se è uguale a 0 istanzio un altra cache su ANAMAG e imposto il codiva uguale al codice iva dell articolo in questione */ key = doc.get(DOC_TIPOCF); key.add(clifo); const TRectype& cfven = cache().get(LF_CFVEN,key); TString8 codiva = cfven.get(CFV_ASSFIS); if (codiva.blank()) { const TRectype& anamag = cache().get(LF_ANAMAG,codartcfg); codiva = anamag.get(ANAMAG_CODIVA); } riga.put(RDOC_QTA,UNO); riga.put(RDOC_UMQTA,umcodart); riga.put(RDOC_PREZZO,totmerc); riga.put(RDOC_CODART,codartcfg); riga.put(RDOC_DESCR,descart); if (descragg.full()) { riga.put(RDOC_DESCLUNGA, "X"); riga.put(RDOC_DESCEST, descragg); } riga.put(RDOC_CODIVA,codiva); set_perc_provv(riga); set_perc_provv(riga, false); break; } else // se non è selezionato raggrupa su unico articolo controllo il tipo canone se è impostato a importo fisso if (tipocan == 1) //se è selezionato tipo canone = importo fisso { // estraggo il canone fisso e l'articolo in configurazione const real canfis=contr.get_real(LVCONDV_IMPFIX); const TString80 codartcfg = ini_get_string(CONFIG_DITTA, "lv", "Codartfix"); const TString80 descart = cached_article(codartcfg).get(ANAMAG_DESCR); const TString descragg = cached_article(codartcfg).get(ANAMAG_DESCRAGG); // istanzio una token string e poi una cache per estrarre l'unità di misura dell articolo in configurazione da UMART TToken_string key; key.add(codartcfg); key.add(1); const TRectype& umart = cache().get(LF_UMART,key); const TString4 umcodart = umart.get(UMART_UM); /* estraggo il codice IVA istanziando in primis una cache su CFVEN per analizzare il codice esenzione iva del cliente in questione. Se è >0 imposto il codiva a tale valore, altrimenti se è uguale a 0 istanzio un altra cache su ANAMAG e imposto il codiva uguale al codice iva dell articolo in questione */ key = doc.get(DOC_TIPOCF); key.add(clifo); const TRectype& cfven = cache().get(LF_CFVEN,key); TString8 codiva = cfven.get(CFV_ASSFIS); if (codiva.blank()) { const TRectype& anamag = cache().get(LF_ANAMAG,codartcfg); codiva = anamag.get(ANAMAG_CODIVA); } const int rigamerce = doc.physical_rows() > 0 && doc[1].is_descrizione()?2:1; TRiga_documento& fixrow=doc.insert_row(rigamerce, "01"); // creo una nuova riga in cima al documento e imposto i valori appena estratti fixrow.put(RDOC_QTA,UNO); fixrow.put(RDOC_UMQTA,umcodart); fixrow.put(RDOC_PREZZO,canfis); fixrow.put(RDOC_CODART,codartcfg); fixrow.put(RDOC_DESCR,descart); if (descragg.full()) { fixrow.put(RDOC_DESCLUNGA, "X"); fixrow.put(RDOC_DESCEST, descragg); } fixrow.put(RDOC_CODIVA,codiva); int tipocanfix = contr.get_int(LVCONDV_CANFIX); const int rows = doc.physical_rows(); switch (tipocanfix) { case 0: for (int k = rigamerce+1; k <= rows; k++) doc.destroy_row(k); break; case 1: for (int k = rigamerce+1; k <= rows; k++) { TRiga_documento& rout = doc[k]; rout.zero(RDOC_PREZZO); } break; case 2: for (int k = rigamerce+1; k <= rows; k++) { TRiga_documento& rout = doc[k]; rout.zero(RDOC_PREZZO); rout.zero(RDOC_QTA); } break; default: break; } break; } else // se il tipo canone è impostato a nessuno o % sul valore convenzionale per cliente vado in ambedue i casi ad eseguire il ciclo che analizza i tipi forfait { //per ogni documento, scorro tutte le sue righe for (int i = 1; i <= doc.physical_rows() ; i++) { TRiga_documento& rout = doc[i]; const TString80 codart = rout.get(RDOC_CODART); //leggo dalla riga del contratto di questo articolo il tipo dotazione e //la scelta per la % sul val.conv su articolo o cliente const TRectype& rcont = contr.row(codart); const TString4 tipodot = rcont.get(LVRCONDV_NOLCIC); const TString4 artcli = rcont.get(LVRCONDV_VCARTCLI); real dot; const int annoes = _data_elab.year(); //instanzio il TArticolo_lavanderia //cerco la giacenza per articolo dell'articolo esaminato TArticolo_lavanderie& artlav = cached_article_laundry(codart, 'C', clifo, use_indsp ? indsped : 0); //estraggo il record corrispondente su LF_CLIFOGIAC const TRecmag_lavanderie& reclav = artlav.find_rec(annoes); //se il tipo dotazione è iniziale 'I', allora leggo la dotazione iniziale //dalle giacenze articolo per cliente, altrimenti leggo la dotazione odierna if (tipodot == "I") dot = reclav.get_real("DOTIN"); else dot = reclav.get_real("DOTOD"); //leggo dalla riga contratto il tipo forfait const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF); switch (tipoforf) { case 0: //forfait = NESSUNO { //gestione fatturazione a kg const bool fatkg = rcont.get_bool(LVRCONDV_FATTKG); //se devo fatturare a kg if(fatkg) { const TString4 umkg = ini_get_string(CONFIG_DITTA, "lv", "UmKg"); const TString4 umri = rout.get(RDOC_UMQTA); //se la riga è già espressa in kg non devo fare niente, altrimenti: if(umri != umkg) { //leggo e controllo l'unità di misura del peso const TString4 ump = artlav.get(ANAMAG_UMP); if(ump.empty()) { warning_box(TR("Manca l'unità di misura del peso")); break; } //leggo e controllo il peso dell'articolo const real peso = artlav.get_real(ANAMAG_PESO); if(peso == ZERO) { warning_box(TR("Manca il peso")); break; } //leggo l'unità di misura dell'articolo e la quantità convertita all'unità di misura dell'articolo const TString4 umart = artlav.um()[1].get(UMART_UM); const real qta = artlav.convert_to_um(rout.get_real(RDOC_QTA), umart, umri, false); //se l'articolo non è espresso in kg, allora: if(umart != umkg) { //preparo una cache sulla tabella delle unità di misura const TRectype& unita = cache().get("%UMS", ump); real fatconv = UNO; if (ump != umkg) { //leggo e controllo se esiste l'unità di misura di riferimento const TString4 umrif = unita.get("S7"); if(umrif.empty()) { warning_box(TR("Manca l'unità di misura di riferimento")); break; } if(umrif != umkg) { warning_box(TR("L'unità di misura di riferimento non è quella dei Kg")); break; } //leggo e controllo il fattore di conversione fatconv = unita.get_real("R10"); if(fatconv == ZERO) { warning_box(TR("Manca il fattore di conversione")); break; } } //se tutti i controlli sono andati a buon fine, converto la quantità e la scrivo sulla riga documento const real qtaconv = qta * fatconv * peso; rout.put(RDOC_UMQTA, umkg); rout.put(RDOC_QTA, qtaconv); } } } } break; case 1: //forfait = A VALORE FISSO { rout.put(RDOC_QTA, UNO); //qta fissa a UNO rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_IMPFISART)); //prezzo letto dalla riga contratto // gestione in base codice per valore fisso ??? tolta la scelta dell'articolo o del cliente } break; case 2: //forfait = NOLO { //aggiungo una riga tipo merce, che contiene tutti i dati della riga del documento //di partenza, poi costruisco la descrizione in base alla periodicità di fatturazione, //metto la qta uguale alla dotazione che ho appena letto //e prendo il prezzo nolo dalla riga contratto if (dot != ZERO && nolo_computed.objptr(codart) == NULL) { TRiga_documento& nolorow = doc.insert_row(++i, "01"); nolo_computed.add(codart, codart); doc.copy_data(nolorow, rout); const TString descrart = rout.get(RDOC_DESCR); TString80 descr("Nolo"); const int contrper = contr.get_int(LVCONDV_PERFAT); switch (contrper) { case 0: descr << " per il giorno "; break; case 1: descr << " per la settimana "; break; case 2: descr << " per la quindicina "; break; case 3: descr << " per il mese "; break; default: break; } descr << descrart; int split_pos = descr.find('\n'); const int descr_len = nolorow.length(RDOC_DESCR); if (split_pos < 0 && descr.len() > descr_len) split_pos = descr_len; if (split_pos > descr_len) split_pos = descr_len; if (split_pos > 0) { nolorow.put(RDOC_DESCR, descr.left(split_pos)); const TString& dest = descr.mid(split_pos); nolorow.put(RDOC_DESCLUNGA, "X"); nolorow.put(RDOC_DESCEST, dest); } else { nolorow.put(RDOC_DESCR, descr); nolorow.zero(RDOC_DESCLUNGA); nolorow.zero(RDOC_DESCEST); } nolorow.put(RDOC_QTA, dot); nolorow.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZNOL)); } } break; case 3: //forfait = CICLAGGIO { //leggo la quantità consegnata e calcolo consumo e ciclaggio secondo le formule //CONSUMO = QTA * PREZZO(dalla riga documento) //CLICLAGGIO = DOT * PREZZO(dalla riga contratto) * MINIMO CICLAGGIO const real qta = rout.get_real(RDOC_QTA); const real consumo = qta * rout.get_real(RDOC_PREZZO); const real ciclaggio = dot * rcont.get_real(LVRCONDV_PREZZO) * rcont.get_real(LVRCONDV_MINCIC); //se il consumo è minore del ciclaggio, allora if (consumo < ciclaggio) { //leggo il flag del tipo ciclaggio const bool cicl2rig = contr.get_bool(LVCONDV_CICLAGGIO); //calcolo il valore cicl secondo la formula CICL = MINIMO CICLAGGIO * DOT const real cicl = rcont.get_real(LVRCONDV_MINCIC) * dot; //se il ciclaggio è su due linee, allora aggiungo una riga merce, per pareggiare il minimo ciclaggio //che ha come quantità la differenza tra la quantità di minimo cilcaggio //e la quantità effettivamente consegnata e come prezzo il prezzo preso dalla riga contratto; //altimenti correggo quantità e prezzo direttamente sulla riga documento che sto analizzando if (cicl2rig) { TRiga_documento& congrow = doc.insert_row(++i, "01"); doc.copy_data(congrow,rout); congrow.put(RDOC_DESCR,"Pareggio minimo ciclaggio"); congrow.put(RDOC_QTA, cicl - qta); congrow.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZZO)); } else { rout.put(RDOC_QTA, cicl); rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZZO)); } } } break; case 4: //forfait = % SUL VALORE CONVENZIONALE { //leggo dalla riga contratto la % sul val.conv su articolo o cliente const char tipovalconv = rcont.get_char(LVRCONDV_VCARTCLI); //se la percentuale sul valore convenzionale è sull'articolo, allora: if (tipovalconv == 'A') { //leggo la quantità consegnata e calcolo consumo e importo convenzionale secondo le formule //CONSUMO = QTA * PREZZO(dalla riga documento) //IMPCONV = DOT * PREZZO(dalla riga contratto) * PERCENTUALE DI FORFAIT CLIENTE const real qta = rout.get_real(RDOC_QTA); const real consumo = qta * rout.get_real(RDOC_PREZZO); const real impconv = dot * rcont.get_real(LVRCONDV_VALCONV) * rcont.get_real(LVRCONDV_FORFPERCL) / 100; impvconv += impconv; consvconv += consumo; } else { //se la percentuale sul valore convenzionale è sul cliente, allora se il flag valconvcli è false if (!valconvcli) { //pongo valconvcli a true in modo da non tornare più in questo if valconvcli = true; //instanzio i due real che andranno a contenere l'importo covenzionale totale e il consumo totale real impconvtot; real consumotot; TAssoc_array arts; //scorro tutte le righe documento dalla riga in esame fino alla fine for (int j = i; j < doc.physical_rows(); j++) { //instanzio la riga documento e sommo ai totali gli importi solo se //la percentuale sul valore convenzionale è sul cliente TRiga_documento& riga = doc[j]; const TString80 codart = riga.get(RDOC_CODART); const TRectype & rcont = contr.row(codart); const char tipvalconvcli = rcont.get_char(LVRCONDV_VCARTCLI); char lavtype = riga.get_char("LVTYPE"); if (tipvalconvcli == 'C' && lavtype != 'D') { if (arts.objptr(codart) == NULL) { const TString4 tipodot = rcont.get(LVRCONDV_NOLCIC); TArticolo_lavanderie& art = cached_article_laundry(codart, 'C', clifo, use_indsp ? indsped : 0); //estraggo il record corrispondente su LF_CLIFOGIAC const TRecmag_lavanderie& rec = art.find_rec(annoes); //se il tipo dotazione è iniziale 'I', allora leggo la dotazione iniziale //dalle giacenze articolo per cliente, altrimenti leggo la dotazione odierna if (tipodot == "I") dot = rec.get_real("DOTIN"); else dot = rec.get_real("DOTOD"); const real impconv = dot * rcont.get_real(LVRCONDV_VALCONV) * rcont.get_real(LVRCONDV_FORFPERCL) / CENTO; impconvtot += impconv; arts.add(codart, codart); } consumotot += riga.get_real(RDOC_QTA) * riga.get_real(RDOC_PREZZO); } } //se il consumo è minore del ciclaggio, allora if (consumotot < impconvtot) { const bool cicl2rig=contr.get_bool(LVCONDV_CICLAGGIO); const TString80 codartcon = ini_get_string(CONFIG_DITTA, "lv", "Codartcofix"); //se il ciclaggio è su due linee, allora aggiungo una riga merce, che contiene //il conguaglio al valore convenzionale, che ha come quantità la costante UNO //e come prezzo la differenza tra l'importo convenzionale totale e il consumo totale; //altimenti correggo quantità e prezzo direttamente sulla riga documento che sto analizzando //e elimino tutte le righe che vanno a comporre il totale in modo che rimanga una riga sola //per mostrare l'importo del conguaglio al valore convenzionale if (cicl2rig) { i++; TRiga_documento& congrow=doc.new_row("01"); doc.copy_data(congrow, rout); congrow.put(RDOC_CODART, codartcon); congrow.put(RDOC_CHECKED, "X"); congrow.put(RDOC_CODARTMAG, codartcon); congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale"); congrow.put(RDOC_QTA, UNO); congrow.put(RDOC_PREZZO, impconvtot - consumotot); set_perc_provv(congrow); set_perc_provv(congrow, false); } else { rout.put(RDOC_CODART, codartcon); rout.put(RDOC_CHECKED, "X"); rout.put(RDOC_CODARTMAG, codartcon); rout.put(RDOC_DESCR, "Valore convenzionale"); rout.put(RDOC_QTA, UNO); rout.put(RDOC_PREZZO, impconvtot); for (int k = doc.physical_rows(); k > i; k--) { TRiga_documento& delrow = doc[k]; const TString80 codart = delrow.get(RDOC_CODART); const TRectype& rcont = contr.row(codart); const char tipvalconvcli = rcont.get_char(LVRCONDV_VCARTCLI); char lavtype = delrow.get_char("LVTYPE"); if (tipvalconvcli == 'C' && lavtype != 'D') doc.destroy_row(k, true); } } } } } } break; case 5: //forfait = FISSO SU DOTAZIONE INIZIALE { rout.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_IMPFISART)); const real dotin = reclav.get_real("DOTIN"); rout.put(RDOC_QTA, dotin); if (rout.get(RDOC_DESCR).blank()) { const TString & descr = cached_article(codart).get(RDOC_DESCR); const TString descragg = cached_article(codart).get(ANAMAG_DESCRAGG); rout.put(RDOC_DESCR, descr); if (descragg.full()) { rout.put(RDOC_DESCLUNGA, "X"); rout.put(RDOC_DESCEST, descragg); } } const TString80 codartorig=rout.get(RDOC_CODART); for (int h = doc.physical_rows(); h > i; h--) { TRiga_documento& delrow = doc[h]; const TString80 codart=delrow.get(RDOC_CODART); if ( codartorig == codart) doc.destroy_row(h, true); } } break; default: break; } } //se il consumo è minore del ciclaggio, allora if (impvconv - consvconv > ZERO) { const bool cicl2rig = contr.get_bool(LVCONDV_CICLAGGIO); const int rows = doc.physical_rows(); //se il ciclaggio è su due linee, allora aggiungo una riga merce, che contiene //il conguaglio al valore convenzionale, che ha come quantità la costante UNO //e come prezzo la differenza tra l'importo convenzionale e il consumo; //altimenti correggo quantità e prezzo direttamente sulla riga documento che sto analizzando TRiga_documento& congrow = doc.new_row("01"); const TString80 codartcon = ini_get_string(CONFIG_DITTA, "lv", "Codartcofix"); congrow.put(RDOC_CODART, codartcon); congrow.put(RDOC_CHECKED, "X"); congrow.put(RDOC_CODARTMAG, codartcon); congrow.put(RDOC_DESCR, "Conguaglio valore convenzionale"); congrow.put(RDOC_QTA, UNO); TString8 codiva = doc.clifor().vendite().get(CFV_ASSFIS); if (codiva.blank()) codiva = cache().get(LF_ANAMAG, codartcon, ANAMAG_CODIVA); congrow.put(RDOC_CODIVA, codiva); if (cicl2rig) congrow.put(RDOC_PREZZO, impvconv - consvconv); else { congrow.put(RDOC_PREZZO, impvconv); for (int k = rows - 1; k >= 1; k--) { TRiga_documento& delrow = doc[k]; const TString80 codart = delrow.get(RDOC_CODART); const TRectype& rcont = contr.row(codart); const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF); char lavtype = delrow.get_char("LVTYPE"); if (tipoforf == 4 && lavtype != 'D') doc.destroy_row(k, true); } } } } if (redditivita > ZERO && fatt_02() && !ragart && tipocan != 1) { const real totdoc = doc.totale_doc(); const real provvigione1 = doc.provvigione(); const real provvigione2 = doc.provvigione(false); doc.put(RDOC_TOTREALE, encode(totdoc.string())); doc.put(RDOC_PROVV1REALE, encode(provvigione1.string())); doc.put(RDOC_PROVV2REALE, encode(provvigione2.string())); for(int j = doc.physical_rows(); j > 0; j--) { TRiga_documento& rdoc = doc[j]; const TString80 codart = rdoc.get(RDOC_CODARTMAG); const TRectype& rcont = contr.row(codart); const int tipoforf = rcont.get_int(LVRCONDV_TIPOFORF); long ppconf = cached_article(codart).get_long(ANAMAG_PPCONF); const real real_qta = rdoc.get(RDOC_QTA); if (rcont.get_int(LVRCONDV_CALCCONS) != 1 || ppconf == 0) ppconf = 1; const char lvtype = rdoc.get_char("LVTYPE"); bool row_has_02 = (tipoforf == 0) && (real_qta / ppconf > UNO || redditivita >= CENTO) && (lvtype == 'C'); // 0 forfait = NESSUN FORFAIT SI // 1 forfait = A VALORE FISSO NO // 2 forfait = NOLO NO // 3 forfait = CICLAGGIO NO // 4 forfait = % SUL VALORE CONVENZIONALE NO // 5 forfait = FISSO SU DOTAZIONE INIZIALE NO if (row_has_02) { const TString key = format("%04d%04d", doc.get_int("FATID"), rdoc.get_int(RDOC_IDRIGA)); real new_qta = real_qta; TCalc_02_data * data = (TCalc_02_data *) _output_rows_02.objptr(key); rdoc.put(RDOC_QTAREALE, encode(real_qta.string())); if (data != NULL) { new_qta /= ppconf; real test = new_qta; test.ceil(); if (test * ppconf != real_qta) { warning_box(FR("L'articolo %s per il cliente %ld ha una quantità %s\nnon coincidente coi pacchi. Controllare le bolle"), (const char *)codart, doc.get_long(DOC_CODCF), real_qta.string()); ppconf = 1; } new_qta *= (CENTO - redditivita) / CENTO; new_qta.round(); data->distr() = new_qta; new_qta *= ppconf; rdoc.put(RDOC_QTA, new_qta); real new_qta_rit = rdoc.get_real("TOTRIT"); new_qta_rit *= (CENTO - redditivita) / CENTO; new_qta_rit.round(); data->distr_rit() = new_qta_rit; TAssoc_array & bol_rows = data->bol_rows(); FOR_EACH_ASSOC_OBJECT(bol_rows, obj, wkey, item) { TToken_string bolkey(wkey); const long ndoc = bolkey.get_long(3); const long id = bolkey.get_long(4); for (int i = 0; i < doc_in.items(); i++) { TDocumento& doc = doc_in[i]; if (doc.get_long(DOC_NDOC) == ndoc) { TRiga_documento * bolrow = (TRiga_documento *) doc.get_row_id(id); if (bolrow != NULL) { const TString8 causale = bolrow->get(RDOC_CODAGG1); const TCausale_lavanderie & cau = cached_causale_lavanderie(causale); if (cau.is_rotto()) break; bool fatturo_ritirato = cau.is_ritiro(); bool fatturo_consegnato = cau.is_consegna(); if (fatturo_ritirato) { const TCausale_magazzino& rit = cau.causale_ritiro(); fatturo_ritirato = rit.sgn(s_consmese) != 0; } if (fatturo_consegnato) { const TCausale_magazzino& con = cau.causale_consegna(); fatturo_consegnato = con.sgn(s_consmese) != 0; } TString str_real = bolrow->get(RDOC_QTA); real qta = real(str_real) / ppconf; qta.round(); if (str_real.full()) bolrow->put(RDOC_QTAREALE, encode(str_real)); str_real = bolrow->get(RDOC_QTAGG1); real qtarit = real(str_real); data->distr_rit().add(qtarit); if (str_real.full()) bolrow->put(RDOC_QTARITREALE, encode(str_real)); if (fatturo_ritirato && !fatturo_consegnato) // ! fatturo il ritirato o fatturo il consegnato { qtarit = real(str_real) / ppconf; qtarit.round(); data->distr().add(qtarit); } else data->distr().add(qta); } else message_box("Riga_bolla smarrita %d - %s - %ld - id = %ld", bolkey.get_int(1), bolkey.get(0), bolkey.get(3), bolkey.get(4)); break; } } } FOR_EACH_ASSOC_OBJECT(bol_rows, obj1, wkey1, item1) { TToken_string bolkey(wkey1); const long ndoc = bolkey.get_long(3); const long id = bolkey.get_long(4); for (int i = 0; i < doc_in.items(); i++) { TDocumento& docb = doc_in[i]; if (docb.get_long(DOC_NDOC) == ndoc) { TRiga_documento * bolrow = (TRiga_documento *) docb.get_row_id(id); if (bolrow != NULL) { const TString8 causale = bolrow->get(RDOC_CODAGG1); const TCausale_lavanderie & cau = cached_causale_lavanderie(causale); if (cau.is_rotto()) break; bool fatturo_ritirato = cau.is_ritiro(); bool fatturo_consegnato = cau.is_consegna(); if (fatturo_ritirato) { const TCausale_magazzino& rit = cau.causale_ritiro(); fatturo_ritirato = rit.sgn(s_consmese) != 0; } if (fatturo_consegnato) { const TCausale_magazzino& con = cau.causale_consegna(); fatturo_consegnato = con.sgn(s_consmese) != 0; } const real qta = data->distr().get() * ppconf; const real qtarit = data->distr_rit().get(); bolrow->put(RDOC_QTAGG1, qtarit); if ((!fatturo_ritirato) || (fatturo_consegnato)) // ! fatturo il ritirato o fatturo il consegnato bolrow->put(RDOC_QTA, qta); else int c = 1; // placeholder } else message_box("Riga_bolla smarrita %d - %s - %ld - id = %ld", bolkey.get_int(1), bolkey.get(0), bolkey.get(3), bolkey.get(4)); break; } } } } } } } for(int h = doc.physical_rows(); h > 0; h--) { TRiga_documento& rdoc = doc[h]; if (rdoc.get(RDOC_DESCR).empty() || ((rdoc.imponibile() == ZERO && rdoc.get_real(RDOC_QTA) == ZERO))) doc.destroy_row(h, true); } } for (int id = doc_out.items() - 1; id >= 0 ; id--) { TDocumento& doc = doc_out[id]; const int rows = doc.physical_rows(); bool to_delete = true; for (int i = rows; to_delete && i > 0; i--) { const TRiga_documento& riga = doc[i]; if (!riga.is_descrizione()) to_delete = (riga.imponibile() == ZERO && riga.get_real(RDOC_QTA) == ZERO); } if (to_delete || doc.totale_doc() == ZERO) doc_out.destroy(id); } for (int id = doc_out.items() - 1; id >= 0 ; id--) { TDocumento& doc = doc_out[id]; const TString4 tipocf = doc.get(DOC_TIPOCF); const int act_cli = doc.get_long(DOC_CODCF); TToken_string key(tipocf); key.add(act_cli); const TRectype & reccli = cache().get(LF_CLIFO, key); const long new_cli = reccli.get_long(CLI_CODCFFATT); if (new_cli > 0L) { doc.put(DOC_CODCF, new_cli); key = tipocf; key.add(new_cli); const TRectype & new_reccli = cache().get(LF_CLIFO, key); const TRectype & new_reccliven = cache().get(LF_CFVEN, key); TLaundry_contract contr(new_cli, doc.get_long(DOC_CODINDSP), _data_elab); if (new_reccli.get_int(CLI_ALLEG) == 7 && new_reccliven.get_bool(CFV_FATTSOSP)) doc.put(DOC_LIQDIFF, "X"); doc.put(DOC_CODINDSP, new_reccliven.get(CFV_CODINDDOC)); TString descr; if (ini_get_bool(CONFIG_DITTA, "lv", "DestHead")) { descr << reccli.get(CLI_RAGSOC) << ", "; descr << reccli.get(CLI_INDCF) << ' ' << reccli.get(CLI_CIVCF) << ", "; descr << reccli.get(CLI_LOCCF) << ", "; TToken_string keyc = reccli.get(CLI_STATOCF); keyc.add(reccli.get(CLI_COMCF)); const TRectype & com = cache().get(LF_COMUNI, keyc); descr << reccli.get(CLI_CAPCF) << ' ' << com.get(COM_DENCOM); doc.put(DOC_DEST, descr); } else { TRiga_documento & r = doc.insert_row(1, "05"); r.put(RDOC_DESCR, "Consegne effettuate presso\n"); descr << act_cli << " " << reccli.get(CLI_RAGSOC); r.put(RDOC_DESCLUNGA, "X"); r.put(RDOC_DESCEST, descr); } if (contr.get_bool(LVCONDV_RAGGCGRUP)) { add_doc_to_list(key, doc); doc_out.destroy(id); } } } if (fatt_02()) { for (int id = doc_in.items() - 1; id >= 0 ; id--) { TDocumento & doc = doc_in[id]; const long clifo = doc.get_long(DOC_CODCF); const int indsped = doc.get_int(DOC_CODINDSP); TLaundry_contract contr(clifo,indsped,_data_elab); const real redditivita = contr.get_real(LVCONDV_REDDI); if (redditivita >= CENTO) { doc_in[id].remove(); doc_in.destroy(id); } } } } //ADD_ROWS: per adesso un segnaposto void TFatturazione_lavanderie::add_rows(TRiga_documento & rout, TRiga_documento & rin) { /*const TString8 causale = rin.get(RDOC_CODAGG1); const TRectype& cau = cache().get("&CAU", causale); const TCausale_magazzino& rit = cached_causale_magazzino(cau.get("S1")); const TCausale_magazzino& con = cached_causale_magazzino(cau.get("S2")); //movimento o meno la dotazione temporanea/odierna a seconda di cosa prevede la causale const long clifo = rin.doc().get_long(DOC_CODCF); const int indsped = rin.doc().get_int(DOC_CODINDSP); TLaundry_contract contr(clifo, indsped, _data_elab); if (cau.get_bool("B4") && contr.get_int(LVCONDV_ADDCAPROT)) // Guardo se è una causale di rotto e se è abilitato nella testata del contratto la fatturazione dei rotti { const real qta = rit.sgn(s_consmese) * rin.get_real(RDOC_QTA); rout.put(RDOC_PREZZO,contr.get_int(LVCONDV_PREZROT)); rout.add(RDOC_QTA, qta); } else { if (cau.get_bool("B0")) { const real qta = rit.sgn(s_consmese) * rin.get_real(RDOC_QTA); rout.add(RDOC_QTA, qta); } if (cau.get_bool("B1")) { const real qta = con.sgn(s_consmese) * rin.get_real(RDOC_QTA); rout.add(RDOC_QTA, qta); } } */ } //CAMPI_RAGGRUPPAMENTO_RIGHE: ridefinisco il metodo campi_raggruppamento_righe della TFatturazione_bolle void TFatturazione_lavanderie::campi_raggruppamento_righe(TToken_string& campi_riga) const { campi_riga = RDOC_CODART"|"RDOC_UMQTA; // Uguali sempre const bool ragg_rig = raggruppa_righe(); if (ragg_rig) { // Uguali se commesse attive if (dongle().active(CAAUT) || dongle().active(CMAUT)) { campi_riga.add(RDOC_CODCMS); campi_riga.add(RDOC_FASCMS); campi_riga.add(RDOC_CODCOSTO); } // Uguali opzionalmente if (riga_uguale(0)) campi_riga.add(RDOC_CODMAG); if (riga_uguale(1)) campi_riga.add(RDOC_CODIVA); if (riga_uguale(2)) { const int tipoprezzo = ini_get_int(CONFIG_DITTA, "lv", "TipoPr"); if(tipoprezzo == 0) campi_riga.add(RDOC_SCONTO); else campi_riga.add(RDOC_PREZZO"|"RDOC_SCONTO); } } } //FIND_OR_CREATE_ROW: questo metodo cerca tra tutte le righe documento della fattura prodotta //una eventuale riga lavanderia raggruppabile; se la trova restituiace quella riga, altrimenti //ne crea una nuova TRiga_documento& TFatturazione_lavanderie::find_or_create_row(TDocumento& doc_out, const TRiga_documento& rin, const char lavtype) { int r; //scorro le righe documetno for (r = doc_out.physical_rows(); r > 0; r--) { //se trovo una riga raggruppabile e di lavanderia, allora interrompo il ciclo if (doc_out[r].raggruppabile(rin, _campi_raggruppamento) && (doc_out[r].get_char("LVTYPE") == lavtype)) break; } //se non ho trovato la riga, ne creo una nuova if (r <= 0) { TRiga_documento& row = doc_out.new_row("01"); doc_out.copy_data(row, rin); row.put(RDOC_TIPORIGA, "01"); set_perc_provv(row); set_perc_provv(row, false); const TRectype& anamag = cache().get(LF_ANAMAG, rin.get(RDOC_CODART)); row.put(RDOC_CODIVA, anamag.get(ANAMAG_CODIVA)); row.zero(RDOC_CODAGG1); row.zero(RDOC_QTA); row.zero(RDOC_QTAGG1); row.zero(RDOC_CODMAGC); row.put("LVTYPE", lavtype); r = row.get_int(RDOC_NRIGA); } if (fatt_02()) { doc_out.set_row_ids(); const TString key = format("%04d%04d", doc_out.get_int("FATID"), doc_out[r].get_int(RDOC_IDRIGA)); TCalc_02_data * data = (TCalc_02_data *) _output_rows_02.objptr(key); if (data == NULL) { data = new TCalc_02_data(key); _output_rows_02.add(key, data); } TString bolkey = rin.get_rdoc_key(); data->bol_rows().add(bolkey, bolkey); } return doc_out[r]; } //CREATE_ROW: metodo che crea fisicamente la riga sul documento di uscita partendo dal documento di ingresso (bolla) void TFatturazione_lavanderie::create_row(TDocumento& doc_out, const TRiga_documento & rin) { //leggo la causale della riga del documento di ingresso const TString8 causale = rin.get(RDOC_CODAGG1); const TCausale_lavanderie & cau = cached_causale_lavanderie(causale); //recupero i dati cliente dalla testata del documento e instanzio il contratto const long clifo = rin.doc().get_long(DOC_CODCF); const int indsped = rin.doc().get_int(DOC_CODINDSP); TLaundry_contract contr(clifo, indsped, _data_elab); //leggo dal documento i valori che vanno riportati sulla fattura e recupero la riga contratto //di quell'articolo const TString80 codart = rin.get(RDOC_CODARTMAG); // non è gestito il caso di un articolo fuori contratto const real qta = rin.get_real(RDOC_QTA); const real qta1 = rin.get_real(RDOC_QTAGG1); const TRectype& rcont = contr.row(codart); //leggo dalla configurazione da dove va preso il prezzo const int tipoprezzo = ini_get_int(CONFIG_DITTA, "lv", "TipoPr"); real prezzo; //se tipoprezzo == 0 (prezzo da contratto), allora cerco il prezzo sul contratto; se l'articolo //non esiste sul contratto, allora cerco il suo prezzo sull'anagrafica di magazzino. //Se tipoprezzo == 1 (prezzo da bolla), allora leggo il prezzo sulla riga della bolla if (tipoprezzo == 0) { if (!rcont.empty()) prezzo = rcont.get_real(LVRCONDV_PREZZO); } else prezzo = rin.get_real(RDOC_PREZZO); //se è una causale di rotto e se è abilitato nella testata del contratto la fatturazione dei rotti //e se sto ritirando una quantità di merce diversa da zero, allora: if (cau.is_rotto() && contr.get_bool(LVCONDV_ADDCAPROT) && !qta1.is_zero()) { //se passo le condizioni iniziali cerco eventualmente una riga che possa essere raggruppata con quella //che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantità da ritirare //al prezzo segnato in contratto TRiga_documento& rd = find_or_create_row(doc_out, rin ,'D'); rd.put(RDOC_DESCLUNGA, "X"); rd.put(RDOC_DESCEST, "\nper addebito biancheria"); rd.add(RDOC_QTA, qta1); rd.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PREZDAN)); if (cau.get_int("I2") > 0) { rd.put(RDOC_QTAGG1, cau.get("I0")); rd.put(RDOC_QTAGG2, cau.get("I1")); rd.put(RDOC_QTAGG3, cau.get("I2")); } if (clifo != _last_cli_damn) _cli_damn++; _last_cli_damn = clifo; _art_damn++; } //se è una causale di ritirato e se sto ritirando una quantità di merce diversa da zero, allora: if (cau.is_ritiro() && !qta1.is_zero()) { //leggo la casuale di magazzino associata al ritiro e il suo segno sul consegnato mese const TCausale_magazzino& rit = cau.causale_ritiro(); const real sgnrit = rit.sgn(s_consmese); //se movimenta il consegnato mese, cerco eventualmente una riga che possa essere raggruppata con quella //che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantità che sto ritirando moltiplicata //per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla if (!sgnrit.is_zero()) { TRiga_documento& rr = find_or_create_row(doc_out, rin, 'C'); rr.add(RDOC_QTA, sgnrit * qta1); rr.put(RDOC_PREZZO, prezzo); rr.add("TOTRIT", qta1); } } //se è una causale di consegnato e se sto consegnando una quantità di merce diversa da zero, allora: if (cau.is_consegna() && !qta.is_zero()) { //leggo la casuale di magazzino associata al ritiro e i suoi segni sul consegnato mese, //sulla dotazione temporanea e sulla dotazione iniziale const TCausale_magazzino& con = cau.causale_consegna(); const real sgntmp=con.sgn(s_dottm); const real sgndotin=con.sgn(s_dotin); const real sgncons=con.sgn(s_consmese); //se movimenta la dotazione temporanea e è previsto l'addebito dotazione temporanea con prezzo diverso, //cerco eventualmente una riga che possa essere raggruppata con quella che sto guardando adesso, //altrimenti la creo; in ogni caso aggiungo la quantità che sto consegnando moltiplicata //per il suo segno al prezzo scritto sul contratto per la dotazine temporanea if (!sgntmp.is_zero() && contr.get_bool(LVCONDV_DOTTMPPRZD)) { TRiga_documento& rt = find_or_create_row(doc_out, rin, 'T'); rt.add(RDOC_QTA, sgntmp * qta); rt.put(RDOC_PREZZO, rcont.get_real(LVRCONDV_PRZDTTMP)); } //se movimenta la dotazione iniziale, cerco eventualmente una riga che possa essere raggruppata con quella //che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantità che sto consegnando moltiplicata //per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla if (!sgndotin.is_zero() && !sgncons.is_zero()) { TRiga_documento& rc = find_or_create_row(doc_out, rin, 'C'); rc.add(RDOC_QTA, sgndotin * qta); rc.put(RDOC_PREZZO, prezzo); } else { //se movimenta il consegnato mese, cerco eventualmente una riga che possa essere raggruppata con quella //che sto guardando adesso, altrimenti la creo; in ogni caso aggiungo la quantità che sto consegnando moltiplicata //per il suo segno al prezzo ricavato sopra o da contratto (o da magazzino), o da bolla if (!sgncons.is_zero()) { TRiga_documento& rc = find_or_create_row(doc_out, rin, 'C'); rc.add(RDOC_QTA, sgncons * qta); rc.put(RDOC_PREZZO, prezzo); rc.add("TOTRIT", qta1); } } } } //ELABORA: metodo che esegue alcune operazioni prliminari, quali settare la data elaborazione e trovare i campi //in base ai quali è possibile raggruppare le righe documetno, e poi chiama l'elaborazione standard per la fatturazione bool TFatturazione_lavanderie::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { _data_elab = data_elab; campi_raggruppamento_righe(_campi_raggruppamento); _output_rows_02.destroy(); return TFatturazione_bolle::elabora(doc_in, doc_out, data_elab, interattivo); } ///////////////////////////////// //// TFatturazione_msk //// ///////////////////////////////// TFatturazione_msk::TFatturazione_msk():TAutomask("lv2500a") { //imposto il periodo di fatturazione dal primo del mese precedente all'ultimo del mese precedente //se la data odierna è inferiore al 10 del mese corrente //altrimenti la imposto dal primo del mese corrente alla data odierna TDate data(TODAY); if (data.day() <= 10) { data.addmonth(-1); data.set_day(1); set(F_DADATA, data); data.set_end_month(); set(F_ADATA, data); } else { set(F_ADATA, data); data.set_day(1); set(F_DADATA, data); } if (main_app().argc() > 2) { TString16 tpela = main_app().argv(2); tpela = tpela.mid(4); TString8 codela = ini_get_string(CONFIG_DITTA, "lv", tpela); set(F_COD_ELAB, codela); field(F_COD_ELAB).check(); disable(F_COD_ELAB); disable(F_DESC_ELAB); } } ///////////////////////////////////// //// TFatturazione_lav_app //// ///////////////////////////////////// //GENERA_BOLLE_NOLO: metodo che genera le fatture di solo nolo per quei clienti a cui non è stato consegnato niente void TFatturazione_lav_app::genera_bolle_nolo(TAssoc_array& cliela, TFatturazione_lavanderie& elab, int& numdocgen, real& totimp, real& imposta, real& totdoc, real& spese) { TString4 codnum = ini_get_string(CONFIG_DITTA, "lv", "NUM_GEN"); TString4 tipodoc = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_GEN"); char stato = cache().get("%TIP", tipodoc, "S2").mid(1,1)[0]; //preparo la query sui contratti TString str; str << "USE LVCONDV"; if (_msk->get_long(F_DACODCF) > 0) str << "\nFROM CODCF=" << _msk->get_long(F_DACODCF); if (_msk->get_long(F_ACODCF) > 0) str << "\nTO CODCF=" << _msk->get_long(F_ACODCF); TISAM_recordset contr(str); TLista_documenti doc_in; TLista_documenti doc_out; TProgind pi(contr.items(), "Fatturazione", true, true); for(bool ok = contr.move_first(); ok; ok = contr.move_next()) { pi.set_text(TR("Elaborazione Nolo")); if (!pi.addstatus(1)) break; //scarto i contratti scaduti if (contr.get(LVCONDV_DATASC).as_date().ok()) if (_msk->get_date(F_DADATA) < contr.get(LVCONDV_DATAIN).as_date() || _msk->get_date(F_ADATA) > contr.get(LVCONDV_DATASC).as_date()) continue; //scarto tutti quelli che non sono in periodo di fatturazione corretto if (contr.get(LVCONDV_PERFAT).as_int() > _msk->get_int(F_PERFAT)) continue; // scarto i clienti sospesi if (contr.get(LVCONDV_FATTSOSP).as_bool()) continue; if(cliela.is_key(contr.get(LVCONDV_CODCF).as_string())) continue; TDocumento *pdoc= new TDocumento('D', _msk->get_date(F_DATAFAT).year(), codnum, 0); doc_in.add(pdoc); TDocumento& doc = *pdoc; doc.put(DOC_TIPODOC, tipodoc); doc.put(DOC_STATO, stato); doc.put(DOC_TIPOCF, 'C'); TLaundry_contract contratto(contr.cursor()->curr()); const long codcf = contratto.get_long(LVCONDV_CODCF); const int codcont = contratto.get_int(LVCONDV_CODCONT); const bool fattnocons = !contratto.get_bool(LVCONDV_FORFNOCONS); doc.put(DOC_CODCF, codcf); TToken_string key("C"); key.add(codcf); const TRectype& clifo = cache().get(LF_CLIFO, key); const TString4 codpag = clifo.get(CLI_CODPAG); const long codabi = clifo.get_long(CLI_CODABI); const long codcab = clifo.get_long(CLI_CODCAB); const TString80 iban = clifo.get(CLI_IBAN); //recupero i dati di interesse dal file CFVEN const TRectype& cfven = cache().get(LF_CFVEN, key); const long codabipr = cfven.get_long(CFV_CODABIPR); const long codcabpr = cfven.get_long(CFV_CODCABPR); const bool ragdoc = cfven.get_bool(CFV_RAGGDOC); const TString8 codag1 = cfven.get(CFV_CODAG1); const TString4 codmez = cfven.get(CFV_CODSPMEZZO); const TString4 codporto = cfven.get(CFV_CODPORTO); const TString4 codnote1 = cfven.get(CFV_CODNOTESP1); const TString4 codnote2 = cfven.get(CFV_CODNOTESP2); const TString4 codnote = cfven.get(CFV_CODNOTE); const TString8 codvet1 = cfven.get(CFV_CODVETT1); const TString8 codvet2 = cfven.get(CFV_CODVETT2); const TString8 codvet3 = cfven.get(CFV_CODVETT3); const real speseinc = cfven.get_real(CFV_PERCSPINC); const TString4 catven = cfven.get(CFV_CATVEN); const bool addbolli = cfven.get_bool(CFV_ADDBOLLI); const TString8 codlist = cfven.get(CFV_CODLIST); const TString4 codzona = cfven.get(CFV_CODZONA); //gestione sconto TString sconto; const char tpgest = ini_get_string(CONFIG_DITTA, "ve", "GESSCO")[0]; switch(tpgest) { case 'P': sconto = cfven.get(CFV_SCONTO); break; //Percentuale su anagrafica cliente case 'T': sconto = cache().get("%SCC", cfven.get(CFV_CODSCC), "S1"); break; //Gestione tabella sconti case 'A': //Gestione archivio sconti { TConfig ditta(CONFIG_DITTA, "ve"); TLocalisamfile sconti(LF_SCONTI); sconti.put("TIPO", "I"); if(ditta.get_bool("SCOKEY", "ve", 1)) sconti.put("CODCAT", cfven.get(CFV_CATVEN)); TString16 cod; if(ditta.get_bool("SCOKEY", "ve", 2)) cod.format("%-2s", (const char*)cfven.get(CFV_CODSCC)); else cod = " "; if(ditta.get_bool("SCOKEY", "ve", 3)) { TString8 tmp; tmp.format("%-2s", (const char*)cfven.get(CFV_CODZONA)); cod << tmp; } else cod << " "; if(ditta.get_bool("SCOKEY", "ve", 4)) cod << clifo.get(CLI_CODPAG); sconti.put("CODART", cod); if (sconti.read() == NOERR) sconto = sconti.get("SCONTO"); } case 'N': //sconto non gestito default: break; } doc.put(DOC_CODPAG, codpag); doc.put(DOC_CODABIA, codabi); doc.put(DOC_CODCABA, codcab); doc.put(DOC_IBAN, iban); doc.put(DOC_CODABIP, codabipr); doc.put(DOC_CODCABP, codcabpr); doc.put(DOC_CODAGVIS, codag1); doc.put(DOC_CODSPMEZZO, codmez); doc.put(DOC_ZONA, codzona); doc.put(DOC_CODPORTO, codporto); doc.put(DOC_CODNOTESP1, codnote1); doc.put(DOC_CODNOTESP2, codnote2); doc.put(DOC_CODNOTE, codnote); doc.put(DOC_CODVETT1, codvet1); doc.put(DOC_CODVETT2, codvet2); doc.put(DOC_CODVETT3, codvet3); doc.put(DOC_CATVEN, catven); doc.put(DOC_CODLIST, codlist); doc.put(DOC_PERCSPINC, speseinc); doc.put(DOC_ADDBOLLI, addbolli); doc.put(DOC_SCONTOPERC, sconto); TString str; str << "USE LVRCONDV\n" << "FROM CODCF=" << codcf << " CODCONT=" << codcont << "\n" << "TO CODCF=" << codcf << " CODCONT=" << codcont; TISAM_recordset rcont(str); for(bool ok = rcont.move_first(); ok; ok = rcont.move_next()) { TRectype& riga = rcont.cursor()->curr(); const int tipoforf = riga.get_int(LVRCONDV_TIPOFORF); //il nolo deve esserci sempre, il ciclaggio solo se fattnocons -> per me l'if diventa: //if (tipoforf > 0 && (tipoforf != 2 && fattnocons)) if (tipoforf > 0 && ((tipoforf == 2) || (tipoforf != 2 && fattnocons))) { TRiga_documento& rdoc = doc.new_row("21"); rdoc.put(RDOC_CODART, riga.get(LVRCONDV_CODART)); rdoc.put(RDOC_CODARTMAG, riga.get(LVRCONDV_CODART)); real r = UNO; if(tipoforf == 3 || tipoforf == 4) r = ZERO; rdoc.put(RDOC_QTA, r); rdoc.put(RDOC_QTAGG1, r); rdoc.put(RDOC_PREZZO, riga.get_real(LVRCONDV_PREZNOL)); rdoc.put(RDOC_CHECKED, true); rdoc.put(RDOC_UMQTA, riga.get(LVRCONDV_UM)); TToken_string key; key.add('C'); key.add(codcf); TString8 codiva = cache().get(LF_CFVEN, key, CFV_ASSFIS); if (codiva.blank()) codiva = cache().get(LF_ANAMAG, riga.get(LVRCONDV_CODART), ANAMAG_CODIVA); rdoc.put(RDOC_CODIVA, codiva); rdoc.put(RDOC_CODAGG1, ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV")); elab.set_perc_provv(rdoc); elab.set_perc_provv(rdoc, false); } } if (ini_get_bool(CONFIG_DITTA, "lv", "RifTest")) elab.put("B15", true); //forzo la descrizione abbreviata if (doc.physical_rows() > 0) { elab.elabora(doc_in, doc_out, _msk->get_date(F_DATAFAT)); if (!_solototali) int err = doc_out.write(); numdocgen += doc_out.items(); if (doc_out.items() > 0) { totimp += doc_out[0].imponibile(); imposta += doc_out[0].imposta(); totdoc += doc_out[0].totale_doc(); spese += doc_out[0].spese(); } } doc_out.destroy(-1); doc_in.destroy(-1); } } //CONTROLLI PRELIMINARI: metodo che si preoccupa di ferivicare la presenza in configurazione di tutti //i dati necessari alla fatturazione bool TFatturazione_lav_app::controlli_preliminari() { bool corretto = true; //controllo se il tipo documento è configurato if (ini_get_string(CONFIG_DITTA, "lv", "NUM_FAT").empty() || ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_FAT").empty()) { warning_box(TR("Il Tipo documento fattura non è configurato correttamente")); corretto = false; } //controllo se le causali di dafault sono configurate if (ini_get_string(CONFIG_DITTA, "lv", "CAUSLAV").empty()) { warning_box(TR("La causale di default non è configurata correttamente")); corretto = false; } if (ini_get_string(CONFIG_DITTA, "lv", "CAULVRITDT").empty()) { warning_box(TR("La causale di default non è configurata correttamente")); corretto = false; } //controllo se l'articolo per il canone fisso è configurato if (ini_get_string(CONFIG_DITTA, "lv", "Codartfix").empty()) { warning_box(TR("L'articolo per canone fisso non è configurato correttamente")); corretto = false; } //controllo se l'articolo per il raggruppamento è configurato if (ini_get_string(CONFIG_DITTA, "lv", "Codartcafix").empty()) { warning_box(TR("L'articolo per il raggruppamento non è configurato correttamente")); corretto = false; } //controllo se l'articolo per il raggruppamento è configurato if (ini_get_string(CONFIG_DITTA, "lv", "Codartcofix").empty()) { warning_box(TR("L'articolo per il valore convenzionale non è configurato correttamente")); corretto = false; } //controllo se l'unità di misura per la fatturazioni a Kg è settata if(ini_get_string(CONFIG_DITTA, "lv", "UmKg").empty()) { warning_box(TR("L'unità di misura per la fatturazione a Kg non è configurata correttamente")); corretto = false; } return corretto; } bool TFatturazione_lav_app::copy_file(const TFilename& src, const TFilename& dst) const { // Crea la cartella di destinazione se necessario const char* dstdir = dst.path(); if (*dstdir && !xvt_fsys_mkdir(dstdir)) return error_box(FR("Impossibile creare la cartella %s"), dst.path()); // Copia veramente il file return ::fcopy(src, dst); } bool TFatturazione_lav_app::copy_tree(const char* src_study, const char* dst_study) const { xvt_fsys_save_dir(); TFilename mask(src_study); mask.add("*."); SLIST dlist = xvt_fsys_list_files(DIR_TYPE, mask, TRUE); xvt_fsys_restore_dir(); TProgind pd(xvt_slist_count(dlist), TR("Copia cartelle"), true, true); TString msg; // Messaggio di progresso bool go_on = true; for (SLIST_ELT d = xvt_slist_get_first(dlist); d && go_on; d = xvt_slist_get_next(dlist, d)) { if (!pd.addstatus(1)) { go_on = false; break; } const TFilename dir = xvt_slist_get(dlist, d, NULL); TString name = dir.name(); name.lower(); if (name == "cesp") // Ignora la vetusta cartella Cespiti in FoxPro continue; msg.cut(0) << TR("Copia di ") << name; pd.set_text(msg); mask = dir; mask.add("*.*"); TString_array files; list_files(mask, files); TProgind pi(files.items(), "Copia file", true, true); TFilename dst; FOR_EACH_ARRAY_ROW(files, i, f) { if (!pi.addstatus(1)) { go_on = false; break; } TFilename src(*f); TString16 ext(src.ext()); ext.lower(); if (ext != "zip" && ext != "rar" && ext != "mdb" && ext != "inf") { msg.cut(0) << TR("Copia di ") << src; pi.set_text(msg); dst = dst_study; dst.add(name); dst.add(src.name()); copy_file(src, dst); } } } xvt_slist_destroy(dlist); return go_on; } void TFatturazione_lav_app::main_loop() { bool prova = false; const bool use_indsp = ini_get_bool(CONFIG_DITTA, "mg", "MOV_INDSPED"); const bool prezzo_da_contratto = ini_get_int(CONFIG_DITTA, "lv", "Tipopr") == 0; const bool agghead = prezzo_da_contratto || ini_get_bool(CONFIG_DITTA, "lv", "AggHead"); const TString4 num_buoni = ini_get_string(CONFIG_DITTA, "lv", "NUM_GEN"); const TString4 tipo_buoni = ini_get_string(CONFIG_DITTA, "lv", "TIPODOC_GEN"); if (main_app().argc() > 2) { TString16 tpela = main_app().argv(2); tpela = tpela.mid(4); prova = (tpela == "FatPro"); } //instanzio la maschera _msk = new TFatturazione_msk(); _msk->show(F_SAVEDATA, lv_is_02_active()); //instanzio i localisamfile che mi servono TLocalisamfile doc(LF_DOC); TLocalisamfile rdoc(LF_RIGHEDOC); while (_msk->run()!= K_QUIT) { _solototali = _msk->get_bool(F_SOLOTOTALI); const int annoes = _msk->get_date(F_DATAFAT).year(); if (!controlli_preliminari()) { TString str; str << "Prima di poter eseguire la fatturazione è necessario correggere tutti gli errori segnalati.\n" << "Si prega di controllare i dati di configurazione."; warning_box(str); return; } _log = new TLog_report("Fatturazione"); if (_msk->get_bool(F_SAVEDATA)) { TFilename src = firm2dir(-1); TFilename dst = ini_get_string(CONFIG_DITTA, "lv", "Backup"); copy_tree(src, dst); } //leggo i dati di primo interesse const TString4 mskzona = _msk->get(F_CODZONA); const TString4 mskcat = _msk->get(F_CODCATC); //preparo le date estremi (dal - al) della query e l'anno dell'esercizio TDate al = _msk->get_date(F_ADATA); //se la data "al" non è corretta, la pongo uguale alla data fattura if (!al.ok()) al = _msk->get_date(F_DATAFAT); const long year = al.year(); TDate dal = _msk->get_date(F_DADATA); //se la data "dal" non è corretta, la pongo uguale a 1/1/annoes if (!dal.ok()) { dal.set_day(1); dal.set_month(1); dal.set_year(year); } //instanzio una TFatturaziome_lavanderie TFatturazione_lavanderie elab(_msk->get(F_COD_ELAB), prova); //preparo le variabili di interesse TLista_documenti docsin; TLista_documenti docsout; long lastcli = 0; const int period = _msk->get_int(F_PERFAT); const TDate datafat = _msk->get_date(F_DATAFAT); long indsped; TToken_string tipi; TToken_string stati; TString stato_min("Z"); elab.last_cli_damn() = -1L; elab.cli_damn() = 0; elab.art_damn() = 0; elab.tipi_stati_iniziali(tipi, stati); for (const char * s = stati.get(); s > " "; s = stati.get()) if (stato_min > s) stato_min = s; //preparo la query TString query; const TString& fromcod = _msk->get(F_DACODCF); const TString& tocod = _msk->get(F_ACODCF); //&&(BETWEEN(DATADOC,#DADATA,#ADATA))&&(STATO==\"2\")&&(TIPODOC==\"B01\") query << "USE DOC KEY 3 SELECT (TIPOCF==\"C\")&&" << "STR(BETWEEN(CODCF,\"" << fromcod << "\",\"" << tocod << "\"))\n" << "BY TIPOCF CODCF DATADOC\n" << "FROM DATADOC=#DAL PROVV=D ANNO=" << year << "\n" << "TO DATADOC=#AL PROVV=D ANNO=" << year << "\n"; // query << "USE DOC KEY 2 SELECT BETWEEN(DATADOC,#DADATA,#ADATA)&&STATO==\"2\")&&(TIPODOC==\"B01\")\n" // << "FROM " << "TIPOCF=C PROVV=D ANNO=#ANNO DATADOC=#DADATA \n" // << "TO " << "TIPOCF=C PROVV=D ANNO=#ANNO DATADOC=#ADATA \n"; //instanzio il recordset011 TISAM_recordset recset(query); recset.set_var("#DAL", dal); recset.set_var("#AL", al); TProgind pi(recset.items(), TR("Fatturazione"), true, true); long last_clifo = 0; int numdocgen = 0; int numdocscart = 0; bool space = true; real totimp; real imposta; real totdoc; real spese; TToken_string key; //TAssoc_array dei clienti per cui ho generato dei documenti TAssoc_array cliela; //scorro tutti documenti che la query mi restiuisce for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { //leggo il codcf const long clifo = recset.get(DOC_CODCF).as_int(); if (clifo != last_clifo) { key.format("C|%ld", clifo); TString str; str << TR("Cliente") << ' ' << clifo << ' ' << cache().get(LF_CLIFO, key, CLI_RAGSOC); pi.set_text(str); last_clifo=clifo; } if (!pi.addstatus(1)) break; //se non è l'ultimo cliente, allora: if (clifo != lastcli) { //se effettivamente devo elaborare delle bolle per questo cliente, allora: if (docsin.items()!= 0) { //elaboro tutti i documenti, li salvo nei file di Campo e svuoto le TList_file elab.put("B15", 'X'); elab.elabora(docsin, docsout, datafat); const int items = docsout.items(); if (items > 0) { if (!_solototali) docsout.write(); numdocgen += items; TString8 tmp; tmp << lastcli; cliela.add(tmp, tmp); } else if (!_solototali && docsout.items() == 0) //il messaggio deve comparire solo se non ho generato fatture { key.format("C|%ld", lastcli); TString str; str << "Cli. " << lastcli << ' ' << cache().get(LF_CLIFO, key, CLI_RICALT) << " non ha generato la fattura pur avendo bolle"; _log->log(0, str); numdocscart++; } //solo totali if(_solototali) { for (int i = 0; i < items; i++) { const TDocumento & doc = docsout[i]; totimp += doc.imponibile(); imposta += doc.imposta(); totdoc += doc.totale_doc(); spese += doc.spese(); } } docsout.destroy(-1); if (!_solototali) docsin.rewrite(); docsin.destroy(-1); } lastcli = clifo; space = true; } //preparo la chiave e recupero da CFVEN i dati di quel cliente key.format("C|%ld", clifo); const TRectype& clienti = cache().get(LF_CFVEN,key); const TRectype& docrec = recset.cursor()->curr(); const TRectype& clirec = cache().get(LF_CLIFO,key); //se il documento che sto analizzando è corretto, allora: bool cliok = elab.is_document_ok(docrec); if (cliok) { //se il codice di zona è pieno, allora: if (mskzona.full()) { //leggo il codice di zona standard di quel cliente e lo confronto con quello della maschera (V o F) const TString& codzona = clienti.get(CFV_CODZONA); cliok = (codzona == mskzona); } //se il codice categoria economica è pieno e ho passato il test sul codice di zona, allora: if (cliok && mskcat.full()) { //leggo il codice categoria economica standard di quel cliente e lo confronto con quello della maschera (V o F) const TString& codcat = clienti.get(CFV_CODCATC); cliok = (codcat == mskcat); } } else if (!_solototali && elab.is_document_compatible(docrec) && docrec.get(DOC_STATO) < stato_min) { if (space) //_log->log(0, ""); space = false; TString msg; msg << "Cli. " << clifo << ' ' << clirec.get(CLI_RICALT) << " Bolla n. " << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " in stato " << docrec.get(DOC_STATO); _log->log(0, msg); } //se ho passato tutti e due i test, allora: if (cliok) { //cerco sul contratto qual'è il periodo di fatturazione di quel cliente indsped = recset.get(DOC_CODINDSP).as_int(); TLaundry_contract contr(clifo, indsped, datafat); if(!contr.ok()) { TString msg; msg << TR("Non ci sono contratti in essere per il cliente ") << clifo << " " << clirec.get(CLI_RICALT) << TR(" in data ") << datafat.string(); _log->log(0, msg); } const int contrper = contr.get_int(LVCONDV_PERFAT); //se il cliente non è sospeso e se si è nel periodo di fatturazione giusto, aggiungo il documento alla //lista dei documenti da elaborare if (!contr.get_bool(LVCONDV_FATTSOSP) && contrper <= period) { TDocumento * doc = new TDocumento(recset.cursor()->curr()); if (agghead && !_solototali && doc->get(DOC_CODNUM) == num_buoni && doc->tipo().codice() == tipo_buoni) { bool doc_updated = false; // banche key.cut(0); key.add(clirec.get(CLI_TIPOCF)); key.add(clirec.get(CLI_CODCF)); key.add("V"); key.add("1"); const TRectype & cfban = cache().get(LF_CFBAN, key); TString8 abi; TString8 cab; TString iban; if (cfban.empty()) { abi = clirec.get(CLI_CODABI); cab = clirec.get(CLI_CODCAB); iban = clirec.get(CLI_IBAN); } else { abi = cfban.get(CFBAN_ABI); cab = cfban.get(CFBAN_CAB); iban = cfban.get(CFBAN_IBAN); } if (cab.full() && cab != "00000") { doc_updated |= (doc->get(DOC_CODABIA) != abi) || (doc->get(DOC_CODCABA) != cab); doc->put(DOC_CODABIA, abi); doc->put(DOC_CODCABA, cab); doc->put(DOC_IBAN, iban); } key.cut(0); key.add(clirec.get(CLI_TIPOCF)); key.add(clirec.get(CLI_CODCF)); key.add("N"); key.add("1"); const TRectype & cfbanpr = cache().get(LF_CFBAN, key); int progbnp = 0; if (cfbanpr.empty()) { abi = clienti.get(CFV_CODABIPR); cab = clienti.get(CFV_CODCABPR); } else { abi = cfbanpr.get(CFBAN_ABI); cab = cfbanpr.get(CFBAN_CAB); progbnp = cfbanpr.get_int(CFBAN_PROGPR); } if (cab.full() && cab != "00000") { doc_updated |= (doc->get(DOC_CODABIP) != abi) || (doc->get(DOC_CODCABP) != cab); doc->put(DOC_CODABIP, abi); doc->put(DOC_CODCABP, cab); doc->put(DOC_PROGBNP, progbnp); } const TString8 codpag = clirec.get(CLI_CODPAG); if (codpag.full()) { doc_updated |= (doc->get(DOC_CODPAG) != codpag); doc->put(DOC_CODPAG, codpag); } const TString8 spinc = clienti.get(CFV_PERCSPINC); if (spinc.full()) { doc_updated |= (doc->get(DOC_PERCSPINC) != spinc); doc->put(DOC_PERCSPINC, spinc); } const bool addbolli = clienti.get_bool(CFV_ADDBOLLI); doc_updated |= (doc->get_bool(DOC_ADDBOLLI) != addbolli); doc->put(DOC_ADDBOLLI, addbolli); const TString agente1 = clienti.get(CFV_CODAG1); if (agente1.full()) { doc_updated |= (doc->get(DOC_CODAGVIS) != agente1); doc->put(DOC_CODAGVIS, agente1); } if (doc_updated) { if (space) //_log->log(0, ""); space = false; TString msg(" Cli."); msg << clifo << " " << clirec.get(CLI_RICALT) << "Bolla " << docrec.get(DOC_CODNUM) << ' ' << docrec.get(DOC_TIPODOC) << ' ' << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " aggiornata la testata "; _log->log(0, msg); } } for (int r = 1; !_solototali && r <= doc->physical_rows(); r++) { const TRiga_documento& rdoc = (*doc)[r]; const TString80 codart = rdoc.get(RDOC_CODARTMAG); if (codart.full()) { const TRectype & rcont = contr.row(codart); const TArticolo_lavanderie& art = cached_article_laundry(codart, 'C', clifo, use_indsp ? indsped : 0); //estraggo il record corrispondente su LF_CLIFOGIAC const TRecmag_lavanderie& rec = art.find_rec(annoes); if (space) //_log->log(0, ""); space = false; TString str; str << "Cli." << clifo << ' ' << clirec.get(CLI_RICALT) << " Bolla " << docrec.get(DOC_CODNUM) << ' ' << docrec.get(DOC_TIPODOC) << ' ' << docrec.get(DOC_NDOC) << " del " << docrec.get(DOC_DATADOC) << " art." << codart << " - "; if (rec.get_real("DOTOD") < ZERO) { TString msg; msg << str << " Dot.odier.negativa"; _log->log(0, msg); } if (rec.get_real("DOTIN") < ZERO) { TString msg; msg << str << " Dot.iniz.negativa"; _log->log(0, msg); } bool prezzo_nullo = false; if (prezzo_da_contratto) { // Segnalo prezzo nullo solo se il contratto non è ad importo fisso (07/11/2011) prezzo_nullo = rcont.get_real(LVRCONDV_PREZZO).is_zero() && contr.get_real(LVCONDV_IMPFIX).is_zero(); } else { prezzo_nullo = rdoc.get_real(RDOC_PREZZO).is_zero(); // Prezzo sulla bolla } if (prezzo_nullo) { const TString8 causale = rdoc.get(RDOC_CODAGG1); const TCausale_lavanderie& cau = cached_causale_lavanderie(causale); if (!cau.ignora_prezzo_zero()) // Segnalo anomalia solo se la causale lo prevede (07/11/2011) { TString msg; msg << str << " Prezzo zero "; if (prezzo_da_contratto) msg << "sul contratto"; else msg << "sulla bolla"; _log->log(0, msg); } } } } docsin.add(doc); } } } //se ho dei documenti in lista li elaboro e poi svuoto le TList_file if (docsin.items() != 0) { if (ini_get_bool(CONFIG_DITTA, "lv", "RifTest")) elab.put("B15", true); //forzo la descrizione abbreviata elab.elabora(docsin, docsout, datafat); const int items = docsout.items(); if (items > 0) { if (!_solototali) docsout.write(); numdocgen += items; TString tmp; tmp << lastcli; cliela.add(tmp, tmp); for (int i = 0; i < items; i++) { const TDocumento & doc = docsout[i]; totimp += doc.imponibile(); imposta += doc.imposta(); totdoc += doc.totale_doc(); spese += doc.spese(); } } else if (!_solototali) { if (space) //_log->log(0, ""); space = false; TString str; TToken_string key; key.add('C'); key.add(lastcli); str << "Cli." << lastcli << ' ' << cache().get(LF_CLIFO, key, CLI_RICALT) << " non ha generato la fattura pur avendo bolle"; _log->log(0, str); numdocscart++; } docsout.destroy(-1); if (!_solototali) docsin.rewrite(); docsin.destroy(-1); } genera_bolle_nolo(cliela, elab, numdocgen, totimp, imposta, totdoc, spese); numdocgen += elab.write_fatt_ragg(_solototali); TString str; const char* const parolapl = _solototali ? "generate" : "elaborate"; const char* const parolasi = _solototali ? "generata" : "elaborata"; switch (numdocgen) { case 0: str << "Non e' stata " << parolasi << " alcuna fattura"; break; case 1: str << "E' stata " << parolasi << " una fattura"; break; default: str << "Sono state " << parolapl << ' ' << numdocgen << " fatture"; break; } if (numdocgen <= 0) warning_box(str); else message_box(str); message_box(TR("Elaborazione terminata")); str = TR("Clienti Danneggati Articoli danneggiati"); _log->log(0, str); str.format(" %5d %5d", elab.cli_damn(), elab.art_damn()); _log->log(0, str); str = "Numero fatture Imponibile Imposta Totale Spese"; _log->log(0, str); str.format(" %5d", numdocgen); str << totimp.stringa(17) << imposta.stringa(16) << totdoc.stringa(15) << spese.stringa(17); _log->log(0, str); str = TR("Numero fatture scartate"); _log->log(0, str); str.format(" %5d", numdocscart); _log->log(0, str); _log->print_or_preview(); delete _log; } } int lv2500(int argc, char *argv[]) { TFatturazione_lav_app a; a.run (argc, argv, TR("Fatturazione lavanderie")); return TRUE; }