#include "velib04.h" /////////////////////////////////////////////////////////// // TFatturazione bolle /////////////////////////////////////////////////////////// TFatturazione_bolle::TFatturazione_bolle(const char* cod) : TElaborazione(cod) { } void TFatturazione_bolle::tipi_validi(TToken_string& tipi) const { tipi.cut(0); TString16 t; for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++) { t = tipo_iniziale(i); if (t.not_empty()) tipi.add(t); } CHECK(!tipi.empty_items(), "Nessun tipo documento valido"); } void TFatturazione_bolle::stati_validi(TToken_string& stati) const { stati.cut(0); for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++) { const char s = stato_iniziale(i); if (s != '\0') stati.add(s); } CHECK(!stati.empty_items(), "Nessuno stato documento valido"); } bool TFatturazione_bolle::raggruppa(TDocumento& doc_in, TDocumento& doc_out) { #ifdef DBG const TString16 tipodoc = doc_in.tipo().codice(); int i; for (i = 0; i < TElaborazione::_max_tipi_doc_elab; i++) { if (tipodoc == tipo_iniziale(i)) break; } if (i >= TElaborazione::_max_tipi_doc_elab) { NFCHECK("Tipo documento non valido: '%s'", (const char*)tipodoc); return TRUE; } #endif const TDate dcons = doc_in.get_date(DOC_DATACONS); const TDate ddoc = doc_out.get_date(DOC_DATADOC); const usa_dcons = usa_data_consegna(); if (usa_dcons) { bool da_elaborare = FALSE; for (int r = 1; !da_elaborare && r <= doc_in.physical_rows(); r++) { const TRiga_documento* rin = &doc_in[r]; TDate data_cons = rin->get_date(RDOC_DATACONS); if (!data_cons.ok()) data_cons = dcons; da_elaborare = ddoc >= data_cons && !rin->get_bool(RDOC_RIGAEVASA); } if (!da_elaborare) return FALSE; } //***vecchio posto cambio stato if (gestione_riferimenti()) { // Determina ed eventualmente crea la riga di riferimento const int riga_rif = riferimenti_in_testa() ? 1 : doc_out.physical_rows()+1; if (riga_rif > doc_out.physical_rows()) { TRiga_documento& rout = doc_out.new_row(); rout.forza_sola_descrizione(); } TRiga_documento& rout = doc_out[riga_rif]; // Costruisce la stringa di riferimento TString riferimento; doc_in.riferimento(riferimento); if (riferimento.empty()) riferimento = doc_in.tipo().descrizione(); if (usa_doc_rif() && doc_in.get(DOC_NUMDOCRIF).not_empty()) { riferimento << " n. " << doc_in.get(DOC_NUMDOCRIF); riferimento << " del " << doc_in.get(DOC_DATADOCRIF); } else { riferimento << " n. " << doc_in.numero(); riferimento << " del " << doc_in.data().string(); } // Setta la descrizione se vuota if (rout.get(RDOC_DESCR).empty()) rout.put(RDOC_DESCR, riferimento); else { // Altrimenti aggiungi il riferimento al memo TString memo(1024); memo = rout.get(RDOC_DESCEST); if (memo.empty()) { TString80 rif(rout.get(RDOC_DESCR)); rif << '\n'; rout.put(RDOC_DESCR, rif); rout.put(RDOC_DESCLUNGA, "X"); } else memo << '\n'; memo << riferimento; rout.put(RDOC_DESCEST, memo); } } const bool ignora_desc = ignora_descrizioni(); TToken_string campi_riga(80); const bool ragg_rig = raggruppa_righe(); if (ragg_rig) { campi_riga = "CODART|UMQTA"; // Uguali sempre // Uguali opzionalmente if (riga_uguale(0)) campi_riga.add("CODMAG"); if (riga_uguale(1)) campi_riga.add("CODIVA"); if (riga_uguale(2)) campi_riga.add("PREZZO|SCONTO"); } for (int r = 1; r <= doc_in.physical_rows(); r++) { TRiga_documento & rin = doc_in[r]; const bool rindesc = rin.sola_descrizione(); // La riga di input e' descrittiva if (ignora_desc && rindesc) continue; if (usa_dcons) { TDate data_cons = rin.get_date(RDOC_DATACONS); if (!data_cons.ok()) data_cons = dcons; if (ddoc < data_cons || rin.get_bool(RDOC_RIGAEVASA)) continue; real q = rin.get_real(RDOC_QTA); rin.put(RDOC_QTAEVASA, q); rin.put(RDOC_RIGAEVASA, true); } bool elaborata = FALSE; // Raggruppo le righe se e' settato il flag di raggruppamento e // se la riga non contiene solo una descrizione if (ragg_rig && !rindesc) // Se devo raggruppare le righe ... { const int last = doc_out.physical_rows(); for (int o = 1; o <= last; o++) // ... cerca una riga compatibile { TRiga_documento& rout = doc_out[o]; if (rout.sola_descrizione()) // Ignora le righe descrittive continue; if (rin.raggruppabile(rout, campi_riga)) // Se esiste una riga compatibile ... { rout += rin; // ... sommaci la quantita' ecc. elaborata = TRUE; // Ricorda di averla gia' elaborata break; } } } if (!elaborata) // Se la riga non e' stata gia' sommata ... { TRiga_documento& rout = doc_out.new_row(); // ... crea una riga nuova e doc_out.copy_data(rout, rin); // copiaci tutti i campi della riga sorgente. rout.set_original_rdoc_key(rin); // memorizza il codice della riga originale if (usa_dcons) { rout.zero(RDOC_QTAEVASA); rout.zero(RDOC_RIGAEVASA); } if (kill_descrizione_estesa()) // Cancello eventualmente la descrizione estesa { rout.zero(RDOC_DESCLUNGA); rout.zero(RDOC_DESCEST); } if (prezzo_da_ordine()) // Se devo copiare il prezzo originale all'ordine { const TRectype* row_ord = rin.find_original_rdoc(); if (row_ord != NULL) { const real ord_price = row_ord->get_real(RDOC_PREZZO); const TString ord_scont = row_ord->get(RDOC_SCONTO); rout.put(RDOC_PREZZO, ord_price); rout.put(RDOC_SCONTO, ord_scont); } } } } //cambio stato documento bool cambia_stato_doc_in = true; if (usa_dcons) { for (int r = 1; r <= doc_in.physical_rows(); r++) { const TRiga_documento & rin = doc_in[r]; if (!rin.sola_descrizione() && !rin.get_bool(RDOC_RIGAEVASA)) { cambia_stato_doc_in = false; break; } } } if (cambia_stato_doc_in) { const char stato_finale_in = get_char("S4"); doc_in.stato(stato_finale_in); } const char stato_finale_out = get_char("S9"); doc_out.stato(stato_finale_out); if (usa_dcons) doc_in.rewrite(); return TRUE; } bool TFatturazione_bolle::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out, const TDate& data_elab, bool interattivo) { TToken_string campi_doc(128); // Lista di campi che devono essere uguali campi_doc = "TIPOCF|CODCF|CODVAL|CODLIN"; // Uguali sempre // Uguali opzionalmente const char* cond[] = { "CAMBIO", "SCONTO", "TIPODOC", "CODNUM", "CODPAG", "CODABIA|CODCABA", "CODLIST", "CODAG", "CODSPMEZZO", "CODPORTO", "CAUSTRASP", "CODVETT1|CODVETT2|CODVETT3", "CODINDSP", NULL }; for (int u = 0; cond[u]; u++) if (doc_uguale(u)) campi_doc.add(cond[u]); for (int id = 0; id < doc_in.items(); id++) { TDocumento& campione = doc_in[id]; const int tot = doc_out.items(); int od = tot; if (interattivo) { od = 0; const TString16 tipo(campione.get(DOC_TIPOCF)); const long codice = campione.get_long(DOC_CODCF); if (tipo != doc_out[od].get(DOC_TIPOCF) || codice != doc_out[od].get_long(DOC_CODCF)) return error_box("Documenti incompatibili : cliente/fornitore diverso"); } else { if (campione.raggruppabile()) // Se il documento ha il flag di raggruppabilita' ... { for (od = 0; od < tot; od++) // ... cerca un documento compatibile. { if (campione.raggruppabile(doc_out[od], campi_doc)) break; } } } if (od >= tot) // Se non ho trovato un documento compatibile ... { // ... creane uno nuovo (certamente compatibile) const char provv = tipo_numerazione(); // const int anno = campione.anno(); const int anno = data_elab.year(); // const TString codnum = codice_numerazione_finale(); const TString16 codnum(campione.get("CODNUM")); const TString16 tipo_out(get("S8")); // Tipo del documento di output TDocumento* new_doc = new TDocumento(provv, anno, codnum, -1); // Attenzione! Il cambio del tipo documento provocherebbe il reset delle variabili // Per cui lo scrivo temporaneamente nel tipo del documento d'ingresso // TRecfield td(campione, DOC_TIPODOC); // Uso il TRecfield per scavalcare tutti gli automatismi // const TString16 old_tipo_in = td; // Salvo il vecchio tipo // td = tipo_out; // Setto il nuovo TDocumento::copy_data(new_doc->head(), campione.head()); // Copio la testata // td = old_tipo_in; // Ripristino il vecchio new_doc->put("DATADOC", data_elab); // Aggiungilo alla lista dei documenti in uscita od = doc_out.add(new_doc); } if (!raggruppa(campione, doc_out[od]) && doc_out[od].physical_rows() == 0) doc_out.destroy(od); campione.flush_rows(); } const int tot = doc_out.items(); const TString codnum(codice_numerazione_finale()); const TString16 tipo_out(get("S8")); // Tipo del documento di output for (int i = 0; i < tot; i++) // Forza tipo e numerazione documento. { TDocumento & d = doc_out[i]; d.put("CODNUM", codnum); TToken_string key; key.add(d.get(DOC_TIPOCF)); key.add(d.get(DOC_CODCF)); const TRectype & cfven = cache().get(LF_CFVEN, key); const TString16 tipo_cli(cfven.get(CFV_TIPODOCFAT)); TRecfield td(d, DOC_TIPODOC); // Uso il TRecfield per scavalcare tutti gli automatismi td = tipo_cli.empty() ? tipo_out : tipo_cli; TString16 sconto(d.get(DOC_SCONTOPERC)); d.put(DOC_SCONTOPERC, sconto); } return tot > 0; }