campo-sirio/ve/velib04a.cpp
luca b93d973499 Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :


git-svn-id: svn://10.65.10.50/trunk@20611 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-06-22 09:36:11 +00:00

573 lines
17 KiB
C++
Executable File

#include <cfven.h>
#include "velib04.h"
#include <dongle.h>
#include <modaut.h>
///////////////////////////////////////////////////////////
// TFatturazione bolle
///////////////////////////////////////////////////////////
TFatturazione_bolle::TFatturazione_bolle(const char* cod)
: TElaborazione(cod)
{
TString80 name; name.format("AGGFLD(%s)", cod);
_lista_campi = ini_get_string(CONFIG_DITTA, "ve", name);
name.format("ROWSORT(%s)", cod);
_rowsort = ini_get_string(CONFIG_DITTA, "ve", name);
}
void TFatturazione_bolle::tipi_validi(TToken_string& tipi) const
{
tipi.cut(0);
TString4 t;
for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++)
{
t = tipo_iniziale(i);
if (t.full())
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");
}
void TFatturazione_bolle::campi_raggruppamento_righe(TToken_string& campi_riga) const
{
const bool ragg_rig = raggruppa_righe();
if (ragg_rig)
{
campi_riga = RDOC_CODART"|"RDOC_UMQTA; // Uguali sempre
// 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)) campi_riga.add(RDOC_PREZZO"|"RDOC_SCONTO);
}
else
campi_riga.cut(0);
}
void TFatturazione_bolle::campi_raggruppamento(TToken_string& campi) const
{
campi = DOC_TIPOCF"|"DOC_CODCF"|"DOC_CODVAL"|"DOC_CODLIN; // Uguali sempre
// Uguali opzionalmente
const char* cond[] = { DOC_CAMBIO, "SCONTO", DOC_TIPODOC, DOC_CODNUM,
DOC_CODPAG, DOC_CODABIA"|"DOC_CODCABA, DOC_CODLIST, DOC_CODAG"|"DOC_CODAGVIS,
DOC_CODSPMEZZO, DOC_CODPORTO, DOC_CAUSTRASP, DOC_CODVETT1"|"DOC_CODVETT2"|"DOC_CODVETT3,
DOC_CODINDSP, DOC_CODCMS,
NULL };
for (int u = 0; cond[u]; u++)
if (doc_uguale(u)) campi.add(cond[u]);
}
bool TFatturazione_bolle::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;
return doc_in.raggruppabile(doc_out, campi);
}
void TFatturazione_bolle::create_row(TDocumento& doc_out, const TRiga_documento& rin)
{
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_data_consegna())
{
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);
}
}
}
void TFatturazione_bolle::elabora_riga(TRiga_documento& r, TDocumento& doc_out, bool usa_dcons, bool ragg_rig, bool ignora_desc,
TToken_string & campi_riga, const TDate & dcons, const TDate & ddoc)
{
const bool rindesc = r.sola_descrizione(); // La riga di input e' descrittiva
if (ignora_desc && rindesc)
return;
TRiga_documento rin(r);
if (rin.is_attrezzatura() || rin.is_risorsa())
rin.cost2revenue();
const bool delete_spese_aut = r.doc().tipo().spese_aut() && doc_out.rows() > 0;
if (delete_spese_aut)
{
if (rin.is_generata() && rin.get("GENTIPO").empty() && rin.is_spese())
{
const TSpesa_prest& sp = rin.spesa();
if (sp.tipo() == 'P')
return;
}
} //if(delete_spese_aut)..
if (usa_dcons)
{
TDate data_cons = rin.get(RDOC_DATACONS);
if (!data_cons.ok())
data_cons = dcons;
if (ddoc < data_cons || rin.get_bool(RDOC_RIGAEVASA))
return;
const real q = rin.get(RDOC_QTA);
r.put(RDOC_QTAEVASA, q);
r.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 && da_raggruppare(rin)) // Se devo raggruppare le righe ...
{
FOR_EACH_PHYSICAL_RDOC(doc_out, r, rout) // ... cerca una riga compatibile
{
if (rout->sola_descrizione()) // Ignora le righe descrittive
continue;
if (rin.raggruppabile(*rout, campi_riga)) // Se esiste una riga compatibile ...
{
add_rows(*rout, rin);
elaborata = true; // Ricorda di averla gia' elaborata
break;
}
}
}
if (!elaborata) // Se la riga non e' stata gia' sommata ...
create_row(doc_out, rin);
}
bool TFatturazione_bolle::raggruppa(TDocumento& doc_in, TDocumento& doc_out)
{
#ifdef DBG
const TString4 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 bool usa_dcons = usa_data_consegna();
const int doc_out_rows = doc_out.physical_rows();
if (usa_dcons)
{
bool da_elaborare = FALSE;
FOR_EACH_PHYSICAL_RDOC(doc_in, r, rin)
{
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;
}
if (gestione_riferimenti())
{
if (change_clifo())
{
const int indsped = doc_in.get_int(DOC_CODINDSP);
if (indsped > 0)
{
const char t = doc_in.get_char(DOC_TIPOCFFATT);
const long codcf = doc_in.get_long(DOC_CODCFFATT);
TString16 kis; kis << t << '|' << codcf << '|' << indsped;
const TString& dest = cache().get(LF_INDSP, kis, IND_RAGSOC);
if (dest.full()) // crea una riga descrizione nuova per indirizzo di spedizione valido
{
TRiga_documento& rout = doc_out.new_row();
rout.forza_sola_descrizione();
rout.put(RDOC_DESCR, dest);
}
} //if(indsped)...
} //if(change_clifo)...
// Determina ed eventualmente crea la riga di riferimento
const bool rif_testa = riferimenti_in_testa();
const bool rif_packed = pack_rif();
const int riga_rif = rif_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;
if (!rif_testa || !rif_packed || doc_out_rows == 0)
{
doc_in.riferimento(riferimento);
if (riferimento.empty())
riferimento = doc_in.tipo().descrizione();
if (riferimento.full())
riferimento << ' ';
}
if (usa_doc_rif() && doc_in.get(DOC_NUMDOCRIF).not_empty())
{
riferimento << "n. " << doc_in.get(DOC_NUMDOCRIF);
if (rif_packed)
riferimento << ' ' << doc_in.get_date(DOC_DATADOCRIF).string(brief);
else
riferimento << " del " << doc_in.get(DOC_DATADOCRIF);
}
else
{
riferimento << " n. " << doc_in.numero();
if (rif_packed)
riferimento << ' ' << doc_in.data().string(brief);
else
riferimento << " del " << doc_in.data().string();
}
// Setta la descrizione se vuota
if (rif_packed)
{
TString memo(1024);
memo = rout.get(RDOC_DESCR);
if (rout.get_bool(RDOC_DESCLUNGA))
memo << rout.get(RDOC_DESCEST);
if (riferimento.full())
{
if (memo.full())
memo << " - ";
memo << riferimento;
}
const int maxlen = rout.length(RDOC_DESCR);
if (memo.len() < maxlen)
rout.put(RDOC_DESCR, memo);
else
{
rout.put(RDOC_DESCR, memo.left(maxlen));
rout.put(RDOC_DESCEST, memo.mid(maxlen));
rout.put(RDOC_DESCLUNGA, true);
}
}
else //else if(rif_packed)...
{
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);
memo.rtrim();
memo << '\n' << riferimento;
rout.put(RDOC_DESCEST, memo);
}
} //if(rif_packed)..
} //if(gestione_riferimenti)...
const bool ignora_desc = ignora_descrizioni() && !doc_in.clifor().vendite().get_bool(CFV_RIFDOC);
TToken_string campi_riga(80);
campi_raggruppamento_righe(campi_riga);
const bool ragg_rig = campi_riga.full();
FOR_EACH_PHYSICAL_RDOC(doc_in, r, rin)
elabora_riga(*rin, doc_out, usa_dcons, ragg_rig, ignora_desc, campi_riga, dcons, ddoc);
//cambio stato documento
bool cambia_stato_doc_in = true;
if (usa_dcons)
{
FOR_EACH_PHYSICAL_RDOC(doc_in, r, rin)
{
if (!rin->sola_descrizione() && !rin->get_bool(RDOC_RIGAEVASA)) // Perche' non rin->is_evasa()
{
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)
{
TWait_cursor hourglass;
TToken_string campi_doc(128); // Lista di campi che devono essere uguali
TBit_array closed;
campi_raggruppamento(campi_doc);
pre_process_input(doc_in);
for (int id = 0; id < doc_in.items(); id++)
{
TDocumento& campione = doc_in[id];
const char orig_t = campione.get_char(DOC_TIPOCF);
const long orig_cod = campione.get_long(DOC_CODCF);
if (change_clifo())
{
const char t = campione.get_char(DOC_TIPOCFFATT);
const long codcf = campione.get_long(DOC_CODCFFATT);
if (t > ' ')
{
campione.put(DOC_TIPOCF, t);
if (interattivo)
doc_out[0].put(DOC_TIPOCF, t);
}
if (codcf > 0L)
{
campione.put(DOC_CODCF, codcf);
if (interattivo)
doc_out[0].put(DOC_CODCF, codcf);
}
}
if (_lista_campi.full())
{
TToken_string s("", '=');
for (s = _lista_campi.get(0); s.full(); s = _lista_campi.get())
{
TString16 oname(s.get());
TString16 iname(s.get());
if (oname == RDOC_CODIVA)
{
const int rows = campione.physical_rows();
const TString8 codesiva = campione.codesiva();
FOR_EACH_PHYSICAL_RDOC(campione, i, rdoc)
{
if (codesiva.full())
rdoc->put(RDOC_CODIVA, codesiva);
else
{
if (rdoc->is_articolo())
{
const TArticolo_giacenza & art = rdoc->articolo();
const TString8 codiva = art.get(ANAMAG_CODIVA);
if (codiva.full())
rdoc->put(RDOC_CODIVA, codiva);
}
else
if ((rdoc->is_spese() || rdoc->is_prestazione()))
{
const TSpesa_prest & s = rdoc->spesa();
const TString8 codiva = s.cod_iva();
if (codiva.full())
rdoc->put(RDOC_CODIVA, codiva);
}
}
}
}
else
{
if (iname.blank())
iname = oname;
if (iname.starts_with("17."))
campione.put(oname, campione.clifor().vendite().get(iname.mid(3)));
else
if (iname.starts_with("CFVEN."))
campione.put(oname, campione.clifor().vendite().get(iname.mid(6)));
else
campione.put(oname, campione.clifor().get(iname));
}
}
}
campione.set_riga_esenzione();
const int tot = doc_out.items();
int od = tot;
if (interattivo)
{
od = 0;
const char tipo = campione.get_char(DOC_TIPOCF);
const long codice = campione.get_long(DOC_CODCF);
TDocumento & out = doc_out[od];
if (tipo != out.get_char(DOC_TIPOCF) ||
codice != out.get_long(DOC_CODCF))
return error_box("Documenti incompatibili: cliente/fornitore diverso");
const TString4 codnum(out.get(DOC_CODNUM));
if (cached_numerazione(codnum).num_provv())
out.put(DOC_PROVV, 'P');
}
else
{
if (doc_raggruppabile(campione)) // Se il documento ha il flag di raggruppabilita' ...
{
for (od = 0; od < tot; od++) // ... cerca un documento compatibile.
{
if (!closed[od])
{
const int in_rows = campione.rows();
const int out_rows = doc_out[od].rows();
if (in_rows + out_rows > 990)
closed.set(od);
else
{
if (doc_raggruppabili(campione, doc_out[od], campi_doc))
break;
}
}
}
}
}
if (od >= tot) // Se non ho trovato un documento compatibile ...
{ // ... creane uno nuovo (certamente compatibile)
const int anno = data_elab.year();
const TString4 codnum(campione.get(DOC_CODNUM));
const TString4 tipo_out(get("S8")); // Tipo del documento di output
char provv = 'D';
if (cached_numerazione(codice_numerazione_finale()).num_provv())
provv = 'P';
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(DOC_DATADOC, data_elab);
// Aggiungilo alla lista dei documenti in uscita
od = doc_out.add(new_doc);
new_doc->put("FATID", od + 1);
}
if (change_clifo())
{
campione.put(DOC_TIPOCF, orig_t);
campione.put(DOC_CODCF, orig_cod);
}
if (!raggruppa(campione, doc_out[od]) && doc_out[od].physical_rows() == 0)
doc_out.destroy(od);
else
doc_out[od].set_riga_esenzione();
campione.flush_rows();
}
post_process_input(doc_in);
int tot = doc_out.items();
const TString4 codnum(codice_numerazione_finale());
for (int i = 0; i < tot; i++) // Forza tipo e numerazione documento.
{
TDocumento& d = doc_out[i];
d.put(DOC_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 TString4 tipo_cli(cfven.get(CFV_TIPODOCFAT));
const TString& tipo_out = get_tipo_out(d); // Tipo del documento di output
TRecfield td(d, DOC_TIPODOC); // Uso il TRecfield per scavalcare tutti gli automatismi
td = tipo_cli.empty() ? tipo_out : tipo_cli;
const TString& sconto = d.get(DOC_SCONTOPERC);
d.put(DOC_SCONTOPERC, sconto);
if (change_clifo())
{
const TString4 tipodoc(d.tipo().codice());
TDocumento_mask m(tipodoc);
if (reload_prices())
{
FOR_EACH_PHYSICAL_RDOC_BACK(d, r, rdoc)
rdoc->zero(RDOC_CHECKED);
}
m.doc() = d;
m.doc2mask(true, true);
m.mask2doc();
d = m.doc();
}
if (_rowsort.full())
d.sort_rows(_rowsort);
}
post_process(doc_out, doc_in);
tot = doc_out.items();
for (int i = 0; i < tot; i++) // Forza tipo e numerazione documento.
{
TDocumento& d = doc_out[i];
d.put("FATID", 0);
}
return tot > 0;
}