Patch level : 10.0
Files correlati : lv4.exe lv4300a.msk Ricompilazione Demo : [ ] Commento : Corretta importazione pagamenti e note di credito. git-svn-id: svn://10.65.10.50/trunk@19904 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
d25469a8be
commit
ecf707ab57
328
lv/lv4200.cpp
328
lv/lv4200.cpp
@ -27,29 +27,46 @@ enum CGC_SALDAC { CGC_NULL, CGC_TIPOCF, CGC_ANNO, CGC_NUMPART, CGC_C
|
|||||||
|
|
||||||
class TCausali_cache : public TCache
|
class TCausali_cache : public TCache
|
||||||
{
|
{
|
||||||
|
TString4 _cln, _frn;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual TObject* key2obj(const char* key);
|
virtual TObject* key2obj(const char* key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const TCausale& causale(const char* codice, int annoiva);
|
const TCausale& causale(char tipocf, tipo_movimento tm, const TDate& datadoc);
|
||||||
|
void init(const char* cln, const char* frn) { _cln = cln; _frn = frn; }
|
||||||
};
|
};
|
||||||
|
|
||||||
TObject* TCausali_cache::key2obj(const char* key)
|
TObject* TCausali_cache::key2obj(const char* key)
|
||||||
{
|
{
|
||||||
// Metodo bastardo per evitare TToken_string temporanee "a randa"
|
const char tipocf = key[0];
|
||||||
// sfrutto chiave a lunghezza fissa
|
const tipo_movimento tm = tipo_movimento(key[1]-'0');
|
||||||
const int anno = atoi(key);
|
int anno = atoi(key + 2);
|
||||||
const char* codice = key+5;
|
if (anno <= 0)
|
||||||
TCausale* pcaus = new TCausale(codice, anno);
|
anno = TDate(TODAY).year();
|
||||||
|
|
||||||
|
TString4 codcaus;
|
||||||
|
if (tm == tm_fattura)
|
||||||
|
codcaus = tipocf == 'F' ? _frn : _cln;
|
||||||
|
if (codcaus.blank())
|
||||||
|
{
|
||||||
|
TString query;
|
||||||
|
query << "USE CAUS\nSELECT (TIPOMOV='" << tm << "')&&(RCAUS->TIPOCF='" << tipocf << "')"
|
||||||
|
<< "\nJOIN RCAUS INTO CODCAUS=CODCAUS NRIGA=1";
|
||||||
|
TISAM_recordset caus(query);
|
||||||
|
if (caus.move_first())
|
||||||
|
codcaus = caus.get(CAU_CODCAUS).as_string();
|
||||||
|
}
|
||||||
|
TCausale* pcaus = new TCausale(codcaus, anno);
|
||||||
return pcaus;
|
return pcaus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TCausale& TCausali_cache::causale(const char* codice, int annoiva)
|
const TCausale& TCausali_cache::causale(const char tipocf, tipo_movimento tm, const TDate& datadoc)
|
||||||
{
|
{
|
||||||
// Metodo bastardo per evitare TToken_string temporanee "a randa"
|
// Metodo bastardo per evitare TToken_string temporanee "a randa"
|
||||||
// creo chiave a lunghezza fissa anno+codice = 9999|AAA
|
// creo chiave a lunghezza fissa TIPOCF+TIPOMOV = C1
|
||||||
TString8 key;
|
TString8 key;
|
||||||
key.format("%04d|%s", annoiva, codice);
|
key.format("%c%1d%4d" , tipocf, tm, datadoc.year());
|
||||||
return *(const TCausale*)objptr(key);
|
return *(const TCausale*)objptr(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +97,7 @@ bool TImporta_sc_mask::on_field_event(TOperable_field& f, TField_event e, long j
|
|||||||
{
|
{
|
||||||
TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32");
|
TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32");
|
||||||
TFilename path = get(F_PATH);
|
TFilename path = get(F_PATH);
|
||||||
path.add("*.txt"); //files delle testate
|
path.add("*.txt"); //file da importare
|
||||||
list_files(path, as.rows_array());
|
list_files(path, as.rows_array());
|
||||||
TFilename name;
|
TFilename name;
|
||||||
FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
|
FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
|
||||||
@ -112,12 +129,13 @@ class TImporta_sc : public TSkeleton_application
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm);
|
void nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm);
|
||||||
|
bool paga_rata(TPartita& game, int nrata, int nrigp, real& importo) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool log_error(TLog_report& log, const char* msg, const TRecordset& recset);
|
bool log_error(TLog_report& log, const char* msg, const TRecordset& recset);
|
||||||
const TString& find_causale(char tipocf, tipo_movimento tm) const;
|
const TCausale& causale(char tipocf, tipo_movimento tm, const TDate& datadoc);
|
||||||
char get_tmcf(int gruppo, int conto) const;
|
char get_tmcf(int gruppo, int conto) const;
|
||||||
bool find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto) const;
|
bool find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto);
|
||||||
|
|
||||||
TRiga_partite& nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game);
|
TRiga_partite& nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game);
|
||||||
void nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game);
|
void nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game);
|
||||||
@ -125,34 +143,20 @@ protected:
|
|||||||
void nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game);
|
void nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game);
|
||||||
void nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game);
|
void nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game);
|
||||||
bool nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log);
|
bool nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log);
|
||||||
void salva_partita(TPartita*& game, bool can_write);
|
void salva_partita(TPartita*& game);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool create();
|
virtual bool create();
|
||||||
virtual bool destroy();
|
virtual bool destroy();
|
||||||
virtual void main_loop();
|
virtual void main_loop();
|
||||||
void transfer(const TFilename& file, bool can_write);
|
void transfer(const TFilename& file);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TString& TImporta_sc::find_causale(char tipocf, tipo_movimento tm) const
|
// Cerca una causale appropriata in base a TIPOCF (C o F) e TIPOMOV (1, 2, 3, ...)
|
||||||
{
|
const TCausale& TImporta_sc::causale(char tipocf, tipo_movimento tm, const TDate& datadoc)
|
||||||
TString4 codcaus;
|
{ return _cache_causali.causale(tipocf, tm, datadoc); }
|
||||||
if (tm == tm_fattura)
|
|
||||||
codcaus = _msk->get(tipocf == 'F' ? F_CODCAUSF : F_CODCAUSC);
|
|
||||||
if (codcaus.blank())
|
|
||||||
{
|
|
||||||
TString query;
|
|
||||||
query << "USE CAUS\nSELECT (TIPOMOV='" << tm << "')&&(RCAUS->TIPOCF='" << tipocf << "')"
|
|
||||||
<< "\nJOIN RCAUS INTO CODCAUS=CODCAUS NRIGA=1";
|
|
||||||
TISAM_recordset caus(query);
|
|
||||||
if (caus.move_first())
|
|
||||||
codcaus = caus.get(CAU_CODCAUS).as_string();
|
|
||||||
}
|
|
||||||
if (codcaus.full())
|
|
||||||
return get_tmp_string() = codcaus;
|
|
||||||
return EMPTY_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Ricava il campo TMCF (Cliente o Fornitore) di un dato conto
|
||||||
char TImporta_sc::get_tmcf(int gruppo, int conto) const
|
char TImporta_sc::get_tmcf(int gruppo, int conto) const
|
||||||
{
|
{
|
||||||
char tmcf = ' ';
|
char tmcf = ' ';
|
||||||
@ -165,38 +169,37 @@ char TImporta_sc::get_tmcf(int gruppo, int conto) const
|
|||||||
return tmcf;
|
return tmcf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TImporta_sc::find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto) const
|
// Trova il conto cliente di una certa anagrafica
|
||||||
|
bool TImporta_sc::find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
TString8 key;
|
TString8 key;
|
||||||
gruppo = conto = 0;
|
gruppo = conto = 0;
|
||||||
|
|
||||||
|
// Prima lo cerca sull'anagrafica stessa
|
||||||
key.format("%c|%ld", tipocf, sottoconto);
|
key.format("%c|%ld", tipocf, sottoconto);
|
||||||
const TRectype& clifo = cache().get(LF_CLIFO, key);
|
const TRectype& clifo = cache().get(LF_CLIFO, key);
|
||||||
gruppo = clifo.get_int(CLI_GRUPPO);
|
gruppo = clifo.get_int(CLI_GRUPPO);
|
||||||
conto = clifo.get_int(CLI_CONTO);
|
conto = clifo.get_int(CLI_CONTO);
|
||||||
|
|
||||||
|
// Controlla che il conto esista
|
||||||
found = get_tmcf(gruppo, conto) == tipocf;
|
found = get_tmcf(gruppo, conto) == tipocf;
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
const TString4 codcaus = find_causale(tipocf, tm_fattura);
|
// Cerca sulla prima riga dellla causale
|
||||||
if (codcaus.full())
|
const TDate datadoc(TODAY);
|
||||||
{
|
const TCausale& caus = causale(tipocf, tm_fattura, datadoc);
|
||||||
key.format("%s|1", (const char*)codcaus);
|
TBill bill; caus.bill(1, bill);
|
||||||
const TRectype& rcaus = cache().get(LF_RCAUSALI, key);
|
gruppo = bill.gruppo();
|
||||||
if (rcaus.get_char(RCA_TIPOCF) == tipocf)
|
conto = bill.conto();
|
||||||
{
|
found = get_tmcf(gruppo, conto) == tipocf;
|
||||||
gruppo = rcaus.get_int(RCA_GRUPPO);
|
|
||||||
conto = rcaus.get_int(RCA_CONTO);
|
|
||||||
found = get_tmcf(gruppo, conto) == tipocf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
// Usa un conto C/F trovato preventivamente in fase di inizializzazione
|
||||||
if (tipocf == 'C')
|
if (tipocf == 'C')
|
||||||
{
|
{
|
||||||
gruppo = _clienti.gruppo();
|
gruppo = _clienti.gruppo();
|
||||||
@ -213,7 +216,7 @@ bool TImporta_sc::find_clifo_bill(char tipocf, int& gruppo, int& conto, long sot
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Aggiunge una nuova riga fattura a 'game' in base ai dati in 'recset'
|
||||||
TRiga_partite& TImporta_sc::nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game)
|
TRiga_partite& TImporta_sc::nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game)
|
||||||
{
|
{
|
||||||
int nriga = game.prima_fattura();
|
int nriga = game.prima_fattura();
|
||||||
@ -227,11 +230,10 @@ TRiga_partite& TImporta_sc::nuova_fattura(const TImporta_cogeco_recset& recset,
|
|||||||
fattura.put(PART_DESCR, TR("*** Fattura gnerata da COGECO ***"));
|
fattura.put(PART_DESCR, TR("*** Fattura gnerata da COGECO ***"));
|
||||||
|
|
||||||
const char tipocf = game.conto().tipo();
|
const char tipocf = game.conto().tipo();
|
||||||
const TString& codcaus = find_causale(tipocf, tm_fattura);
|
const TCausale& caus = causale(tipocf, tm_fattura, datadoc);
|
||||||
if (codcaus.full())
|
if (caus.ok())
|
||||||
{
|
{
|
||||||
const TCausale& caus = _cache_causali.causale(codcaus, game.anno());
|
fattura.put(PART_CODCAUS, caus.codice());
|
||||||
fattura.put(PART_CODCAUS, codcaus);
|
|
||||||
fattura.put(PART_REG, caus.reg().name());
|
fattura.put(PART_REG, caus.reg().name());
|
||||||
fattura.put(PART_TIPOMOV, caus.tipomov());
|
fattura.put(PART_TIPOMOV, caus.tipomov());
|
||||||
fattura.put(PART_SEZ, caus.sezione(1));
|
fattura.put(PART_SEZ, caus.sezione(1));
|
||||||
@ -246,21 +248,25 @@ TRiga_partite& TImporta_sc::nuova_fattura(const TImporta_cogeco_recset& recset,
|
|||||||
|
|
||||||
TRiga_partite& fattura = game.riga(nriga);
|
TRiga_partite& fattura = game.riga(nriga);
|
||||||
const real importo = recset.get_real(CGC_IMPORTO);
|
const real importo = recset.get_real(CGC_IMPORTO);
|
||||||
|
|
||||||
|
fattura.add(PART_IMPTOTDOC, importo);
|
||||||
fattura.add(PART_IMPORTO, importo);
|
fattura.add(PART_IMPORTO, importo);
|
||||||
|
|
||||||
return fattura;
|
return fattura;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Aggiunge una nuova rata alla UNICA fattura di 'game'.
|
||||||
|
// Attenzione: in assenza di fattura ne viene creata una "al volo" di pari importo.
|
||||||
void TImporta_sc::nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game)
|
void TImporta_sc::nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game)
|
||||||
{
|
{
|
||||||
int nriga = game.prima_fattura();
|
int nriga = game.prima_fattura(); // PART_NRIGA della fattura (solitamente = 1)
|
||||||
if (nriga <= 0)
|
if (nriga <= 0) // Se non ci sono fattura in questa partita ...
|
||||||
{
|
{
|
||||||
nuova_fattura(recset, game);
|
nuova_fattura(recset, game); // Creo una nuova fattura
|
||||||
nriga = game.prima_fattura();
|
nriga = game.prima_fattura(); // Aggiorno PART_NRIGA che valeva -1
|
||||||
}
|
}
|
||||||
TRiga_partite& fattura = game.riga(nriga);
|
TRiga_partite& fattura = game.riga(nriga); // Accedo alla riga di fattura, che ora DEVE esistere!
|
||||||
TRiga_scadenze& scadenza = fattura.new_row();
|
TRiga_scadenze& scadenza = fattura.new_row(); // Creo nuova rata, alla faccia di SCAD_CODPAG
|
||||||
|
|
||||||
const real importo = recset.get_real(CGC_IMPORTO);
|
const real importo = recset.get_real(CGC_IMPORTO);
|
||||||
scadenza.put(SCAD_DATASCAD, recset.get_date(CGC_SCADENZA));
|
scadenza.put(SCAD_DATASCAD, recset.get_date(CGC_SCADENZA));
|
||||||
@ -268,10 +274,40 @@ void TImporta_sc::nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita&
|
|||||||
scadenza.put(SCAD_DESCR, TR("*** Rata generata da COGECO ***"));
|
scadenza.put(SCAD_DESCR, TR("*** Rata generata da COGECO ***"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TImporta_sc::paga_rata(TPartita& game, int nrata, int nrigp, real& importo) const
|
||||||
|
{
|
||||||
|
const int nriga = game.prima_fattura();
|
||||||
|
if (nriga > 0)
|
||||||
|
{
|
||||||
|
const TRiga_partite& fattura = game.riga(nriga);
|
||||||
|
TRiga_scadenze& scadenza = fattura.rata(nrata);
|
||||||
|
const real residuo = scadenza.residuo(false).valore();
|
||||||
|
if (!residuo.is_zero()) // Considera solo rate aperte
|
||||||
|
{
|
||||||
|
// Elenco dei campi chiave da riportare dalla rata al pagamento
|
||||||
|
const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART,
|
||||||
|
PAGSCA_NRIGA, PAGSCA_NRATA, NULL };
|
||||||
|
const real pagare = residuo > importo ? importo : residuo; // Importo da pagare sulla rata
|
||||||
|
TRectype rpag(LF_PAGSCA);
|
||||||
|
for (int k = 0; field[k]; k++)
|
||||||
|
rpag.put(field[k], scadenza.get(field[k]));
|
||||||
|
rpag.put(PAGSCA_NRIGP, nrigp); // Completa la chiave di PAGSCA col numero riga di partita
|
||||||
|
rpag.put(PAGSCA_IMPORTO, pagare);
|
||||||
|
const TValuta euro;
|
||||||
|
game.modifica_pagamento(rpag, euro, true); // Speriamo che faccia tutto lei :-)
|
||||||
|
importo -= pagare;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggiunge una nuova riga tipo 2 (n.c.) o 3 (pag.) alla partita
|
||||||
void TImporta_sc::nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm)
|
void TImporta_sc::nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm)
|
||||||
{
|
{
|
||||||
|
// Crea una nuova riga di partita
|
||||||
TRiga_partite& pagamento = game.new_row();
|
TRiga_partite& pagamento = game.new_row();
|
||||||
const int nrigp = pagamento.get_int(PART_NRIGA);
|
const int nrigp = pagamento.get_int(PART_NRIGA); // Ricorda numero da mettere in PAGSCA_NRIGP
|
||||||
|
|
||||||
const TDate datadoc = recset.get_date(CGC_DATADOC);
|
const TDate datadoc = recset.get_date(CGC_DATADOC);
|
||||||
pagamento.put(PART_DATAREG, datadoc);
|
pagamento.put(PART_DATAREG, datadoc);
|
||||||
@ -281,12 +317,12 @@ void TImporta_sc::nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, T
|
|||||||
else
|
else
|
||||||
pagamento.put(PART_DESCR, TR("*** Pagamento generato da COGECO ***"));
|
pagamento.put(PART_DESCR, TR("*** Pagamento generato da COGECO ***"));
|
||||||
|
|
||||||
|
// Cerca di inizlizzare la riga con una causale appropriata
|
||||||
const char tipocf = game.conto().tipo();
|
const char tipocf = game.conto().tipo();
|
||||||
const TString& codcaus = find_causale(tipocf, tm);
|
const TCausale& caus = causale(tipocf, tm, datadoc);
|
||||||
if (codcaus.full())
|
if (caus.ok())
|
||||||
{
|
{
|
||||||
const TCausale& caus = _cache_causali.causale(codcaus, game.anno());
|
pagamento.put(PART_CODCAUS, caus.codice());
|
||||||
pagamento.put(PART_CODCAUS, codcaus);
|
|
||||||
pagamento.put(PART_REG, caus.reg().name());
|
pagamento.put(PART_REG, caus.reg().name());
|
||||||
pagamento.put(PART_TIPOMOV, caus.tipomov());
|
pagamento.put(PART_TIPOMOV, caus.tipomov());
|
||||||
pagamento.put(PART_SEZ, caus.sezione(1));
|
pagamento.put(PART_SEZ, caus.sezione(1));
|
||||||
@ -294,87 +330,112 @@ void TImporta_sc::nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, T
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
pagamento.put(PART_TIPOMOV, tm);
|
pagamento.put(PART_TIPOMOV, tm);
|
||||||
pagamento.put(PART_SEZ, tipocf == 'F' ? 'A' : 'D');
|
pagamento.put(PART_SEZ, tipocf == 'F' ? 'D' : 'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Somma da distribuire sulle rate aperte
|
||||||
real importo = recset.get_real(CGC_IMPORTO);
|
real importo = recset.get_real(CGC_IMPORTO);
|
||||||
pagamento.put(PART_IMPORTO, importo);
|
pagamento.put(PART_IMPTOTDOC, importo);
|
||||||
|
|
||||||
const TValuta euro;
|
// Se esiste una fattura cerca di saldare il residuo delle rate aperte
|
||||||
const int nriga = game.prima_fattura();
|
const int nriga = game.prima_fattura();
|
||||||
if (nriga > 0)
|
if (nriga > 0)
|
||||||
{
|
{
|
||||||
const TRiga_partite& fattura = game.riga(nriga);
|
const TRiga_partite& fattura = game.riga(nriga);
|
||||||
for (int nrata = 1; nrata <= fattura.rate() && !importo.is_zero(); nrata++)
|
|
||||||
|
// Si assicura che la sezione sia inversa rispetto alla fattura
|
||||||
|
pagamento.put(PART_SEZ, fattura.sezione() == 'D' ? 'A' : 'D');
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
TRiga_scadenze& scadenza = fattura.rata(nrata);
|
int best_rata = 0, best_score = 0;
|
||||||
const real residuo = scadenza.residuo(false).valore();
|
for (int nrata = 1; nrata <= fattura.rate() && !importo.is_zero(); nrata++)
|
||||||
if (!residuo.is_zero())
|
|
||||||
{
|
{
|
||||||
const real pagare = residuo > importo ? importo : residuo;
|
const TRiga_scadenze& rata = fattura.rata(nrata);
|
||||||
TRectype rpag(LF_PAGSCA);
|
const real residuo = rata.residuo(false).valore();
|
||||||
const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART,
|
const TDate data_scad = rata.get(SCAD_DATASCAD);
|
||||||
PAGSCA_NRIGA, PAGSCA_NRATA, NULL };
|
int score = data_scad == datadoc ? 2 : 0;
|
||||||
for (int k = 0; field[k]; k++)
|
if (score == 0 && datadoc == data_scad+1L)
|
||||||
rpag.put(field[k], scadenza.get(field[k]));
|
score++;
|
||||||
rpag.put(PAGSCA_NRIGP, nrigp);
|
if (residuo >= importo)
|
||||||
rpag.put(PAGSCA_IMPORTO, pagare);
|
{
|
||||||
game.modifica_pagamento(rpag, euro, true);
|
score++;
|
||||||
importo -= pagare;
|
if (residuo == importo)
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
if (score > best_score)
|
||||||
|
{
|
||||||
|
best_rata = nrata;
|
||||||
|
best_score = score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (best_rata > 0)
|
||||||
|
paga_rata(game, best_rata, nrigp, importo);
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Se ci rimane qualcosa o non e' stata trovata una rata aperta allora crea un pagamento non assegnato
|
||||||
if (!importo.is_zero())
|
if (!importo.is_zero())
|
||||||
{
|
{
|
||||||
TRectype rpag(LF_PAGSCA);
|
TRectype rpag(LF_PAGSCA);
|
||||||
const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART, NULL };
|
const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART, NULL };
|
||||||
for (int k = 0; field[k]; k++)
|
for (int k = 0; field[k]; k++)
|
||||||
rpag.put(field[k], pagamento.get(field[k]));
|
rpag.put(field[k], pagamento.get(field[k]));
|
||||||
rpag.put(PAGSCA_NRIGA, 9999);
|
rpag.put(PAGSCA_NRIGA, 9999); // Questo 9999 significa "fattura ignota"
|
||||||
rpag.put(PAGSCA_NRATA, 9999);
|
rpag.put(PAGSCA_NRATA, 9999); // Questo 9999 significa "rata ignota"
|
||||||
rpag.put(PAGSCA_NRIGP, nrigp);
|
rpag.put(PAGSCA_NRIGP, nrigp); // Completa la chiave di PAGSCA col numero riga di partita
|
||||||
rpag.put(PAGSCA_IMPORTO, importo);
|
rpag.put(PAGSCA_IMPORTO, importo);
|
||||||
|
const TValuta euro;
|
||||||
game.modifica_pagamento(rpag, euro, true);
|
game.modifica_pagamento(rpag, euro, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In COGECO le riba si intendono pagate automaticamente,
|
||||||
|
// per cui in CAMPO viene aperta una scadenza ed immediatamente chiusa col relativo pagamento
|
||||||
void TImporta_sc::nuova_riba(const TImporta_cogeco_recset& recset, TPartita& game)
|
void TImporta_sc::nuova_riba(const TImporta_cogeco_recset& recset, TPartita& game)
|
||||||
{
|
{
|
||||||
nuova_scadenza(recset, game);
|
nuova_scadenza(recset, game);
|
||||||
nuovo_pagamento(recset, game);
|
nuovo_pagamento(recset, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creo una nuova riga partita corrispondente ad una riga pagamento in PAGSCA
|
||||||
void TImporta_sc::nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game)
|
void TImporta_sc::nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game)
|
||||||
{ nuovo_pagamento_o_nota(recset, game, tm_pagamento); }
|
{ nuovo_pagamento_o_nota(recset, game, tm_pagamento); }
|
||||||
|
|
||||||
|
// Creo una nuova riga partita corrispondente ad una riga nota di credito in PAGSCA
|
||||||
void TImporta_sc::nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game)
|
void TImporta_sc::nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game)
|
||||||
{ nuovo_pagamento_o_nota(recset, game, tm_nota_credito); }
|
{ nuovo_pagamento_o_nota(recset, game, tm_nota_credito); }
|
||||||
|
|
||||||
|
// Creo una nuova riga partita corrispondente ad una riga di insoluto PAGSCA
|
||||||
bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log)
|
bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log)
|
||||||
{
|
{
|
||||||
const int nriga = game.prima_fattura();
|
const int nriga = game.prima_fattura(); // Cerco la fattura insoluta
|
||||||
if (nriga <= 0)
|
if (nriga <= 0) // Non e' carino creare un insoluto non assegnato
|
||||||
return log_error(log, TR("Impossibile associare insoluto"), recset);
|
return log_error(log, TR("Impossibile associare insoluto"), recset);
|
||||||
|
|
||||||
const TDate datadoc = recset.get_date(CGC_DATADOC);
|
const TDate datadoc = recset.get_date(CGC_DATADOC);
|
||||||
const real importo = recset.get_real(CGC_IMPORTO);
|
real importo = recset.get_real(CGC_IMPORTO);
|
||||||
|
|
||||||
|
// Cerca la miglior rata possibile da mandare insoluta
|
||||||
|
// Per fare cio', si assegna un punteggio ad ogni rata, basato sulla data e sull'importo
|
||||||
int best_rata = 0, best_score = 0;
|
int best_rata = 0, best_score = 0;
|
||||||
|
|
||||||
const TRiga_partite& fattura = game.riga(nriga);
|
const TRiga_partite& fattura = game.riga(nriga);
|
||||||
for (int nrata = fattura.rate(); nrata > 0; nrata--)
|
for (int nrata = fattura.rate(); nrata > 0; nrata--)
|
||||||
{
|
{
|
||||||
const TRiga_scadenze& scadenza = fattura.rata(nrata);
|
const TRiga_scadenze& scadenza = fattura.rata(nrata);
|
||||||
const TImporto imp = scadenza.importo_pagato(false);
|
const TImporto imp = scadenza.importo_pagato(false);
|
||||||
const TDate data = scadenza.get(SCAD_DATASCAD);
|
const TDate data = scadenza.get(SCAD_DATASCAD);
|
||||||
int score = 0;
|
int score = datadoc == data ? 2 : 0;
|
||||||
if (imp.valore() == importo)
|
if (score == 0 && datadoc == data+1L)
|
||||||
score++;
|
score++;
|
||||||
if (imp.valore() >= importo)
|
if (imp.valore() >= importo)
|
||||||
|
{
|
||||||
score++;
|
score++;
|
||||||
if (datadoc == data)
|
if (imp.valore() == importo)
|
||||||
score++;
|
score++;
|
||||||
|
}
|
||||||
if (score > best_score)
|
if (score > best_score)
|
||||||
{
|
{
|
||||||
best_rata = nrata;
|
best_rata = nrata;
|
||||||
@ -382,7 +443,7 @@ bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_rata > 0)
|
if (best_rata > 0) // Se ho trovato almeno una rata compatibile con l'insoluto...
|
||||||
{
|
{
|
||||||
const TRiga_scadenze& scadenza = fattura.rata(best_rata);
|
const TRiga_scadenze& scadenza = fattura.rata(best_rata);
|
||||||
TRiga_partite& insoluto = game.new_row();
|
TRiga_partite& insoluto = game.new_row();
|
||||||
@ -391,13 +452,13 @@ bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita&
|
|||||||
insoluto.put(PART_DATAREG, datadoc);
|
insoluto.put(PART_DATAREG, datadoc);
|
||||||
insoluto.put(PART_DATADOC, datadoc);
|
insoluto.put(PART_DATADOC, datadoc);
|
||||||
insoluto.put(PART_DESCR, TR("*** Insoluto trasferito da COGECO ***"));
|
insoluto.put(PART_DESCR, TR("*** Insoluto trasferito da COGECO ***"));
|
||||||
|
insoluto.put(PART_IMPTOTDOC, importo);
|
||||||
|
|
||||||
const char tipocf = game.conto().tipo();
|
const char tipocf = game.conto().tipo();
|
||||||
const TString& codcaus = find_causale(tipocf, tm_insoluto);
|
const TCausale& caus = causale(tipocf, tm_insoluto, datadoc);
|
||||||
if (codcaus.full())
|
if (caus.ok())
|
||||||
{
|
{
|
||||||
const TCausale& caus = _cache_causali.causale(codcaus, game.anno());
|
insoluto.put(PART_CODCAUS, caus.codice());
|
||||||
insoluto.put(PART_CODCAUS, codcaus);
|
|
||||||
insoluto.put(PART_REG, caus.reg().name());
|
insoluto.put(PART_REG, caus.reg().name());
|
||||||
insoluto.put(PART_TIPOMOV, caus.tipomov());
|
insoluto.put(PART_TIPOMOV, caus.tipomov());
|
||||||
insoluto.put(PART_SEZ, caus.sezione(1));
|
insoluto.put(PART_SEZ, caus.sezione(1));
|
||||||
@ -407,17 +468,7 @@ bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita&
|
|||||||
insoluto.put(PART_TIPOMOV, tm_insoluto);
|
insoluto.put(PART_TIPOMOV, tm_insoluto);
|
||||||
insoluto.put(PART_SEZ, fattura.sezione());
|
insoluto.put(PART_SEZ, fattura.sezione());
|
||||||
}
|
}
|
||||||
insoluto.put(PART_IMPORTO, importo);
|
paga_rata(game, best_rata, nrigp, importo);
|
||||||
|
|
||||||
const TValuta euro;
|
|
||||||
TRectype rpag(LF_PAGSCA);
|
|
||||||
const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART,
|
|
||||||
PAGSCA_NRIGA, PAGSCA_NRATA, NULL };
|
|
||||||
for (int k = 0; field[k]; k++)
|
|
||||||
rpag.put(field[k], scadenza.get(field[k]));
|
|
||||||
rpag.put(PAGSCA_NRIGP, nrigp);
|
|
||||||
rpag.put(PAGSCA_IMPORTO, importo);
|
|
||||||
game.modifica_pagamento(rpag, euro, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log_error(log, TR("Impossibile associare insoluto"), recset);
|
log_error(log, TR("Impossibile associare insoluto"), recset);
|
||||||
@ -425,11 +476,12 @@ bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita&
|
|||||||
return best_rata > 0;
|
return best_rata > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TImporta_sc::log_error(TLog_report& log, const char* msg, const TRecordset& recset)
|
bool TImporta_sc::log_error(TLog_report& log, const char* msg, const TRecordset& recset)
|
||||||
{
|
{
|
||||||
TString message;
|
TString message;
|
||||||
message << TR("Riga") << ' ' << recset.current_row() << ": " << msg;
|
message << recset.get(CGC_TIPOCF) << recset.get(CGC_CODCF) << '-'
|
||||||
|
<< recset.get(CGC_ANNO) << '/' << recset.get(CGC_NUMPART)
|
||||||
|
<< '.' << recset.get(CGC_NUMEROREC) << " : " << msg;
|
||||||
log.log(2, message);
|
log.log(2, message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -469,6 +521,16 @@ static int game_sorter(const TObject** o1, const TObject** o2)
|
|||||||
if (cmp != 0)
|
if (cmp != 0)
|
||||||
return cmp;
|
return cmp;
|
||||||
|
|
||||||
|
const TString datadoc1 = r1.get(CGC_DATADOC);
|
||||||
|
if (datadoc1.blank() || datadoc1 == "00/00/0000")
|
||||||
|
return -1;
|
||||||
|
const TString datadoc2 = r2.get(CGC_DATADOC);
|
||||||
|
if (datadoc2.blank() || datadoc2 == "00/00/0000")
|
||||||
|
return +1;
|
||||||
|
cmp = TDate(datadoc1)-TDate(datadoc2);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
const TString data1 = r1.get(CGC_SCADENZA);
|
const TString data1 = r1.get(CGC_SCADENZA);
|
||||||
if (data1.blank() || data1 == "00/00/0000")
|
if (data1.blank() || data1 == "00/00/0000")
|
||||||
return -1;
|
return -1;
|
||||||
@ -480,32 +542,33 @@ static int game_sorter(const TObject** o1, const TObject** o2)
|
|||||||
if (cmp != 0)
|
if (cmp != 0)
|
||||||
return cmp;
|
return cmp;
|
||||||
|
|
||||||
|
// I tipi documento vanno ordinati in base alla sequenza sequente, non in base al valore numerico!
|
||||||
|
TToken_string priority = "1|3|15|2|4|5|6|7|8|9|10|11";
|
||||||
const int tipodoc1 = r1.get_int(CGC_TIPODOC);
|
const int tipodoc1 = r1.get_int(CGC_TIPODOC);
|
||||||
const int tipodoc2 = r2.get_int(CGC_TIPODOC);
|
const int tipodoc2 = r2.get_int(CGC_TIPODOC);
|
||||||
cmp = tipodoc1 - tipodoc2;
|
int pri1 = priority.get_pos(tipodoc1);
|
||||||
|
if (pri1 < 0) pri1 = 100+tipodoc1;
|
||||||
|
int pri2 = priority.get_pos(tipodoc2);
|
||||||
|
if (pri2 < 0) pri2 = 100+tipodoc2;
|
||||||
|
cmp = pri1 - pri2;
|
||||||
|
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TImporta_sc::salva_partita(TPartita*& game, bool can_write)
|
void TImporta_sc::salva_partita(TPartita*& game)
|
||||||
{
|
{
|
||||||
if (game != NULL)
|
if (game != NULL)
|
||||||
{
|
{
|
||||||
if (can_write)
|
game->write();
|
||||||
{
|
|
||||||
// for (int r = game->last(); r > 0; r = game->pred(r))
|
|
||||||
// game->riga(r).put(PART_IMPTOTDOC, totdoc);
|
|
||||||
game->write();
|
|
||||||
}
|
|
||||||
delete game;
|
delete game;
|
||||||
game = NULL;
|
game = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TImporta_sc::transfer(const TFilename& file, bool can_write)
|
void TImporta_sc::transfer(const TFilename& file)
|
||||||
{
|
{
|
||||||
TImporta_cogeco_recset recset(file);
|
TImporta_cogeco_recset recset(file);
|
||||||
recset.sort(game_sorter);
|
recset.sort(game_sorter);
|
||||||
recset.save_as("c:/temp/topartite.txt");
|
|
||||||
|
|
||||||
TString caption; _msk->get_caption(caption);
|
TString caption; _msk->get_caption(caption);
|
||||||
TProgind pi(recset.items(), caption, true, true);
|
TProgind pi(recset.items(), caption, true, true);
|
||||||
@ -537,23 +600,23 @@ void TImporta_sc::transfer(const TFilename& file, bool can_write)
|
|||||||
|
|
||||||
if (tipocf != t || sottoconto != s || anno != a || p != part)
|
if (tipocf != t || sottoconto != s || anno != a || p != part)
|
||||||
{
|
{
|
||||||
salva_partita(game, can_write); // Salva parita corrente se non nulla
|
salva_partita(game); // Salva parita corrente se non nulla
|
||||||
|
|
||||||
TToken_string key; key.format("%c|%ld", t, s);
|
TToken_string key; key.format("%c|%ld", t, s);
|
||||||
const TRectype& clifo = cache().get(LF_CLIFO, key);
|
const TRectype& clifo = cache().get(LF_CLIFO, key);
|
||||||
if (clifo.empty())
|
if (clifo.empty())
|
||||||
{
|
{
|
||||||
can_write = log_error(log, TR("Codice Cliente/Fornitore non valido"), recset);
|
log_error(log, TR("Codice Cliente/Fornitore non valido"), recset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (a < 2000)
|
if (a < 2000)
|
||||||
{
|
{
|
||||||
can_write = log_error(log, TR("Anno partita non valido"), recset);
|
log_error(log, TR("Anno partita non valido"), recset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p <= 0)
|
if (p <= 0)
|
||||||
{
|
{
|
||||||
can_write = log_error(log, TR("Numero partita non valido"), recset);
|
log_error(log, TR("Numero partita non valido"), recset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,7 +635,7 @@ void TImporta_sc::transfer(const TFilename& file, bool can_write)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
can_write = log_error(log, TR("Impossibile determinare il conto cliente/fornitore"), recset);
|
log_error(log, TR("Impossibile determinare il conto cliente/fornitore"), recset);
|
||||||
break; // Esce subito, probabilmente il piano dei conti non e' stato ancora importato
|
break; // Esce subito, probabilmente il piano dei conti non e' stato ancora importato
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,19 +649,24 @@ void TImporta_sc::transfer(const TFilename& file, bool can_write)
|
|||||||
case 1: nuova_fattura(recset, *game); break; // Fattura
|
case 1: nuova_fattura(recset, *game); break; // Fattura
|
||||||
case 2: nuova_nota_credito(recset, *game); break; // Nota di credito
|
case 2: nuova_nota_credito(recset, *game); break; // Nota di credito
|
||||||
case 3: nuova_fattura(recset, *game); break; // Fattura in sospensione
|
case 3: nuova_fattura(recset, *game); break; // Fattura in sospensione
|
||||||
|
case 4: nuova_nota_credito(recset, *game); break; // Reso su fattura in sospensione
|
||||||
|
case 5: nuovo_pagamento(recset, *game); break; // Pagamento fattura in sospeso
|
||||||
case 6: nuovo_insoluto(recset, *game, log); break; // Insoluto
|
case 6: nuovo_insoluto(recset, *game, log); break; // Insoluto
|
||||||
case 8: // Tratta
|
case 8: // Tratta
|
||||||
case 9: // Ri.Ba.
|
case 9: // Ri.Ba.
|
||||||
case 10: nuova_riba(recset, *game); break; // Cambiale
|
case 10: nuova_riba(recset, *game); break; // Cambiale
|
||||||
case 11: nuovo_pagamento(recset, *game); break; // Pagamento
|
case 11: nuovo_pagamento(recset, *game); break; // Pagamento
|
||||||
case 19: nuova_riba(recset, *game); break; // Avviso di scadenza
|
|
||||||
case 13: nuova_nota_credito(recset, *game); break; // Nota di credito su RB clienti
|
case 13: nuova_nota_credito(recset, *game); break; // Nota di credito su RB clienti
|
||||||
|
case 14: nuova_nota_credito(recset, *game); break; // Abbuono
|
||||||
case 15: nuova_scadenza(recset, *game); break;
|
case 15: nuova_scadenza(recset, *game); break;
|
||||||
|
case 18: nuova_riba(recset, *game); break; // Paghero'
|
||||||
|
case 19: nuova_riba(recset, *game); break; // Avviso di scadenza
|
||||||
|
case 20: nuova_riba(recset, *game); break; // R.I.D.
|
||||||
default: log_error(log, TR("Tipo documento non riconosciuto"), recset); break;
|
default: log_error(log, TR("Tipo documento non riconosciuto"), recset); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
salva_partita(game, can_write); // Salva ultima partita se non nulla
|
salva_partita(game); // Salva ultima partita se non nulla
|
||||||
|
|
||||||
if (log.recordset()->items() > 0)
|
if (log.recordset()->items() > 0)
|
||||||
log.preview();
|
log.preview();
|
||||||
@ -606,6 +674,7 @@ void TImporta_sc::transfer(const TFilename& file, bool can_write)
|
|||||||
|
|
||||||
bool TImporta_sc::create()
|
bool TImporta_sc::create()
|
||||||
{
|
{
|
||||||
|
// Determina i conti per clienti e fornitori nel caso non siano in anagrafica
|
||||||
TString query; query << "USE PCON SELECT TMCF!=\'\'";
|
TString query; query << "USE PCON SELECT TMCF!=\'\'";
|
||||||
TISAM_recordset pcon(query);
|
TISAM_recordset pcon(query);
|
||||||
for (bool ok = pcon.move_first(); ok; ok = pcon.move_next())
|
for (bool ok = pcon.move_first(); ok; ok = pcon.move_next())
|
||||||
@ -617,7 +686,6 @@ bool TImporta_sc::create()
|
|||||||
if (tmcf == 'F' && _fornitori.gruppo() == 0)
|
if (tmcf == 'F' && _fornitori.gruppo() == 0)
|
||||||
_fornitori.get(rec);
|
_fornitori.get(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
_msk = new TImporta_sc_mask();
|
_msk = new TImporta_sc_mask();
|
||||||
return TSkeleton_application::create();
|
return TSkeleton_application::create();
|
||||||
}
|
}
|
||||||
@ -630,14 +698,14 @@ bool TImporta_sc::destroy()
|
|||||||
|
|
||||||
void TImporta_sc::main_loop()
|
void TImporta_sc::main_loop()
|
||||||
{
|
{
|
||||||
KEY tasto;
|
if (_msk->run() == K_ENTER)
|
||||||
tasto = _msk->run();
|
|
||||||
if (tasto == K_ENTER)
|
|
||||||
{
|
{
|
||||||
|
_cache_causali.init(_msk->get(F_CODCAUSC), _msk->get(F_CODCAUSF));
|
||||||
|
|
||||||
//genero il nome del file da caricare
|
//genero il nome del file da caricare
|
||||||
TFilename name = _msk->get(F_PATH);
|
TFilename name = _msk->get(F_PATH);
|
||||||
name.add(_msk->get(F_NAME));
|
name.add(_msk->get(F_NAME));
|
||||||
transfer(name, true);
|
transfer(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,3 +8,4 @@
|
|||||||
#define F_CODCAUSF 106
|
#define F_CODCAUSF 106
|
||||||
#define F_DESCRCAUSC 107
|
#define F_DESCRCAUSC 107
|
||||||
#define F_DESCRCAUSF 108
|
#define F_DESCRCAUSF 108
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ BEGIN
|
|||||||
CHECKTYPE REQUIRED
|
CHECKTYPE REQUIRED
|
||||||
END
|
END
|
||||||
|
|
||||||
GROUPBOX DLG_NULL 90 6
|
GROUPBOX DLG_NULL 90 4
|
||||||
BEGIN
|
BEGIN
|
||||||
PROMPT 2 8 "Causali"
|
PROMPT 2 8 "Causali"
|
||||||
END
|
END
|
||||||
|
Loading…
x
Reference in New Issue
Block a user