1529 lines
52 KiB
C++
Executable File
1529 lines
52 KiB
C++
Executable File
#include <applicat.h>
|
||
#include <automask.h>
|
||
#include <progind.h>
|
||
#include <reputils.h>
|
||
#include <utility.h>
|
||
|
||
#include "../cg/cg2101.h"
|
||
#include "../cg/cg2103.h"
|
||
#include "../cg/cgsaldac.h"
|
||
#include "../mg/movmag.h"
|
||
#include "../mg/rmovmag.h"
|
||
|
||
#include "halib.h"
|
||
#include "ha1250.h"
|
||
#include "ha1300a.h"
|
||
#include "ha1301a.h"
|
||
|
||
//funzione di ordinamento del file di upload una volta caricato in memoria
|
||
|
||
static TToken_string tipi_record("SU|VC|TF|RF|SI|BR|RC");
|
||
|
||
int ordina_upload(const TObject** o1, const TObject** o2)
|
||
{
|
||
const TString& s1 = *(TString*)*o1;
|
||
const TString& s2 = *(TString*)*o2;
|
||
|
||
//ordinatore dei record Testata e Riga fattura
|
||
if (s1[1] == 'F' && s2[1] == 'F')
|
||
{
|
||
TToken_string k[2];
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
const TString& rec = i == 0 ? s1 : s2;
|
||
TToken_string& key = k[i];
|
||
if (rec[0] == 'T')
|
||
{
|
||
key.add(rec.mid(14,2)); //anno
|
||
key.add(rec.mid(16,1)); //tipodoc
|
||
key.add(rec.mid(5,5)); //numdoc
|
||
}
|
||
else
|
||
{
|
||
key.add(rec.mid(14,2)); //anno
|
||
key.add(rec.mid(28,1)); //tipodoc
|
||
key.add(rec.mid(5,5)); //numdoc
|
||
key.add(rec.mid(29,5)); //codart
|
||
}
|
||
}
|
||
return k[0].compare(k[1]);
|
||
}
|
||
|
||
const int pos1 = tipi_record.get_pos(s1.left(2));
|
||
const int pos2 = tipi_record.get_pos(s2.left(2));
|
||
if (pos1 != pos2)
|
||
return pos1 - pos2;
|
||
|
||
return s1.compare(s2);
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------
|
||
// Hardy_upload_recordset: serve per l'INPUT
|
||
//------------------------------------------------------------
|
||
class THardy_upload_recordset : public THardy_recordset
|
||
{
|
||
public:
|
||
virtual TRecnotype new_rec(const char* trc);
|
||
THardy_upload_recordset(const TFilename& filename);
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////
|
||
// Recordset specifici per i dati da trasferire INPUT
|
||
/////////////////////////////////////////////////////////////
|
||
|
||
TRecnotype THardy_upload_recordset::new_rec(const char* trc)
|
||
{
|
||
if (trc && *trc > ' ')
|
||
{
|
||
TString rec; rec << trc << "\r\n";
|
||
return TText_recordset::new_rec(rec);
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
//questo invece <20> il metodo magico che vale per il caricamento da file esterno
|
||
THardy_upload_recordset::THardy_upload_recordset(const TFilename& filename)
|
||
: THardy_recordset(256)
|
||
{
|
||
TFilename cazzone;
|
||
//as400 con lunghezza 256 e chiave lunga 2 (a partire dall'inizio): <20> il tipo record
|
||
parse_query("AS400(256,2)", cazzone);
|
||
|
||
//Tipo record SU
|
||
//--------------
|
||
add_trc_field("SU", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("SU", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("SU", "CodiceAgente", T_N, 6, 3); //x
|
||
add_trc_field("SU", "NonUsato", T_X, 9, 6);
|
||
add_trc_field("SU", "Targa", T_X, 15, 8);
|
||
add_trc_field("SU", "nDDT", T_N, 23, 5);
|
||
add_trc_field("SU", "nFATT", T_N, 28, 5);
|
||
add_trc_field("SU", "nBOLLA", T_N, 33, 5);
|
||
add_trc_field("SU", "NomeAgente", T_X, 38,30); //x
|
||
|
||
//Tipo record TF
|
||
//--------------
|
||
add_trc_field("TF", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("TF", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("TF", DOC_NDOC, T_N, 6, 5); //x
|
||
add_trc_field("TF", DOC_DATADOC, T_X, 11, 6); //x
|
||
add_trc_field("TF", DOC_TIPODOC, T_X, 17, 1); //x
|
||
add_trc_field("TF", DOC_CODCF, T_X, 18, 6); //x
|
||
add_trc_field("TF", DOC_CODCFFATT, T_X, 24, 6); //x
|
||
add_trc_field("TF", "ImponibileLordo", T_Nv2N, 30, 8); // campi seguenti da righe doc
|
||
add_trc_field("TF", "ScontoFattura", T_2Nv2N,38, 4);
|
||
add_trc_field("TF", "ImponibileDoc", T_Nv2N, 42, 8);
|
||
add_trc_field("TF", "TotaleDoc", T_Nv2N, 50, 8);
|
||
add_trc_field("TF", "ScontoTotale", T_Nv2N, 58, 8);
|
||
add_trc_field("TF", "ImponibileOmaggi", T_Nv2N, 66, 8);
|
||
add_trc_field("TF", "ImponibileSost", T_Nv2N, 74, 8);
|
||
add_trc_field("TF", "Incasso", T_Nv2N, 82, 8); //forse IMPPAGATO ?
|
||
add_trc_field("TF", DOC_CODPAG, T_X, 90, 2); //x
|
||
add_trc_field("TF", DOC_DATAPART, T_X, 92, 6); //x
|
||
add_trc_field("TF", "Iva1", T_N, 98, 2); //anche questi da righe doc
|
||
add_trc_field("TF", "Imponibile1", T_Nv2N, 100,8);
|
||
add_trc_field("TF", "Imposta1", T_Nv2N, 108,7);
|
||
add_trc_field("TF", "Iva2", T_N, 115,2);
|
||
add_trc_field("TF", "Imponibile2", T_Nv2N, 117,8);
|
||
add_trc_field("TF", "Imposta2", T_Nv2N, 125,7);
|
||
add_trc_field("TF", "Iva3", T_N, 132,2);
|
||
add_trc_field("TF", "Imponibile3", T_Nv2N, 134,8);
|
||
add_trc_field("TF", "Imposta3", T_Nv2N, 142,7);
|
||
add_trc_field("TF", "Iva4", T_N, 149,2);
|
||
add_trc_field("TF", "Imponibile4", T_Nv2N, 151,8);
|
||
add_trc_field("TF", "Imposta4", T_Nv2N, 159,7);
|
||
add_trc_field("TF", "CodcliGiro3", T_X, 166,6);
|
||
add_trc_field("TF", "IvaOmag1", T_N, 172,2);
|
||
add_trc_field("TF", "ImponibileOmag1", T_Nv2N, 174,6);
|
||
add_trc_field("TF", "ImpostaOmag1", T_Nv2N, 180,5);
|
||
add_trc_field("TF", "IvaOmag2", T_N, 185,2);
|
||
add_trc_field("TF", "ImponibileOmag2", T_Nv2N, 187,6);
|
||
add_trc_field("TF", "ImpostaOmag2", T_Nv2N, 193,5);
|
||
add_trc_field("TF", "DataEmissione", T_X, 198,6);
|
||
add_trc_field("TF", "PagamentoCarta", T_X, 204,1);
|
||
|
||
//Tipo record RF
|
||
//--------------
|
||
add_trc_field("RF", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("RF", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("RF", RDOC_NDOC, T_N, 6, 5); //x
|
||
add_trc_field("RF", DOC_DATADOC, T_X, 11, 6); //x testata
|
||
add_trc_field("RF", DOC_CODCF, T_X, 17, 6); //x testata
|
||
add_trc_field("RF", DOC_CODCFFATT, T_X, 23, 6); //x testata
|
||
add_trc_field("RF", DOC_TIPODOC, T_X, 29, 1); //x testata
|
||
add_trc_field("RF", RDOC_CODART, T_X, 30, 5); //x
|
||
add_trc_field("RF", "TipoCessione", T_X, 35, 1);
|
||
add_trc_field("RF", "Qta[int]", T_N, 36, 5); //x
|
||
add_trc_field("RF", "Qta[dec]", T_N, 41, 2); //x
|
||
add_trc_field("RF", "Sconto1", T_2Nv2N,43, 4);
|
||
add_trc_field("RF", "Sconto2", T_2Nv2N,47, 4);
|
||
add_trc_field("RF", "Sconto3", T_2Nv2N,51, 4);
|
||
add_trc_field("RF", "ScontoLibero", T_2Nv2N,55, 4);
|
||
add_trc_field("RF", RDOC_PREZZO, T_Nv3N, 59, 7); //x forse PREZZOL ?
|
||
add_trc_field("RF", "TotaleRiga", T_Nv3N, 66, 8);
|
||
add_trc_field("RF", "TotaleSconto", T_Nv3N, 74, 8);
|
||
add_trc_field("RF", "AliquotaIva", T_N, 82, 2); //noi abbiamo il codice
|
||
add_trc_field("RF", RDOC_UMQTA, T_X, 84, 2); //x
|
||
add_trc_field("RF", "PrezzoScontato", T_Nv3N, 86, 7);
|
||
add_trc_field("RF", "Fascia", T_X, 93, 1);
|
||
add_trc_field("RF", "ScontoFascia", T_2N, 94, 2);
|
||
add_trc_field("RF", "NonUsato", T_N, 96, 2);
|
||
add_trc_field("RF", "CodcliGiro3", T_X, 98, 6);
|
||
add_trc_field("RF", "CodiceLotto", T_X, 104,10); //noi lo leghiamo all'articolo
|
||
|
||
//Tipo record SI
|
||
//--------------
|
||
add_trc_field("SI", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("SI", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("SI", "CodiceCliente", T_X, 6, 6);
|
||
add_trc_field("SI", "NumeroFattura", T_X, 12, 12);
|
||
add_trc_field("SI", "DataFattura", T_X, 24, 6);
|
||
add_trc_field("SI", "NonUsato", T_N, 30, 9);
|
||
add_trc_field("SI", "ImportoIncassato", T_Nv2N, 39, 9);
|
||
add_trc_field("SI", "DataIncasso", T_X, 48, 6);
|
||
add_trc_field("SI", "Partita", T_X, 54, 15);
|
||
add_trc_field("SI", "TipoDocumento", T_X, 69, 1);
|
||
add_trc_field("SI", "DataEmissione", T_X, 70, 6);
|
||
add_trc_field("SI", "PagamentoCarta", T_X, 76, 1);
|
||
|
||
//Tipo record BR
|
||
//--------------
|
||
add_trc_field("BR", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("BR", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("BR", "NumeroRiga", T_N, 6, 3);
|
||
add_trc_field("BR", "NumeroDoc", T_N, 9, 5);
|
||
add_trc_field("BR", "DataMov", T_X, 14, 6);
|
||
add_trc_field("BR", "CodiceArticolo", T_X, 20, 5);
|
||
add_trc_field("BR", "Qta[int]", T_N, 25, 5);
|
||
add_trc_field("BR", "Qta[dec]", T_N, 30, 2);
|
||
add_trc_field("BR", "Mittente", T_N, 32, 3);
|
||
add_trc_field("BR", "Destinatario", T_N, 35, 3);
|
||
add_trc_field("BR", "CausaleMov", T_N, 38, 2);
|
||
add_trc_field("BR", "CodiceLotto", T_X, 40, 10);
|
||
|
||
//Tipo record VC
|
||
//--------------
|
||
add_trc_field("VC", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("VC", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("VC", "CodiceCliente", T_X, 6, 6); //x
|
||
add_trc_field("VC", "RagioneSociale", T_X, 12, 34); //x
|
||
add_trc_field("VC", "Indirizzo", T_X, 46, 34); //x
|
||
add_trc_field("VC", "Localita", T_X, 80, 20); //x attenzione che potrebbe essere il com_dencom
|
||
add_trc_field("VC", "CAP", T_X, 100, 5); //x
|
||
add_trc_field("VC", "Provincia", T_X, 105, 2); //x da questo e da dencom ricaviamo il codcom
|
||
add_trc_field("VC", "PartitaIVA", T_X, 107, 16); //x
|
||
add_trc_field("VC", "CodicePagamento", T_X, 123, 2); //x
|
||
add_trc_field("VC", "CodiceListino", T_X, 125, 3);
|
||
add_trc_field("VC", "TipoDocumento", T_X, 128, 1);
|
||
add_trc_field("VC", "CodiceFiscale", T_X, 129, 16); //x
|
||
|
||
|
||
//Tipo record RC
|
||
//--------------
|
||
add_trc_field("RC", "TipoRecord", T_X, 1, 2); //x
|
||
add_trc_field("RC", "CodiceTerminale", T_N, 3, 3); //x
|
||
add_trc_field("RC", "CodiceArticolo", T_X, 6, 5); //x
|
||
add_trc_field("RC", "Quantita", T_Nv2N, 11, 7); //x
|
||
add_trc_field("RC", "DataCarico", T_X, 18, 6); //x
|
||
|
||
TText_recordset::load_file(filename);
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TAutomask : maschera principale
|
||
///////////////////////////////////////////////////////////
|
||
class TUpload2Campo_mask : public TAutomask
|
||
{
|
||
protected:
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
|
||
public:
|
||
TUpload2Campo_mask();
|
||
};
|
||
|
||
bool TUpload2Campo_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
TUpload2Campo_mask::TUpload2Campo_mask() : TAutomask ("ha1300a")
|
||
{
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TAutomask : maschera secondaria per inserimento nuovo cliente
|
||
///////////////////////////////////////////////////////////
|
||
class TUpload2Campo_newcli_mask : public TAutomask
|
||
{
|
||
protected:
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
|
||
public:
|
||
TUpload2Campo_newcli_mask();
|
||
};
|
||
|
||
bool TUpload2Campo_newcli_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
TUpload2Campo_newcli_mask::TUpload2Campo_newcli_mask() : TAutomask ("ha1301a")
|
||
{
|
||
}
|
||
|
||
///////////////////////////////////////
|
||
// TSkeleton_application
|
||
///////////////////////////////////////
|
||
class TUpload2Campo : public THardy_transaction
|
||
{
|
||
bool _can_write;
|
||
TAssoc_array _nuovi_clienti;
|
||
|
||
protected:
|
||
virtual void elabora(const TMask& mask, TLog_report& log);
|
||
virtual TMask* create_mask() const;
|
||
const char* fake_trans_file() const;
|
||
|
||
//metodi di basso livello
|
||
const TString& check_agente(TString& codice_terminale, TLog_report& log);
|
||
const TString& check_articolo(TString& codart, TLog_report& log);
|
||
long check_cliente(const TString& str_codcf, TLog_report& log);
|
||
void check_magazzino(const TString& codmag_age, TLog_report& log);
|
||
void check_causale(TString& codcaus, TLog_report& log);
|
||
bool genera_incasso(TPartita& game, int nriga, int nrata, const TMovimentoPN& mov, const TBill& zio_agente, TLog_report& log) const;
|
||
bool archivia_file_importato(const TString& dst_root_path, const TFilename& curr_fname, const TString& terminalino, TLog_report& log);
|
||
|
||
//metodi di alto livello
|
||
const TString4 elabora_SU(THardy_upload_recordset& recset, TLog_report& log);
|
||
void elabora_BR(THardy_upload_recordset& recset, TLog_report& log);
|
||
void elabora_VC(THardy_upload_recordset& recset, TLog_report& log);
|
||
void elabora_TF(THardy_upload_recordset& recset, TLog_report& log);
|
||
void elabora_SI(THardy_upload_recordset& recset, TLog_report& log);
|
||
void elabora_RC(THardy_upload_recordset& recset, TLog_report& log);
|
||
|
||
public:
|
||
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Metodi di basso livello
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
bool TUpload2Campo::archivia_file_importato(const TString& dst_root_path, const TFilename& curr_fname, const TString& terminalino, TLog_report& log)
|
||
{
|
||
//controllo della cartella di destinazione
|
||
TFilename dst_file = dst_root_path;
|
||
dst_file.add(terminalino);
|
||
const bool crea_dir = make_dir(dst_file);
|
||
//non riesce a crearla/trovarla! deve dare errore di grave livello!
|
||
if (!crea_dir)
|
||
{
|
||
TString msg;
|
||
msg.format(FR("Impossibile creare la cartella %s!"), (const char*)dst_file);
|
||
log.log(2, msg);
|
||
return false;
|
||
}
|
||
|
||
//se invece crea/trova la cartella -> copia il file
|
||
dst_file.add(curr_fname.name());
|
||
|
||
const bool copia_riuscita = fcopy(curr_fname, dst_file);
|
||
if (!copia_riuscita)
|
||
{
|
||
TString msg;
|
||
msg.format(FR("Impossibile copiare il file %s!"), (const char*)curr_fname.name());
|
||
log.log(2, msg);
|
||
return false;
|
||
}
|
||
|
||
//controllo dell'avvenuta copia e della correttezza del file destinazione
|
||
//controllo sulle dimensioni
|
||
const long src_size = fsize(curr_fname);
|
||
const long dst_size = fsize(dst_file);
|
||
|
||
if (src_size != dst_size)
|
||
{
|
||
TString msg;
|
||
msg.format(FR("Copia del file %s non completata!"), curr_fname.name());
|
||
log.log(2, msg);
|
||
return false;
|
||
}
|
||
|
||
//eliminazione del file sorgente
|
||
const bool src_file_removed = remove_file(curr_fname);
|
||
if (!src_file_removed)
|
||
{
|
||
TString msg;
|
||
msg.format(FR("Impossibile eliminare il file origine %s"), curr_fname.name());
|
||
log.log(1, msg);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//controlla se il terminale corrisponde ad un agente registrato e restituisce l'agente
|
||
const TString& TUpload2Campo::check_agente(TString& codice_terminale, TLog_report& log)
|
||
{
|
||
codice_terminale.right_just(3, '0');
|
||
TString8 codice_agente = codice_terminale;
|
||
codice_agente.right_just(5, '0');
|
||
|
||
const TRectype& rec_age = cache().get(LF_AGENTI, codice_agente);
|
||
const TString& codage_campo = rec_age.get(AGE_CODAGE);
|
||
|
||
if (codage_campo != codice_agente)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << TR("Codice agente ") << codice_agente << TR(" da terminale: sconosciuto");
|
||
log.log(2, msg);
|
||
}
|
||
return codage_campo;
|
||
}
|
||
|
||
|
||
//controlla che l'articolo esista su Campo
|
||
const TString& TUpload2Campo::check_articolo(TString& codart, TLog_report& log)
|
||
{
|
||
codart.trim();
|
||
const TRectype& rec_anamag = cache().get(LF_ANAMAG, codart);
|
||
const TString& articolo_campo = rec_anamag.get(ANAMAG_CODART);
|
||
if (articolo_campo != codart)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << TR("Codice articolo ") << codart << TR(" sconosciuto su Campo");
|
||
log.log(2, msg);
|
||
}
|
||
return rec_anamag.get(ANAMAG_DESCR);
|
||
}
|
||
|
||
//controlla l'esistenza del magazzino su Campo
|
||
void TUpload2Campo::check_magazzino(const TString& codmag_age, TLog_report& log)
|
||
{
|
||
const TString& codmag_campo = cache().get("MAG", codmag_age, "CODTAB");
|
||
if (codmag_campo != codmag_age)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Codice magazzino " << codmag_age << " sconosciuto su Campo";
|
||
log.log(2, msg);
|
||
}
|
||
}
|
||
|
||
//controlla il cliente;se nuovo controlla che sia gi<67> stato importato nella lista dei nuovi clienti,se..
|
||
//esistente controlla che ci sia negli archivi Campo
|
||
long TUpload2Campo::check_cliente(const TString& str_codcf, TLog_report& log)
|
||
{
|
||
long codcf = 0L;
|
||
const bool new_cliente = str_codcf.find('*') >= 0;
|
||
|
||
if (new_cliente)
|
||
{
|
||
const real* ptr = (const real*)_nuovi_clienti.objptr(str_codcf);
|
||
codcf = ptr ? ptr->integer() : 0L;
|
||
}
|
||
else
|
||
{
|
||
TToken_string key_clifo;
|
||
key_clifo.add("C");
|
||
key_clifo.add(str_codcf);
|
||
codcf = atol(cache().get(LF_CLIFO, key_clifo, CLI_CODCF));
|
||
}
|
||
|
||
//controllo effettuabile solo se il cliente <20> gi<67> presente (vecchio o nuovo aggiunto con la importa_VC se era _can_write)
|
||
if (codcf <= 0)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Codice cliente " << str_codcf << " sconosciuto";
|
||
log.log(2, msg);
|
||
}
|
||
|
||
return codcf;
|
||
}
|
||
|
||
//aggiorna una partita con una nuova riga che riguarda l'incasso
|
||
bool TUpload2Campo::genera_incasso(TPartita& game, int nriga, int nrata,
|
||
const TMovimentoPN& mov, const TBill& zio_agente, TLog_report& log) const
|
||
{
|
||
TString msg;
|
||
msg.format(FR(" %d della riga %d della partita %d/%s"),
|
||
nrata, nriga, game.anno(), (const char*)game.numero());
|
||
|
||
if (!game.esiste(nriga, nrata)) // Non si sa mai col saldaconto!
|
||
{
|
||
msg.insert(TR("Non esiste la rata"));
|
||
msg << " Creazione pagamento non assegnato.";
|
||
log.log(1, msg);
|
||
nriga = nrata = game.UNASSIGNED;
|
||
}
|
||
|
||
const TRectype& head = mov.curr();
|
||
|
||
// Creo una riga di partita di tipo pagamento e ci copio i dati della testata del movimento
|
||
TRiga_partite& riga = game.new_row();
|
||
const int nrigp = riga.get_int(PART_NRIGA);
|
||
riga.put(PART_TIPOMOV, tm_pagamento);
|
||
riga.put(PART_SEZ, game.conto().tipo() == 'F' ? 'D' : 'A');
|
||
riga.put(PART_NREG, head.get(MOV_NUMREG));
|
||
riga.put(PART_NUMRIG, 1);
|
||
riga.put(PART_DATAREG, head.get(MOV_DATAREG));
|
||
riga.put(PART_DATADOC, head.get(MOV_DATADOC));
|
||
riga.put(PART_DATAPAG, head.get(MOV_DATACOMP));
|
||
riga.put(PART_CODCAUS, head.get(MOV_CODCAUS));
|
||
riga.put(PART_NUMDOC, head.get(MOV_NUMDOC));
|
||
riga.put(PART_DESCR, head.get(MOV_DESCR));
|
||
|
||
// Creo una nuova riga di pagamento assegnado il flag di saldo
|
||
TRectype new_pag(LF_PAGSCA);
|
||
if (nriga > 0 && nriga < game.UNASSIGNED)
|
||
{
|
||
TRiga_scadenze& scad = game.rata(nriga, nrata);
|
||
new_pag = scad.new_row(nrigp); // Creo nuova riga e la duplico
|
||
}
|
||
else //se la partita non esiste si inventa il pagamento
|
||
new_pag = game.pagamento(nriga, nrata, nrigp);
|
||
|
||
new_pag.put(PAGSCA_ACCSAL, 'A');
|
||
new_pag.put(PART_IMPORTO, head.get_real(MOV_TOTDOC));
|
||
|
||
//richiesta di Hardy del 04-03-2011: aggiungere il conto agente in $pagsca gruppoc-contoc-sottocontc..
|
||
//..ovvero il conto di contropartita sul pagamento
|
||
const int gruppoc = zio_agente.gruppo();
|
||
const int contoc = zio_agente.conto();
|
||
const long sottocontc = zio_agente.sottoconto();
|
||
new_pag.put(PAGSCA_GRUPPOC, gruppoc);
|
||
new_pag.put(PAGSCA_CONTOC, contoc);
|
||
new_pag.put(PAGSCA_SOTTOCONTC, sottocontc);
|
||
//..ovvero nei gruppi di contropartita
|
||
const TValuta valuta(head);
|
||
game.modifica_pagamento(new_pag, valuta, true);
|
||
return true;
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Metodi di alto livello
|
||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
//SU non <20> un tipo record di qualche utilit<69>
|
||
const TString4 TUpload2Campo::elabora_SU(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
codice_terminale.format("%03d", atoi(codice_terminale));
|
||
return codice_terminale;
|
||
}
|
||
|
||
//elabora clienti e loro variazioni; viene comunque eseguita per prima perch<63> i record VC vengono messi all'inizio
|
||
void TUpload2Campo::elabora_VC(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
//dati dal recordset di upload
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
const TString8 codice_agente = check_agente(codice_terminale, log);
|
||
|
||
long codcf = recset.get("CodiceCliente").as_int();
|
||
|
||
TLocalisamfile file_clifo(LF_CLIFO);
|
||
|
||
//se il codice contiene un '*' -> il cliente <20> nuovo e va aggiunto alla lista di Campo
|
||
//se invece il cliente ha un codice normale -> <20> un aggiornamento dei suoi dati -> controlla che esista davvero
|
||
if (codcf <= 0)
|
||
{
|
||
//questa <20> un surrogato della get_next_cli considerando che vanno riempiti i clienti della serie 200000..
|
||
//..prima di intaccare eventuali clienti della serie 300000
|
||
file_clifo.zero();
|
||
file_clifo.put(CLI_TIPOCF, 'C');
|
||
file_clifo.put(CLI_CODCF, 300000);
|
||
int err = file_clifo.read(_isgteq);
|
||
codcf = 1;
|
||
if (err == NOERR)
|
||
{
|
||
file_clifo.prev();
|
||
codcf += file_clifo.get_long(CLI_CODCF);
|
||
}
|
||
|
||
//La finestra propositiva per ora non viene usata!
|
||
//finestra propositiva del nuovo codcf; viene proposto il codcf calcolato come ultimo + 1, ma l'utonto potrebbe..
|
||
//..decidere di andare a riempire un qualche 'buco' precedentemente alla cazzo creato!!
|
||
/* TUpload2Campo_newcli_mask newcli_mask;
|
||
newcli_mask.set(F_CODCF, codcf);
|
||
FOR_EACH_MASK_FIELD(newcli_mask, f, fld)
|
||
{
|
||
const TFieldref* fr = fld->field();
|
||
if (fr != NULL)
|
||
fld->set(recset.get(fr->name()).as_string());
|
||
}
|
||
if (newcli_mask.run() == K_ENTER)
|
||
{*/
|
||
|
||
//aggiunge il cliente nuovo ricodificato all'array dei nuovi clienti in modo da ricordarsi chi era..
|
||
//..quando loritrover<65> nei record di tipo TF,RF,SI; lo in ogni modo perch<63> serve anche in caso di simulazione!
|
||
const TString& str_new_codcf = recset.get("CodiceCliente").as_string();
|
||
_nuovi_clienti.add(str_new_codcf, real(codcf));
|
||
|
||
file_clifo.zero();
|
||
file_clifo.put(CLI_TIPOCF, 'C');
|
||
file_clifo.put(CLI_CODCF, codcf);
|
||
|
||
//ATTENZIONE!! In caso di simulazione ci si ferma qui perch<63> non si potrebbe inserire alcun dato, visto che..
|
||
//_can_write <20> comunque falso!
|
||
if (_can_write)
|
||
file_clifo.write();
|
||
else
|
||
{
|
||
TString msg;
|
||
msg << "Nuovo cliente con codice provvisorio: " << str_new_codcf << "da registrare in Campo con il codice: " << codcf;
|
||
log.log(0, msg);
|
||
return;
|
||
}
|
||
} //if(codcf<=0)...
|
||
|
||
|
||
//il cliente, se non nuovo, deve esistere!
|
||
file_clifo.put(CLI_TIPOCF, 'C');
|
||
file_clifo.put(CLI_CODCF, codcf);
|
||
|
||
int err = file_clifo.read();
|
||
|
||
//se non esiste non scrive ma continua
|
||
if (err != NOERR)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Impossibile aggiornare il cliente " << codcf << ". File clifo.";
|
||
log.log(2, msg);
|
||
}
|
||
|
||
//campi clifo
|
||
const TString& ragsoc = recset.get("RagioneSociale").as_string();
|
||
file_clifo.put(CLI_RAGSOC, ragsoc);
|
||
const TString& indcf = recset.get("Indirizzo").as_string();
|
||
file_clifo.put(CLI_INDCF, indcf);
|
||
const TString& localita = recset.get("Localita").as_string();
|
||
file_clifo.put(CLI_LOCCF, localita);
|
||
const TString& cap = recset.get("CAP").as_string();
|
||
file_clifo.put(CLI_CAPCF, cap);
|
||
//modo semi-intelligente per cercare il comune dato il cap e la localit<69>
|
||
const TString& codcom = cap2comune(cap, localita);
|
||
file_clifo.put(CLI_COMCF, codcom);
|
||
//la provincia non serve perch<63> si passa dal codice del comune
|
||
//const TString& provincia = recset.get("Provincia").as_string();
|
||
const TString& piva = recset.get("PartitaIVA").as_string();
|
||
file_clifo.put(CLI_PAIV, piva);
|
||
const TString& codpag = recset.get("CodicePagamento").as_string();
|
||
file_clifo.put(CLI_CODPAG, codpag);
|
||
const TString& cofi = recset.get("CodiceFiscale").as_string();
|
||
file_clifo.put(CLI_COFI, cofi);
|
||
|
||
//campi cfven
|
||
//prima cerca se il record di questo c+codcf esiste gi<67> sul cfven
|
||
TLocalisamfile file_cfven(LF_CFVEN);
|
||
file_cfven.put(CFV_TIPOCF, 'C');
|
||
file_cfven.put(CFV_CODCF, codcf);
|
||
err = file_cfven.read();
|
||
//se non c'<27> lo crea!
|
||
if (err != NOERR)
|
||
{
|
||
file_cfven.zero();
|
||
file_cfven.put(CFV_TIPOCF, 'C');
|
||
file_cfven.put(CFV_CODCF, codcf);
|
||
if (_can_write)
|
||
err = file_cfven.write();
|
||
else
|
||
err = NOERR;
|
||
}
|
||
//se la creazione non va a buon fine avverte
|
||
if (err != NOERR)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Impossibile aggiornare il cliente " << ragsoc << ". File cfven.";
|
||
log.log(2, msg);
|
||
}
|
||
|
||
file_cfven.put(CFV_CODAG, codice_agente);
|
||
const TString& codlist = recset.get("CodiceListino").as_string();
|
||
file_cfven.put(CFV_CODLIST, codlist);
|
||
|
||
|
||
//incredibilmente arriva in fondo
|
||
TString msg;
|
||
msg << "Cliente: " << codcf << " Terminale: " << codice_terminale;
|
||
//se pu<70> scrivere...
|
||
if (_can_write)
|
||
{
|
||
//alla fine della fiera salva il cliente e il cfven
|
||
err = file_clifo.rewrite();
|
||
if (err == NOERR)
|
||
err = file_cfven.rewrite();
|
||
|
||
if (err == NOERR)
|
||
{
|
||
msg.insert("Registrato cliente: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Impossibile registrare cliente: ", 0);
|
||
log.log(2, msg);
|
||
}
|
||
}
|
||
}
|
||
|
||
//movimenti di incasso
|
||
void TUpload2Campo::elabora_SI(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
//dati dal recordset di upload (con i relativi controlli)
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
const TString8 codice_agente = check_agente(codice_terminale, log);
|
||
const TString& str_codcf = recset.get("CodiceCliente").as_string();
|
||
long codcf = check_cliente(str_codcf, log);
|
||
|
||
//crea un movimento contabile pescando i dati dal recordset (e inventandosene qualcuno!)
|
||
//testata
|
||
const TString& str_dataincasso = recset.get("DataIncasso").as_string();
|
||
const TDate data_incasso = upload_format_date6(str_dataincasso);
|
||
const TDate datareg = data_incasso;
|
||
const TDate datacomp = data_incasso;
|
||
TEsercizi_contabili esc;
|
||
const int annoes = esc.date2esc(data_incasso);
|
||
const int anno = datareg.year();
|
||
const long ndoc = recset.get("NumeroFattura").as_int();
|
||
const TString& str_datadoc = recset.get("DataFattura").as_string();
|
||
const TDate datadoc = upload_format_date6(str_datadoc);
|
||
const TString4 tipodoc = recset.get("TipoDocumento").as_string();
|
||
const real incasso = recset.get("ImportoIncassato").as_real() / CENTO;
|
||
|
||
//panegirico su anno partita e numero partita
|
||
const TString16 str_part = recset.get("Partita").as_string();
|
||
int annopart = atoi(str_part.left(4)); // anno = primi 4 caratteri del campo partita
|
||
TString8 numpart = str_part.mid(5, 7); // numero partita = 7 caratteri a partire dal sesto
|
||
|
||
if (numpart.blank())
|
||
{
|
||
annopart = datadoc.year();
|
||
TToken_string nd(recset.get("NumeroFattura").as_string(), '/');
|
||
numpart.format("%ld/%02d", nd.get_long(0), nd.get_int(1));
|
||
}
|
||
|
||
if (annopart <= 0 || numpart.blank())
|
||
{
|
||
TString msg;
|
||
msg << "Partita: " << numpart << " Anno: " << anno << " non valida!";
|
||
_can_write = false;
|
||
log.log(2, msg);
|
||
}
|
||
|
||
//TConfig config(CONFIG_DITTA, "ha");
|
||
//const TString& codcaus = config.get("InpCausale");
|
||
const TString8 codcaus = ini_get_string(CONFIG_DITTA, "ha", "InpCausale");
|
||
const TCausale caus(codcaus, anno);
|
||
|
||
TMovimentoPN mov;
|
||
TRectype& head = mov.curr();
|
||
head.put(MOV_CODCAUS, codcaus);
|
||
head.put(MOV_DATAREG, datareg);
|
||
head.put(MOV_DATACOMP, datacomp);
|
||
TString descr;
|
||
descr << "Incasso. Cliente: " << codcf << " - Agente: " << codice_agente;
|
||
head.put(MOV_DESCR, descr);
|
||
|
||
head.put(MOV_ANNOES, annoes);
|
||
head.put(MOV_DATADOC, datadoc);
|
||
head.put(MOV_NUMDOC, ndoc);
|
||
head.put(MOV_TIPODOC, tipodoc);
|
||
head.put(MOV_TIPOMOV, caus.tipomov());
|
||
head.put(MOV_ANNOIVA, anno);
|
||
head.put(MOV_TOTDOC, incasso);
|
||
|
||
long numreg = 999999L;
|
||
|
||
TString msg;
|
||
msg << " movimento di incasso. Cliente: " << codcf << " - Agente: " << codice_agente << " - Data: " << data_incasso;
|
||
|
||
//panegirico sui conti
|
||
//conto cliente
|
||
TToken_string key_clifo;
|
||
key_clifo.add('C');
|
||
key_clifo.add(codcf);
|
||
const TRectype& rec_codcf = cache().get(LF_CLIFO, key_clifo);
|
||
int gr_cli = rec_codcf.get_int(CLI_GRUPPO);
|
||
int co_cli = rec_codcf.get_int(CLI_CONTO);
|
||
TBill zio_clifo(gr_cli, co_cli, codcf ,'C');
|
||
//se il cliente non ha un suo conto, prova con il primo della causale incassi in configurazione
|
||
if (zio_clifo.conto() <= 0)
|
||
{
|
||
caus.bill(1, zio_clifo);
|
||
gr_cli = zio_clifo.gruppo();
|
||
co_cli = zio_clifo.conto();
|
||
zio_clifo.set(gr_cli, co_cli, codcf, 'C');
|
||
}
|
||
|
||
TPartita game(zio_clifo, annopart, numpart);
|
||
for (int r = game.last(); r > 0; r = game.pred(r))
|
||
{
|
||
const TRiga_partite& riga = game.riga(r);
|
||
if (riga.tipo() == tm_pagamento)
|
||
{
|
||
const TDate data_riga = riga.get_date(PART_DATAPAG);
|
||
const real imp_riga = riga.get_real(PART_IMPORTO);
|
||
if (data_riga == data_incasso && imp_riga == incasso)
|
||
{
|
||
_can_write = false;
|
||
msg.insert("Doppio");
|
||
log.log(2, msg);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (_can_write)
|
||
{
|
||
if (mov.write() != NOERR)
|
||
{
|
||
_can_write = false;
|
||
msg.insert("Impossibile registrare");
|
||
log.log(2, msg);
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Registrato");
|
||
log.log(0, msg);
|
||
numreg = head.get_long(MOV_NUMREG);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Controllato");
|
||
log.log(0, msg);
|
||
}
|
||
|
||
|
||
//conto agente
|
||
const TRectype& rec_agente = cache().get(LF_AGENTI, codice_agente);
|
||
int gr_age = rec_agente.get_int(AGE_GRUPPO);
|
||
int co_age = rec_agente.get_int(AGE_CONTO);
|
||
long sott_age = rec_agente.get_long(AGE_SOTTOCONTO);
|
||
TBill zio_agente(gr_age, co_age, sott_age);
|
||
//se l'agente non ha un suo conto, prova con il secondo della causale incassi in configurazione
|
||
if (zio_agente.conto() <= 0)
|
||
{
|
||
caus.bill(2, zio_agente);
|
||
gr_age = zio_agente.gruppo();
|
||
co_age = zio_agente.conto();
|
||
sott_age = zio_agente.sottoconto();
|
||
zio_agente.set(gr_age, co_age, sott_age);
|
||
}
|
||
|
||
//creazione vera e propria delle righe
|
||
//riga 1: conto cliente
|
||
TRectype& new_rmov_cli = mov.cg(-1);
|
||
new_rmov_cli.put(RMV_ROWTYPE, 'K');
|
||
new_rmov_cli.put(RMV_ANNOES, annoes);
|
||
new_rmov_cli.put(RMV_DATAREG, datareg);
|
||
zio_clifo.put(new_rmov_cli);
|
||
const char sezione_cli = caus.sezione(1);
|
||
new_rmov_cli.put(RMV_SEZIONE, sezione_cli);
|
||
TString descr_rmv_cli;
|
||
descr_rmv_cli << "Incasso cliente " << codcf;
|
||
new_rmov_cli.put(RMV_DESCR, descr_rmv_cli);
|
||
zio_agente.put(new_rmov_cli, true); //conto di contropartita = conto agente
|
||
new_rmov_cli.put(RMV_IMPORTO, incasso);
|
||
//riga 2: conto agente
|
||
TRectype& new_rmov_age = mov.cg(-1);
|
||
new_rmov_age.put(RMV_ROWTYPE, 'I');
|
||
new_rmov_age.put(RMV_ANNOES, annoes);
|
||
new_rmov_age.put(RMV_DATAREG, datareg);
|
||
zio_agente.put(new_rmov_age);
|
||
const char sezione_age = caus.sezione(2);
|
||
new_rmov_age.put(RMV_SEZIONE, sezione_age);
|
||
TString descr_rmv_age;
|
||
descr_rmv_age << "Incasso agente " << codice_agente;
|
||
new_rmov_age.put(RMV_DESCR, descr_rmv_age);
|
||
zio_clifo.put(new_rmov_age, true); //conto di contropartita = conto cliente
|
||
new_rmov_age.put(RMV_IMPORTO, incasso);
|
||
|
||
//crea i pagamenti aggiornando anche la partita (qui si parr<72> la tua nobilitate!)
|
||
const int nriga = game.prima_fattura();
|
||
const int nrata = 1;
|
||
//metodo magicissimo per l'aggiornamento della partita con l'incasso
|
||
genera_incasso(game, nriga, nrata, mov, zio_agente, log);
|
||
|
||
//alla fine della fiera scrive (se pu<70>) movimento e pagamento su partita
|
||
if (_can_write)
|
||
{
|
||
int err = mov.rewrite();
|
||
|
||
TString mov_msg;
|
||
mov_msg << " movimento di incasso n.reg.: " << numreg;
|
||
|
||
if (err == NOERR)
|
||
{
|
||
mov_msg.insert("Completato");
|
||
log.log(0, mov_msg);
|
||
|
||
game.write(true);
|
||
}
|
||
else
|
||
{
|
||
_can_write = false;
|
||
mov_msg.insert("Impossibile completare");
|
||
log.log(2, mov_msg);
|
||
}
|
||
} //if(_can_write)...
|
||
}
|
||
|
||
|
||
void TUpload2Campo::elabora_BR(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
//dati dal recordset di upload
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
const TString& codice_agente = check_agente(codice_terminale, log);
|
||
const TString8 cod_magazzino = cache().get(LF_AGENTI, codice_agente, AGE_CODMAG);
|
||
check_magazzino(cod_magazzino, log);
|
||
|
||
const long curr_movmag = recset.get("NumeroDoc").as_int();
|
||
const TString& str_data_mov = recset.get("DataMov").as_string();
|
||
const TDate data_mov = upload_format_date6(str_data_mov);
|
||
const int anno = data_mov.year();
|
||
TString descr;
|
||
descr << "Agente: " << codice_terminale;
|
||
|
||
//1) crea la testata
|
||
//movimento di magazzino da riempire
|
||
TMov_mag movmag;
|
||
|
||
//const long numreg = atol(movmag.get_next_key());
|
||
//movmag.put(MOVMAG_NUMREG, numreg);
|
||
movmag.put(MOVMAG_ANNOES, anno);
|
||
movmag.put(MOVMAG_DATAREG, data_mov);
|
||
movmag.put(MOVMAG_DATACOMP, data_mov);
|
||
movmag.put(MOVMAG_EXNUMDOC, curr_movmag);
|
||
movmag.put(MOVMAG_EXDATADOC, data_mov);
|
||
movmag.put(MOVMAG_DESCR, descr);
|
||
|
||
//la causale va trascodificata con l'apposita tabella &CAU
|
||
const TString& caus_term = recset.get("CausaleMov").as_string();
|
||
const TString& codcaus = cache().get("&CAU", caus_term, "S7");
|
||
if (codcaus.empty())
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Causale movimento " << caus_term << " non codificata";
|
||
log.log(2, msg);
|
||
}
|
||
movmag.put(MOVMAG_CODCAUS, codcaus);
|
||
|
||
bool go_on = true;
|
||
// righe movimento di magazzino
|
||
//scansione delle righe documento su record BR
|
||
while (go_on)
|
||
{
|
||
//2) crea le righe (legge tutti i record di tipo BR successivi finch<63> hanno lo stesso numero documento!)
|
||
|
||
//agginunge una nuova riga (solo merce, per quanto ne sappiamo)
|
||
TRectype& rmovmag = movmag.new_row();
|
||
rmovmag.put(RMOVMAG_CODMAG, cod_magazzino);
|
||
TString8 codart = recset.get("CodiceArticolo").as_string();
|
||
check_articolo(codart, log);
|
||
rmovmag.put(RMOVMAG_CODART, codart);
|
||
TToken_string key_umart;
|
||
key_umart.add(codart);
|
||
key_umart.add(1);
|
||
const TString& um = cache().get(LF_UMART, key_umart, UMART_UM);
|
||
rmovmag.put(RMOVMAG_UM, um);
|
||
const TString& lotto = recset.get("CodiceLotto").as_string();
|
||
rmovmag.put(RMOVMAG_LIVGIAC, lotto);
|
||
|
||
real qta = recset.get("Qta[int]").as_real();
|
||
qta += recset.get("Qta[dec]").as_real() / CENTO;
|
||
rmovmag.put(RMOVMAG_QUANT, qta);
|
||
|
||
//quando non trova un BR con lo stesso numero di movimento significa che le righe sono finite!
|
||
go_on = recset.move_next();
|
||
|
||
if (go_on && (recset.get("TipoRecord").as_string() != "BR" || curr_movmag != recset.get("NumeroDoc").as_int()))
|
||
{
|
||
recset.move_prev(); //allora torna indietro di un record per riposizionarsi sull'ultimo non letto
|
||
go_on = false;
|
||
}
|
||
} //while(go_on)...
|
||
|
||
|
||
//incredibilmente arriva in fondo
|
||
TString msg;
|
||
msg << "Doc.: " << curr_movmag << " Terminale: " << codice_terminale;
|
||
//se pu<70> scrivere...
|
||
if (_can_write)
|
||
{
|
||
//alla fine della fiera salva il maggico movimento di magazzino
|
||
TLocalisamfile file_movmag(LF_MOVMAG);
|
||
int err = movmag.write(file_movmag);
|
||
|
||
if (err == NOERR)
|
||
{
|
||
msg.insert("Registrato mov. magazzino: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Impossibile registrare mov. magazzino: ", 0);
|
||
log.log(2, msg);
|
||
}
|
||
}
|
||
else //..senn<6E> avverte e basta
|
||
{
|
||
msg.insert("Controllato mov. magazzino: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
}
|
||
|
||
|
||
void TUpload2Campo::elabora_TF(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
const char rec_tipodoc = recset.get(DOC_TIPODOC).as_string()[0];
|
||
//i documenti di vendita annullati vanno ignorati
|
||
if (rec_tipodoc == 'A' || rec_tipodoc == 'N' || rec_tipodoc <= ' ')
|
||
return;
|
||
|
||
//1) codice terminale (lungo 3) e codice agente (lungo 5)
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
const TString& codice_agente = check_agente(codice_terminale, log);
|
||
const TString8 codmag = cache().get(LF_AGENTI, codice_agente, AGE_CODMAG);
|
||
check_magazzino(codmag, log);
|
||
|
||
//2) Testata documento
|
||
//genera una simpatico documento di cui raccatta la chiave
|
||
const TString& str_datadoc = recset.get(DOC_DATADOC).as_string();
|
||
const TDate datadoc = upload_format_date6(str_datadoc);
|
||
|
||
//2a) tipo documento
|
||
TString4 tipodoc;
|
||
switch (rec_tipodoc)
|
||
{
|
||
case 'F': tipodoc = ini_get_string(CONFIG_DITTA, "ha", "InpFatTip"); break; //Fatture
|
||
case 'B': tipodoc = ini_get_string(CONFIG_DITTA, "ha", "InpBolTip"); break; //Bolle
|
||
case 'V': tipodoc = ini_get_string(CONFIG_DITTA, "ha", "InpValTip"); break; //bolle Valorizzate: attenzione!! devono essere trasformate in 'B'olle alla creazione della numerazione di Campo
|
||
case 'O': tipodoc = ini_get_string(CONFIG_DITTA, "ha", "InpOrdTip"); break; //Ordini
|
||
default:
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Tipo documento in input " << rec_tipodoc << " sconosciuto";
|
||
log.log(2, msg);
|
||
}
|
||
break;
|
||
}
|
||
//2b) numerazione documento
|
||
//il codnum dipende dal tipo documento del terminale (F,B,O...) e dal codice del terminale
|
||
//se tipo 'V' va cambiato in tipo 'B' in quanto le bolle valorizzate sono normali bolle in Campo
|
||
const char key_td = rec_tipodoc == 'V' ? 'B' : rec_tipodoc;
|
||
TString4 codnum;
|
||
codnum << key_td << codice_terminale;
|
||
const TString& numerazione = cache().get("%NUM", codnum, "CODTAB");
|
||
if (numerazione != codnum)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "Codice numerazione " << codnum << " sconosciuto";
|
||
log.log(2, msg);
|
||
}
|
||
|
||
const long ndoc = recset.get(DOC_NDOC).as_int();
|
||
|
||
TDocumento doc;
|
||
doc.read('D', datadoc.year(), codnum, ndoc, _isequal, _can_write ? _lock : _nolock);
|
||
|
||
//2c) tipo documento e data documento
|
||
doc.put(DOC_TIPODOC, tipodoc);
|
||
TTipo_documento td(tipodoc);
|
||
const TString& caus_movmag = td.caus_mov();
|
||
doc.put(DOC_CAUSMAG, caus_movmag);
|
||
|
||
doc.put(DOC_DATADOC, datadoc);
|
||
|
||
//2d) cliente e campi collegati via cli2doc()
|
||
doc.put(DOC_TIPOCF, "C");
|
||
|
||
//dato il codice cliente sul recordset (stringa di 6) risale al codice di Campo (long di 6) stabilendo..
|
||
//..eventuali relazioni con i clienti nuovi (con '*') importati nei record VC all'inizio della procedura
|
||
const TString8 str_codcf = recset.get(DOC_CODCF).as_string();
|
||
long codcf = check_cliente(str_codcf, log);
|
||
|
||
doc.put(DOC_CODCF, codcf);
|
||
doc.put(DOC_CODCFFATT, recset.get(DOC_CODCFFATT).as_int());
|
||
|
||
//usa la cli2doc per riempire tutti i campi legati al cliente
|
||
TCli_for clifor('C', codcf);
|
||
clifor.cli2doc(doc);
|
||
|
||
//sconto in fattura, sconto totale, che cazzo sono?
|
||
//TString8 scontone = recset.get();
|
||
|
||
//codice pagamento (su terminalino <20> lungo 2, da noi 3 e lo vogliamo zero-filled; mah?!)
|
||
TString4 str_codpag = recset.get(DOC_CODPAG).as_string();
|
||
str_codpag.right_just(3, '0');
|
||
doc.put(DOC_CODPAG, str_codpag);
|
||
//incasso (importo pagato)
|
||
const real incasso = recset.get("Incasso").as_real() / CENTO;
|
||
doc.put(DOC_IMPPAGATO, incasso);
|
||
|
||
//data spedizione...datapart o datacons? (solo per ordini)
|
||
|
||
//al simpatico documento appiccia tutte le righe RF che seguono il record TF..
|
||
//..dopo il magico ordinamento iniziale del recordset
|
||
//intanto azzera le righe eventualmente gi<67> presenti (riscrittura)
|
||
doc.destroy_rows();
|
||
|
||
|
||
//3) righe documento
|
||
//scansione delle righe documento su record RF
|
||
while (recset.move_next())
|
||
{
|
||
if (recset.get("TipoRecord").as_string() != "RF") //quando non trova un RF significa che le righe della testata sono finite!
|
||
{
|
||
recset.move_prev(); //allora torna indietro di un record per riposizionarsi sull'ultimo non letto
|
||
break;
|
||
}
|
||
|
||
//agginunge una nuova riga (solo merce, per quanto ne sappiamo)
|
||
TRiga_documento& rigadoc = doc.new_row("01");
|
||
|
||
//3a) tipo cessione (fa cambiare il tipo riga o la causale di riga)
|
||
const char tipocess = recset.get("TipoCessione").as_string()[0];
|
||
switch (tipocess)
|
||
{
|
||
case 'V': break;
|
||
case 'O':
|
||
rigadoc.put(RDOC_TIPORIGA, "09");
|
||
rigadoc.put(RDOC_ADDIVA, "X");
|
||
rigadoc.put(RDOC_CAUSMAG, "OMA");
|
||
break;
|
||
case 'R': break;
|
||
case 'S': break;
|
||
default : break;
|
||
}
|
||
|
||
//serie delle put sulla riga documento; ricordiamo che la chiave della riga viene riempita dalla new_row
|
||
//3a) articolo
|
||
TString8 codart = recset.get(RDOC_CODART).as_string();
|
||
TString80 descr = check_articolo(codart, log);
|
||
if (tipocess == 'O')
|
||
descr << " (OMAGGIO)";
|
||
|
||
rigadoc.put(RDOC_CODART, codart);
|
||
rigadoc.put(RDOC_CODARTMAG, codart);
|
||
rigadoc.put(RDOC_CHECKED, "X");
|
||
rigadoc.put(RDOC_DESCR, descr);
|
||
|
||
//3b) umart e qta
|
||
const TString& umqta = recset.get(RDOC_UMQTA).as_string();
|
||
TLocalisamfile file_umart(LF_UMART);
|
||
file_umart.setkey(2);
|
||
file_umart.put(UMART_CODART, codart);
|
||
file_umart.put(UMART_UM, umqta);
|
||
const int err_umart = file_umart.read();
|
||
if (err_umart != NOERR)
|
||
{
|
||
_can_write = false;
|
||
TString msg;
|
||
msg << "U.m. " << umqta << " dell'articolo " << codart << " sconosciuta";
|
||
log.log(2, msg);
|
||
}
|
||
rigadoc.put(RDOC_UMQTA, umqta);
|
||
|
||
real qta = recset.get("Qta[int]").as_real();
|
||
qta += recset.get("Qta[dec]").as_real() / CENTO;
|
||
rigadoc.put(RDOC_QTA, qta);
|
||
|
||
//panegirico sugli sconti
|
||
TString str_sconto;
|
||
real sconto[4];
|
||
sconto[0] = recset.get("Sconto1").as_real();
|
||
sconto[1] = recset.get("Sconto2").as_real();
|
||
sconto[2] = recset.get("Sconto3").as_real();
|
||
sconto[3] = recset.get("ScontoLibero").as_real();
|
||
for (int s = 0; s < 4; s++)
|
||
{
|
||
if (!sconto[s].is_zero())
|
||
str_sconto << real(sconto[s] / CENTO) << '+';
|
||
}
|
||
str_sconto.rtrim(1);
|
||
|
||
rigadoc.put(RDOC_SCONTO, str_sconto);
|
||
|
||
//prezzi
|
||
real prezzo_lordo = recset.get(RDOC_PREZZO).as_real();
|
||
prezzo_lordo /= 1000;
|
||
rigadoc.put(RDOC_PREZZO, prezzo_lordo);
|
||
|
||
//3x) iva
|
||
const int aliquota_iva = recset.get("AliquotaIva").as_int();
|
||
TString4 codiva;
|
||
//il codice lo si trova nella configurazione del modulo Ha (c'<27> un magico sheet apposito)
|
||
TConfig config(CONFIG_DITTA, "ha");
|
||
TString curr_name;
|
||
for (int j = 0; ; j++)
|
||
{
|
||
const real curr_aliq_iva = config.get("IVAaliquota", NULL, j);
|
||
if (curr_aliq_iva.is_zero())
|
||
break;
|
||
if (curr_aliq_iva.integer() == aliquota_iva)
|
||
{
|
||
codiva = config.get("IVAcodice", NULL, j);
|
||
break;
|
||
}
|
||
}
|
||
|
||
rigadoc.put(RDOC_CODIVA, codiva);
|
||
rigadoc.put(RDOC_LIVELLO, recset.get("CodiceLotto").as_string());
|
||
rigadoc.put(RDOC_CODMAG, codmag); //questo viene dall'agente ed <20> stato preso all'inizio del metodo
|
||
}
|
||
|
||
/* Commentato in quanto sfuggono molti errori veri 10-10-2014
|
||
const real totdoc = doc.totale_doc();
|
||
if (totdoc.is_zero())
|
||
doc.put(DOC_STATO, 5); // Evita problemi di contabilizzazione dei documenti nulli
|
||
*/
|
||
|
||
//incredibilmente arriva in fondo
|
||
TString msg;
|
||
msg << datadoc.year() << "-" << codnum << "-" << ndoc
|
||
<< " Terminale: " << codice_terminale << " Cliente: " << codcf;
|
||
//se pu<70> scrivere...
|
||
if (_can_write)
|
||
{
|
||
int err = doc.write();
|
||
|
||
if (err == NOERR)
|
||
{
|
||
msg.insert("Registrato documento: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Impossibile registrare documento: ", 0);
|
||
log.log(2, msg);
|
||
}
|
||
}
|
||
else //..senn<6E> avverte e basta
|
||
{
|
||
msg.insert("Controllato documento: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
|
||
if (!incasso.is_zero() && rec_tipodoc == 'V') // Incasso su bolla valorizzata
|
||
{
|
||
const TRecnotype old_pos = recset.current_row();
|
||
recset.new_rec("SI");
|
||
recset.set("CodiceTerminale", codice_terminale);
|
||
recset.set("CodiceCliente", str_codcf);
|
||
TString16 numfatt; numfatt.format("%ld/%02d", ndoc, atoi(codice_terminale));
|
||
recset.set("NumeroFattura", numfatt);
|
||
recset.set("DataFattura", hd_format_date6(datadoc));
|
||
recset.set("ImportoIncassato", real(incasso * CENTO));
|
||
recset.set("DataIncasso", hd_format_date6(datadoc));
|
||
TString16 partita; partita.format("%04d-%4ld/%02d", datadoc.year(), ndoc, atoi(codice_terminale));
|
||
recset.set("Partita", partita);
|
||
recset.set("TipoDocumento", "V");
|
||
recset.set("DataEmissione", hd_format_date6(datadoc));
|
||
recset.move_to(old_pos);
|
||
|
||
msg.format("Generazione anticipo di %s su bolla valorizzata %s", incasso.stringa(0, 2), (const char*)partita);
|
||
log.log(0, msg);
|
||
}
|
||
}
|
||
|
||
|
||
void TUpload2Campo::elabora_RC(THardy_upload_recordset& recset, TLog_report& log)
|
||
{
|
||
//1) codice terminale (lungo 3) e codice agente (lungo 5)
|
||
TString4 codice_terminale = recset.get("CodiceTerminale").as_string();
|
||
const TString& codice_agente = check_agente(codice_terminale, log);
|
||
const TRectype& rec_agente = cache().get(LF_AGENTI, codice_agente);
|
||
const TString8 codmag = rec_agente.get(AGE_CODMAG);
|
||
const long codcf = rec_agente.get_long(AGE_CODFORN); //cliente (legato all'agente)
|
||
|
||
//2) Testata documento
|
||
const TString& str_datadoc = recset.get("DataCarico").as_string();
|
||
const TDate datadoc = upload_format_date6(str_datadoc);
|
||
const int anno = datadoc.year();
|
||
|
||
//2a) numerazione e tipo documento
|
||
TConfig hardy(CONFIG_DITTA, "ha");
|
||
const TString4 codnum = hardy.get("CarDocNum");
|
||
const TString4 tipodoc = hardy.get("CarDocTip");
|
||
|
||
//2b) documento vero e proprio (stessi campi del caso tipo record = TF)
|
||
TDocumento doc;
|
||
|
||
doc.put(DOC_CODNUM, codnum);
|
||
doc.put(DOC_ANNO, anno);
|
||
doc.put(DOC_PROVV, "D");
|
||
doc.put(DOC_TIPODOC, tipodoc);
|
||
doc.put(DOC_STATO, "1");
|
||
doc.put(DOC_DATADOC, datadoc);
|
||
doc.put(DOC_TIPOCF, "C");
|
||
doc.put(DOC_CODCF, codcf);
|
||
|
||
TTipo_documento td(tipodoc);
|
||
const TString& caus_movmag = td.caus_mov();
|
||
doc.put(DOC_CAUSMAG, caus_movmag);
|
||
|
||
TCli_for clifor('C', codcf);
|
||
clifor.cli2doc(doc);
|
||
|
||
doc.destroy_rows();
|
||
|
||
// righe documento di carico
|
||
bool go_on = true;
|
||
//scansione delle righe documento su record RC
|
||
while (go_on)
|
||
{
|
||
//3) crea le righe (legge tutti i record di tipo RC successivi)
|
||
TRiga_documento& rigadoc = doc.new_row("01");
|
||
|
||
//serie delle put sulla riga documento; ricordiamo che la chiave della riga viene riempita dalla new_row
|
||
//3a) articolo, um, codmag
|
||
TString8 codart = recset.get("CodiceArticolo").as_string();
|
||
const TString& descr = check_articolo(codart, log);
|
||
|
||
rigadoc.put(RDOC_CODART, codart);
|
||
rigadoc.put(RDOC_CODARTMAG, codart);
|
||
rigadoc.put(RDOC_CHECKED, "X");
|
||
rigadoc.put(RDOC_DESCR, descr);
|
||
|
||
TToken_string key_umart;
|
||
key_umart.add(codart);
|
||
key_umart.add(1);
|
||
const TString& um = cache().get(LF_UMART, key_umart, UMART_UM);
|
||
rigadoc.put(RDOC_UMQTA, um);
|
||
|
||
const real qta = recset.get("Quantita").as_real() / CENTO;
|
||
rigadoc.put(RDOC_QTA, qta);
|
||
|
||
rigadoc.put(RDOC_CODMAG, codmag);
|
||
|
||
//quando non trova un RC significa che le righe sono finite!
|
||
go_on = recset.move_next();
|
||
|
||
if (go_on && (recset.get("TipoRecord").as_string() != "RC"))
|
||
{
|
||
recset.move_prev(); //allora torna indietro di un record per riposizionarsi sull'ultimo non letto
|
||
go_on = false;
|
||
}
|
||
}
|
||
|
||
//incredibilmente arriva in fondo
|
||
TString msg;
|
||
msg << anno << "-" << codnum << " Terminale: " << codice_terminale << " Cliente: " << codcf;
|
||
//se pu<70> scrivere...
|
||
if (_can_write)
|
||
{
|
||
int err = doc.write();
|
||
|
||
if (err == NOERR)
|
||
{
|
||
msg.insert("Registrato documento di carico: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
else
|
||
{
|
||
msg.insert("Impossibile registrare documento di carico: ", 0);
|
||
log.log(2, msg);
|
||
}
|
||
}
|
||
else //..senn<6E> avverte e basta
|
||
{
|
||
msg.insert("Controllato documento di carico: ", 0);
|
||
log.log(0, msg);
|
||
}
|
||
}
|
||
|
||
static int upload_cmp(const TSortable& o1, const TSortable& o2, void* jolly)
|
||
{
|
||
const TFilename f1 = (const TString&)o1;
|
||
const TFixed_string s1 = f1.ext()+1;
|
||
if (s1.empty())
|
||
return +1;
|
||
|
||
const TFilename f2 = (const TString&)o2;
|
||
const TFixed_string s2 = f2.ext()+1;
|
||
if (s2.empty())
|
||
return -1;
|
||
|
||
TToken_string d1(s1, '_');
|
||
TToken_string d2(s2, '_');
|
||
|
||
int cmp = 0;
|
||
|
||
const int seq[6] = { 2, 1, 0, 3, 4, 5 }; // upload.dGG_MM_AAAA_hh_mm_ss
|
||
for (int i = 0; i < 6 && cmp == 0; i++)
|
||
{
|
||
const int tok = seq[i];
|
||
cmp = d1.get_int(tok) - d2.get_int(tok);
|
||
}
|
||
|
||
return cmp;
|
||
}
|
||
|
||
void TUpload2Campo::elabora(const TMask& mask, TLog_report& log)
|
||
{
|
||
/* Per il momento preferiscono agire manualmente
|
||
// a) stoppa il concentratore
|
||
chiudi_concentratore();
|
||
|
||
// b) scarica il concentratore per generare il file upload.d
|
||
bool carica = scarica_concentratore();
|
||
|
||
// c) rilancia il concentratore in modalit<69> trasmissione
|
||
trasmetti_concentratore();
|
||
|
||
// d) esegue le elaborazioni
|
||
if (carica)
|
||
*/
|
||
{
|
||
//creazione del filename dei files da importare
|
||
TFilename src_files = _input_path;
|
||
//una volta si importavano tutti i files di tipo upload*.d; poi si <20> passati ad importare solo upload.d e basta!
|
||
src_files.add("upload.d*");
|
||
TString_array src_files_list;
|
||
|
||
int n_files_d = list_files(src_files, src_files_list);
|
||
if (n_files_d > 0)
|
||
{
|
||
src_files_list.TArray::sort(upload_cmp, NULL);
|
||
const TString& u = src_files_list.row(n_files_d-1);
|
||
if (u.ends_with(".d", true)) // Ignoro upload.d in quanto duplicato nell'ultimo upload.dGG_MM_AAAA_hh_mm_ss
|
||
n_files_d--;
|
||
}
|
||
|
||
TProgress_monitor pi(n_files_d, TR("Acquisizione upload in corso..."));
|
||
|
||
//scandisce i files uno ad uno
|
||
for (int i = 0; i < n_files_d; i++)
|
||
{
|
||
if (!pi.add_status())
|
||
break;
|
||
|
||
const TFilename curr_fname = src_files_list.row(i);
|
||
pi.set_text(curr_fname);
|
||
|
||
//file corrente in fase di elaborazione
|
||
|
||
THardy_upload_recordset recset(curr_fname);
|
||
const long items = recset.items();
|
||
//ordinamento del file in memoria secondo l'ordine stabilito nella tipi_record "SU|VC|TF|RF|SI|BR|RC";
|
||
recset.sort(ordina_upload);
|
||
|
||
TString msg;
|
||
|
||
//creazione progind e log
|
||
msg << "Elaborazione file " << curr_fname << " in corso...";
|
||
TProgress_monitor pi(items, msg);
|
||
|
||
msg.cut(0);
|
||
msg << "File " << curr_fname.name();
|
||
log.log(0, "");
|
||
log.log(0, msg);
|
||
log.log(0, "");
|
||
//parametro di controllo; solo se resta true fino alla fine il documento viene writato
|
||
//solo in caso di elaborazione definitiva pu<70> diventare true; vale per ogni upload*.d, in modo da archiviare..
|
||
//..quelli buoni
|
||
_can_write = false;
|
||
if (mask.get_bool(F_DEFINITIVO))
|
||
_can_write = true;
|
||
|
||
//codice terminalino; viene preso dal tipo record SU (<28> comunque presente in ogni tipo record) ed usato per l'archiviazione..
|
||
//..del file se correttamente importato
|
||
TString4 terminalino;
|
||
|
||
//giro su tutti i record del terribile recordset per l'acquisizione dei dati
|
||
for (bool ok = recset.move_first(); ok; ok = recset.move_next())
|
||
{
|
||
if (!pi.add_status())
|
||
break;
|
||
|
||
//acquisizione tipo record da riga corrente del file di input
|
||
TString4 tipo_record = recset.rec_type();
|
||
tipo_record.trim();
|
||
|
||
//Sequenza di ordinamento dei record "SU|VC|TF|RF|SI|BR|RC": NON ATTENTATEVI A CAMBIARLA O NON FUNZIONA PIU' UN CAZZO!!
|
||
const int pos = tipi_record.get_pos(tipo_record);
|
||
|
||
//trattazione dei vari tracciati record
|
||
switch (pos)
|
||
{
|
||
case 0: //tipo record: SU (SetUp...ovvero agente)
|
||
terminalino = elabora_SU(recset, log); //non serve a una cippa!
|
||
break;
|
||
case 1: //tipo record: VC (nuovi clienti e Variazioni Cliente)
|
||
elabora_VC(recset, log);
|
||
break;
|
||
case 2: //tipo record: TF (Testata Fattura)
|
||
elabora_TF(recset, log);
|
||
break;
|
||
case 3: //tipo record: RF (Riga Fattura)
|
||
//elabora_RF(recset, log); //non serve! lo fa l'elaborazione di testata
|
||
break;
|
||
case 4: //tipo record: SI (incasso documenti)
|
||
elabora_SI(recset, log);
|
||
break;
|
||
case 5: //tipo record: BR (righe movimenti magazzino)
|
||
elabora_BR(recset, log);
|
||
break;
|
||
case 6: //tipo record: RC (Richiesta Carico)
|
||
elabora_RC(recset, log);
|
||
break;
|
||
default: //se il tipo record non esiste nella lista dei tipi record si incazza e lo scrive!
|
||
{
|
||
TString msg;
|
||
msg << "Tipo record non riconosciuto '" << tipo_record << "' alla riga " << (recset.current_row() + 1);
|
||
log.log(2, msg);
|
||
}
|
||
break;
|
||
} //switch(pos)..
|
||
|
||
} //for (bool ok... (acquisizione di un file)
|
||
log.log(0, "");
|
||
|
||
//sequenza di archiviazione del file di upload se elaborato con successo in via definitiva
|
||
if (_can_write)
|
||
{
|
||
if (archivia_file_importato(_archive_path, curr_fname, terminalino, log))
|
||
{
|
||
msg.cut(0);
|
||
msg << "Archiviato file " << curr_fname.name_only();
|
||
log.log(0, msg);
|
||
}
|
||
}
|
||
|
||
} //for (int i = 0; i < n_files_d;... (giro su tutti i files tipo upload*.d)
|
||
|
||
} //if (carica)
|
||
}
|
||
|
||
TMask* TUpload2Campo::create_mask() const
|
||
{
|
||
TMask* mask = new TUpload2Campo_mask;
|
||
mask->set(F_INPUT_PATH, _input_path);
|
||
mask->set(F_ARCHIVE_PATH, _archive_path);
|
||
//mask->set(F_CONC_PATH, _conc_path);
|
||
//mask->set(F_TRANS_PATH, _trans_path);
|
||
return mask;
|
||
}
|
||
|
||
|
||
const char* TUpload2Campo::fake_trans_file() const
|
||
{ return "164"; }
|
||
|
||
int ha1300(int argc, char* argv[])
|
||
{
|
||
TUpload2Campo a;
|
||
a.run(argc, argv, TR("Importazione dati da file"));
|
||
return 0;
|
||
} |