campo-sirio/ve/velib04a.cpp
alex 815b64014a Patch level : 10.0 814
Files correlati     : ve0.exe ve6.exe
Ricompilazione Demo : [ ]
Commento            :

Bug 0001703: Fatturazione Bolle (ve6)

Nella gestione dei riferimenti in testa non viene scritto il flagh descrizione lunga per cui non si vedono i riferimenti delle bolla dalla seconda in poi (seganalato da Servizi informatici (SIPAG))

Bug	0001702: Documenti interattivi (ve0)

Agguingere una elaborazione al tipodocumento in modo da poter effettuare delle operazioni all' atto della registrazione. (HABA)

Per utilizzarla correttamente chi la configura deve configurarei stati dell elaborazione perche' venga chiamata quand serve.

Modificata anche la lettura dell stato attivo per le provvigioni, da verificare ka genreazioe dell provvigioni.


git-svn-id: svn://10.65.10.50/branches/R_10_00@20953 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-10-06 11:41:48 +00:00

598 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);
_impminfat = real(ini_get_string(CONFIG_DITTA, "ve", "IMPMINFAT"));
}
TFatturazione_bolle::TFatturazione_bolle(const TRectype& rec)
: TElaborazione(rec)
{
TString cod(rec.get("CODTAB"));
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);
_impminfat = real(ini_get_string(CONFIG_DITTA, "ve", "IMPMINFAT"));
}
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);
rout.put(RDOC_DESCLUNGA, "X");
}
} //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;
TArray docrefs;
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();
TBit_array * row = (TBit_array *) docrefs.objptr(od);
if (row == NULL)
{
row = new TBit_array;
docrefs.add(row, od);
}
row->set(id);
}
post_process_input(doc_in);
const int tot = doc_out.items();
const TString4 codnum(codice_numerazione_finale());
real impminfat;
if (!interattivo && tot > 0)
{
impminfat = doc_out[0].clifor().vendite().get_real(CFV_IMPMINFAT);
if (impminfat == ZERO)
impminfat = _impminfat;
}
for (int i = tot - 1; i >=0; 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);
for (int i = tot - 1; i >=0; i--) // Forza tipo e numerazione documento.
{
TDocumento& d = doc_out[i];
if (!interattivo && impminfat > ZERO && d.totale_doc() <= impminfat)
{
doc_out.destroy(i);
TBit_array & row = (TBit_array &) docrefs[i];
for (int j = row.last_one(); j >= row.first_one(); j--)
if (row[j])
doc_in.destroy(j);
docrefs.destroy(i);
}
else
d.put("FATID", 0);
}
for (int id = 0; id < doc_in.items(); id++)
{
TDocumento& d = doc_in[id];
d.flush_rows();
}
return doc_out.items() > 0;
}