145ecbff09
Files correlati : ve0.exe ve6.ex Ricompilazione Demo : [ ] Commento Bugs 0001356 : Elaborazione differita per fatturazione di prova Ho inserito una nuova numerazione documenti F09 "fatturazione di prova" con il check di "numerazione provvisoria" un tipo documento "fatturazione di prova" F09 ho inserito una elaborazione differita che lascia le bolle B01 allo stato 2 ma crea un F09 quando vado a vedere le fatture F09 sono definitive e non provvisorie. Allego la parte tabellare git-svn-id: svn://10.65.10.50/trunk@19313 c028cbd2-c16b-5b4b-a496-9718f37d4682
586 lines
16 KiB
C++
Executable File
586 lines
16 KiB
C++
Executable File
#include "velib04.h"
|
|
|
|
#include <dongle.h>
|
|
#include <modaut.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TFatturazione bolle
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TFatturazione_bolle::TFatturazione_bolle(const char* cod)
|
|
: TElaborazione(cod)
|
|
{
|
|
TConfig c(CONFIG_DITTA, "ve");
|
|
TString16 name; name.format("AGGFLD(%s)", cod);
|
|
|
|
_lista_campi = c.get(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.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");
|
|
}
|
|
|
|
void TFatturazione_bolle::campi_raggruppamento_righe(TToken_string& campi_riga) const
|
|
{
|
|
const bool ragg_rig = raggruppa_righe();
|
|
|
|
if (ragg_rig)
|
|
{
|
|
campi_riga = "CODART|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("CODMAG");
|
|
if (riga_uguale(1)) campi_riga.add("CODIVA");
|
|
if (riga_uguale(2)) campi_riga.add("PREZZO|SCONTO");
|
|
|
|
}
|
|
}
|
|
|
|
void TFatturazione_bolle::campi_raggruppamento(TToken_string& campi) const
|
|
{
|
|
campi = "TIPOCF|CODCF|CODVAL|CODLIN"; // Uguali sempre
|
|
|
|
// Uguali opzionalmente
|
|
const char* cond[] = { "CAMBIO", "SCONTO", "TIPODOC", "CODNUM",
|
|
"CODPAG", "CODABIA|CODCABA", "CODLIST", "CODAG|CODAGVIS",
|
|
"CODSPMEZZO", "CODPORTO", "CAUSTRASP", "CODVETT1|CODVETT2|CODVETT3",
|
|
"CODINDSP", "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)
|
|
{
|
|
TRiga_documento rin(r);
|
|
|
|
const bool rindesc = rin.sola_descrizione(); // La riga di input e' descrittiva
|
|
if (ignora_desc && rindesc)
|
|
return;
|
|
if (rin.is_attrezzatura() || rin.is_risorsa())
|
|
{
|
|
const TSpesa_prest & risatt = rin.spesa();
|
|
const TString codprest(risatt.revenue());
|
|
|
|
if ( codprest.full())
|
|
{
|
|
const TSpesa_prest prest(codprest, RIGA_PRESTAZIONI);
|
|
rin.put(RDOC_TIPORIGA, "06");
|
|
rin.put(RDOC_CODART, prest.codice());
|
|
rin.put(RDOC_DESCR, prest.descrizione());
|
|
rin.put(RDOC_UMQTA, prest.um());
|
|
rin.put(RDOC_PREZZO, prest.prezzo());
|
|
rin.put(RDOC_CODIVA, prest.cod_iva());
|
|
}
|
|
}
|
|
|
|
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) // 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 (da_raggruppare(rin) && 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 (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())
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 (memo.full())
|
|
memo << " - ";
|
|
memo << riferimento;
|
|
|
|
if (memo.len() < rout.length(RDOC_DESCR))
|
|
rout.put(RDOC_DESCR, memo);
|
|
else
|
|
{
|
|
rout.put(RDOC_DESCR, memo.left(rout.length(RDOC_DESCR)));
|
|
rout.put(RDOC_DESCEST, memo.mid(rout.length(RDOC_DESCR)));
|
|
rout.put(RDOC_DESCLUNGA, "X");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
|
|
campi_raggruppamento_righe(campi_riga);
|
|
|
|
const bool ragg_rig = campi_riga.full();
|
|
|
|
for (int r = 1; r <= doc_in.physical_rows(); r++)
|
|
elabora_riga(doc_in[r], 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 (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)
|
|
{
|
|
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 (int i = 1; i <= rows; i++)
|
|
{
|
|
TRiga_documento& rdoc = campione[i];
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
const 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 TString8 tipodoc(d.tipo().codice());
|
|
TDocumento_mask m(tipodoc);
|
|
|
|
if (reload_prices())
|
|
{
|
|
const int rows = d.physical_rows();
|
|
|
|
for (int i = 1; i <= rows;i++)
|
|
d[i].zero(RDOC_CHECKED);
|
|
}
|
|
m.doc() = d;
|
|
m.doc2mask(true, true);
|
|
m.mask2doc();
|
|
d = m.doc();
|
|
}
|
|
}
|
|
post_process_output(doc_out);
|
|
return tot > 0;
|
|
}
|
|
|