1997-08-05 14:10:21 +00:00
|
|
|
#include "velib.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;
|
1998-08-25 18:07:30 +00:00
|
|
|
for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1998-08-25 18:07:30 +00:00
|
|
|
t = tipo_iniziale(i);
|
1997-08-05 14:10:21 +00:00
|
|
|
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);
|
1998-08-25 18:07:30 +00:00
|
|
|
for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1998-08-25 18:07:30 +00:00
|
|
|
const char s = stato_iniziale(i);
|
|
|
|
if (s != '\0')
|
1997-08-05 14:10:21 +00:00
|
|
|
stati.add(s);
|
|
|
|
}
|
|
|
|
CHECK(!stati.empty_items(), "Nessuno stato documento valido");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool TFatturazione_bolle::raggruppa(TDocumento& doc_in, TDocumento& doc_out)
|
|
|
|
{
|
|
|
|
#ifdef DBG
|
1998-08-25 18:07:30 +00:00
|
|
|
const TString16 tipodoc = doc_in.tipo().codice();
|
|
|
|
for (int i = 0; i < TElaborazione::_max_tipi_doc_elab; i++)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1998-08-25 18:07:30 +00:00
|
|
|
if (tipodoc == tipo_iniziale(i))
|
1997-08-05 14:10:21 +00:00
|
|
|
break;
|
|
|
|
}
|
1998-08-25 18:07:30 +00:00
|
|
|
if (i >= TElaborazione::_max_tipi_doc_elab)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
|
|
|
NFCHECK("Tipo documento non valido: '%s'", (const char*)tipodoc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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 (gestione_riferimenti())
|
|
|
|
{
|
|
|
|
// Determina ed eventualmente crea la riga di riferimento
|
1997-08-28 16:58:33 +00:00
|
|
|
const int riga_rif = riferimenti_in_testa() ? 1 : doc_out.physical_rows()+1;
|
|
|
|
if (riga_rif > doc_out.physical_rows())
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
|
|
|
TRiga_documento& rout = doc_out.new_row();
|
|
|
|
rout.forza_sola_descrizione();
|
|
|
|
}
|
|
|
|
|
|
|
|
TRiga_documento& rout = doc_out[riga_rif];
|
|
|
|
|
|
|
|
// Costruisce la stringa di riferimento
|
2002-12-20 16:15:03 +00:00
|
|
|
TString riferimento;
|
|
|
|
doc_in.riferimento(riferimento);
|
1997-08-05 14:10:21 +00:00
|
|
|
if (riferimento.empty())
|
|
|
|
riferimento = doc_in.tipo().descrizione();
|
2002-02-26 16:20:19 +00:00
|
|
|
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();
|
|
|
|
}
|
1997-08-05 14:10:21 +00:00
|
|
|
|
|
|
|
// Setta la descrizione se vuota
|
2003-12-15 14:25:45 +00:00
|
|
|
if (rout.get(RDOC_DESCR).empty())
|
|
|
|
rout.put(RDOC_DESCR, riferimento);
|
1997-08-05 14:10:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Altrimenti aggiungi il riferimento al memo
|
|
|
|
TString memo(1024);
|
2003-12-15 14:25:45 +00:00
|
|
|
memo = rout.get(RDOC_DESCEST);
|
1997-08-05 14:10:21 +00:00
|
|
|
if (memo.empty())
|
1998-08-25 18:07:30 +00:00
|
|
|
{
|
2003-12-15 14:25:45 +00:00
|
|
|
TString80 rif(rout.get(RDOC_DESCR));
|
1998-08-25 18:07:30 +00:00
|
|
|
rif << '\n';
|
2003-12-15 14:25:45 +00:00
|
|
|
rout.put(RDOC_DESCR, rif);
|
|
|
|
rout.put(RDOC_DESCLUNGA, "X");
|
1998-08-25 18:07:30 +00:00
|
|
|
}
|
1997-08-05 14:10:21 +00:00
|
|
|
else
|
|
|
|
memo << '\n';
|
|
|
|
memo << riferimento;
|
2003-12-15 14:25:45 +00:00
|
|
|
rout.put(RDOC_DESCEST, memo);
|
1997-08-05 14:10:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
1999-10-22 10:00:18 +00:00
|
|
|
|
|
|
|
TRiga_documento tmp(&doc_in);
|
1997-10-29 11:08:40 +00:00
|
|
|
for (int r = 1; r <= doc_in.physical_rows(); r++)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1999-10-22 10:00:18 +00:00
|
|
|
const TRiga_documento* rin = &doc_in[r];
|
|
|
|
const bool rindesc = rin->sola_descrizione(); // La riga di input e' descrittiva
|
1997-08-05 14:10:21 +00:00
|
|
|
if (ignora_desc && rindesc)
|
|
|
|
continue;
|
1999-10-22 10:00:18 +00:00
|
|
|
|
|
|
|
if (prezzo_da_ordine()) // Se devo copiare il prezzo originale all'ordine
|
|
|
|
{
|
|
|
|
const TRectype* row_ord = rin->find_original_rdoc();
|
|
|
|
if (row_ord != NULL)
|
|
|
|
{
|
|
|
|
tmp = *rin; rin = &tmp;
|
|
|
|
const real ord_price = row_ord->get(RDOC_PREZZO);
|
|
|
|
const TString ord_scont = row_ord->get(RDOC_SCONTO);
|
|
|
|
tmp.put(RDOC_PREZZO, ord_price);
|
|
|
|
tmp.put(RDOC_SCONTO, ord_scont);
|
|
|
|
}
|
|
|
|
}
|
1997-08-05 14:10:21 +00:00
|
|
|
|
|
|
|
bool elaborata = FALSE;
|
|
|
|
|
1999-04-06 15:34:39 +00:00
|
|
|
// Raggruppo le righe se e' settato il flag di raggruppamento e
|
1997-08-05 14:10:21 +00:00
|
|
|
// se la riga non contiene solo una descrizione
|
|
|
|
if (ragg_rig && !rindesc) // Se devo raggruppare le righe ...
|
|
|
|
{
|
1997-08-28 16:58:33 +00:00
|
|
|
const int last = doc_out.physical_rows();
|
1997-08-05 14:10:21 +00:00
|
|
|
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;
|
1999-10-22 10:00:18 +00:00
|
|
|
|
|
|
|
if (rin->raggruppabile(rout, campi_riga)) // Se esiste una riga compatibile ...
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1999-10-22 10:00:18 +00:00
|
|
|
rout += *rin; // ... sommaci la quantita' ecc.
|
1997-08-05 14:10:21 +00:00
|
|
|
elaborata = TRUE; // Ricorda di averla gia' elaborata
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!elaborata) // Se la riga non e' stata gia' sommata ...
|
|
|
|
{
|
1999-04-06 15:34:39 +00:00
|
|
|
TRiga_documento& rout = doc_out.new_row(); // ... crea una riga nuova e
|
1999-10-22 10:00:18 +00:00
|
|
|
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
|
1997-08-05 14:10:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TFatturazione_bolle::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
|
1998-06-10 16:38:58 +00:00
|
|
|
const TDate& data_elab, bool interattivo)
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
|
|
|
bool ok = TRUE;
|
|
|
|
|
|
|
|
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",
|
1998-08-25 18:07:30 +00:00
|
|
|
"CODSPMEZZO", "CODPORTO", "CAUSTRASP", "CODVETT1|CODVETT2|CODVETT3",
|
|
|
|
"CODINDSP",
|
1997-08-05 14:10:21 +00:00
|
|
|
NULL };
|
1998-06-10 16:38:58 +00:00
|
|
|
|
1997-08-05 14:10:21 +00:00
|
|
|
for (int u = 0; cond[u]; u++)
|
|
|
|
if (doc_uguale(u)) campi_doc.add(cond[u]);
|
|
|
|
|
|
|
|
for (int id = 0; id < doc_in.items() && ok; id++)
|
|
|
|
{
|
|
|
|
TDocumento& campione = doc_in[id];
|
|
|
|
const int tot = doc_out.items();
|
|
|
|
int od = tot;
|
|
|
|
|
1998-06-10 16:38:58 +00:00
|
|
|
if (interattivo)
|
|
|
|
{
|
|
|
|
od = 0;
|
|
|
|
const TString16 tipo(campione.get(DOC_TIPOCF));
|
1999-10-22 10:00:18 +00:00
|
|
|
const long codice = campione.get_long(DOC_CODCF);
|
|
|
|
|
1998-06-10 16:38:58 +00:00
|
|
|
if (tipo != doc_out[od].get(DOC_TIPOCF) ||
|
|
|
|
codice != doc_out[od].get_long(DOC_CODCF))
|
1999-10-22 10:00:18 +00:00
|
|
|
return error_box("Documenti incompatibili : cliente/fornitore diverso");
|
1998-06-10 16:38:58 +00:00
|
|
|
}
|
|
|
|
else
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1998-06-10 16:38:58 +00:00
|
|
|
if (campione.raggruppabile()) // Se il documento ha il flag di raggruppabilita' ...
|
1997-08-05 14:10:21 +00:00
|
|
|
{
|
1999-04-26 15:58:05 +00:00
|
|
|
for (od = 0; od < tot; od++) // ... cerca un documento compatibile.
|
|
|
|
{
|
|
|
|
if (campione.raggruppabile(doc_out[od], campi_doc))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1997-08-05 14:10:21 +00:00
|
|
|
}
|
2000-05-05 15:25:49 +00:00
|
|
|
|
1997-08-05 14:10:21 +00:00
|
|
|
if (od >= tot) // Se non ho trovato un documento compatibile ...
|
|
|
|
{ // ... creane uno nuovo (certamente compatibile)
|
|
|
|
const char provv = tipo_numerazione();
|
1999-10-22 10:00:18 +00:00
|
|
|
// const int anno = campione.anno();
|
|
|
|
const int anno = data_elab.year();
|
1997-08-29 13:19:59 +00:00
|
|
|
// const TString codnum = codice_numerazione_finale();
|
|
|
|
const TString16 codnum(campione.get("CODNUM"));
|
2000-05-05 15:25:49 +00:00
|
|
|
const TString16 tipo_out(get("S8")); // Tipo del documento di output
|
|
|
|
|
1997-08-05 14:10:21 +00:00
|
|
|
TDocumento* new_doc = new TDocumento(provv, anno, codnum, -1);
|
2000-05-05 15:25:49 +00:00
|
|
|
|
|
|
|
// 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
|
1997-08-05 14:10:21 +00:00
|
|
|
|
|
|
|
new_doc->put("DATADOC", data_elab);
|
|
|
|
|
|
|
|
// Aggiungilo alla lista dei documenti in uscita
|
|
|
|
od = doc_out.add(new_doc);
|
|
|
|
}
|
1999-06-18 15:35:05 +00:00
|
|
|
|
1997-08-05 14:10:21 +00:00
|
|
|
ok = raggruppa(campione, doc_out[od]);
|
1999-06-18 15:35:05 +00:00
|
|
|
|
|
|
|
campione.flush_rows();
|
1997-08-29 13:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const int tot = doc_out.items();
|
|
|
|
const TString codnum(codice_numerazione_finale());
|
2000-05-05 15:25:49 +00:00
|
|
|
const TString16 tipo_out(get("S8")); // Tipo del documento di output
|
1997-08-29 13:19:59 +00:00
|
|
|
|
2000-05-05 15:25:49 +00:00
|
|
|
for (int i = 0; i < tot; i++) // Forza tipo e numerazione documento.
|
1997-08-29 13:19:59 +00:00
|
|
|
{
|
|
|
|
TDocumento & d = doc_out[i];
|
|
|
|
d.put("CODNUM", codnum);
|
1999-10-22 10:00:18 +00:00
|
|
|
|
|
|
|
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));
|
2000-05-05 15:25:49 +00:00
|
|
|
|
|
|
|
TRecfield td(d, DOC_TIPODOC); // Uso il TRecfield per scavalcare tutti gli automatismi
|
2000-10-03 13:45:12 +00:00
|
|
|
#ifdef DBG
|
|
|
|
real tot = d.totale_doc();
|
|
|
|
#endif
|
2000-05-05 15:25:49 +00:00
|
|
|
td = tipo_cli.empty() ? tipo_out : tipo_cli;
|
2000-10-03 13:45:12 +00:00
|
|
|
TString16 sconto(d.get(DOC_SCONTOPERC));
|
|
|
|
d.put(DOC_SCONTOPERC, sconto);
|
|
|
|
#ifdef DBG
|
|
|
|
tot = d.totale_doc();
|
|
|
|
#endif
|
1997-08-29 13:19:59 +00:00
|
|
|
}
|
1997-08-05 14:10:21 +00:00
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2002-05-31 10:35:40 +00:00
|
|
|
|