campo-sirio/tc/tc8200.cpp
guy 6de44e6502 Correzioni su invio Payline
git-svn-id: svn://10.65.10.50/branches/R_10_00@22866 c028cbd2-c16b-5b4b-a496-9718f37d4682
2013-05-27 12:08:13 +00:00

596 lines
15 KiB
C++

#include <applicat.h>
#include <automask.h>
#include <dongle.h>
#include <netsock.h>
#include <progind.h>
#include <recarray.h>
#include <relation.h>
#include <reputils.h>
#include <textset.h>
#include <validate.h>
#include <utility.h>
#include "tc8.h"
#include "../cg/cgsaldac.h"
#include <clifo.h>
#include <partite.h>
#include <scadenze.h>
#include <pagsca.h>
///////////////////////////////////////////////////////////
// TPayLine_recset
///////////////////////////////////////////////////////////
class TPayLine_recset : public TCSV_recordset
{
public:
TPayLine_recset() : TCSV_recordset("CSV(;)") {}
};
///////////////////////////////////////////////////////////
// TAutomask
///////////////////////////////////////////////////////////
class TPayLine_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TPayLine_mask() :TAutomask ("tc8200a") {}
};
bool TPayLine_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
return true;
}
///////////////////////////////////////
// TSkeleton_application
///////////////////////////////////////
class TPayLine_app : public TSkeleton_application
{
protected:
virtual bool create();
virtual const char* extra_modules() const { return "cg"; }
virtual void main_loop();
public:
bool find_clifo(long codcf, TPayLine_recset& clienti) const;
long export_clifo(long codcf, TPayLine_recset& clienti, TLog_report& log) const;
bool esporta_pagsca(const TRiga_partite& part, const TRiga_scadenze* scad, const TRectype& pag,
const TDate& dal, const TDate& al, TPayLine_recset& clienti, TPayLine_recset& movimenti,
TLog_report& log) const;
bool esporta_scad(const TRiga_scadenze& scad,
const TDate& dal, const TDate& al,
TPayLine_recset& clienti, TPayLine_recset& movimenti, TLog_report& log) const;
void esporta_partita(long lastcf, int lastyear, const TString& lastpart, const TDate& dal, const TDate& al,
TPayLine_recset& clienti, TPayLine_recset& movimenti, TLog_report& log) const;
bool esporta(const TString& dir, const TString& ftp, const TDate& dt, TLog_report& log) const;
bool ftp_send(const TFilename& filename, const TString& ftp) const;
};
bool TPayLine_app::find_clifo(long codcf, TPayLine_recset& clienti) const
{
for (bool ok = clienti.move_first(); ok; ok = clienti.move_next())
{
if (clienti.get(0L).as_int() == codcf)
return true;
}
return false;
}
long TPayLine_app::export_clifo(long codcf, TPayLine_recset& clienti, TLog_report& log) const
{
TString8 key; key.format("C|%ld", codcf);
TRectype rec = cache().get(LF_CLIFO, key);
TString msg, str;
str = rec.get(CLI_RAGSOC);
str.strip_double_spaces();
msg << codcf << ' ' << str << ": ";
if (rec.get_bool(CLI_OCCAS))
{
msg << TR("OCCASIONALE");
log.log(1, msg);
return -1;
}
int alleg = rec.get_int(CLI_ALLEG);
while (alleg == 4)
{
alleg = 0;
const long altcf = rec.get_long(CLI_CODALLEG);
if (altcf > 0)
{
key.format("C|%ld", codcf);
rec = cache().get(LF_CLIFO, key);
if (!rec.empty())
{
codcf = altcf;
alleg = rec.get_int(CLI_ALLEG); // Ok, go on with new code
}
}
}
bool good = false;
switch (alleg)
{
case 2: msg << TR("OCCASIONALE"); break;
case 5:
case 6: msg << TR("PRIVATO"); break;
case 9: msg << TR("ESTERO"); break;
default: good = true; break;
}
if (!good)
{
log.log(1, msg);
return -2;
}
if (find_clifo(codcf, clienti))
return codcf; // Already saved
TToken_string row(128, ';');
row.format("%6ld", codcf);
str = rec.get(CLI_RAGSOC);
str.strip_double_spaces(); str.strip(";");
str.left_just(50);
row.add(str);
str = rec.get(CLI_INDCF);
str << ' ' << rec.get(CLI_CIVCF);
row.add(str);
row.add(rec.get(CLI_CAPCF), 3);
row.add(rec.get(CLI_LOCCF), 4);
TString4 stato = rec.get(CLI_STATOPAIV); // ""=Italia; "SM"=San Marino
str = rec.get(CLI_PAIV);
if (str.blank())
str = rec.get(CLI_COFI);
if (str.starts_with("SM"))
{
stato = "SM";
str = str.right(5);
}
if (stato != "SM")
stato = "IT";
row.add(stato, 6); // Stato partita IVA
if (!pi_check(stato, str))
{
msg << TR("Partita IVA non valida ") << str;
log.log(2, msg);
return -3; // Partita IVA non italiana?
}
if (stato != "SM") // No San Marino!
{
row.add(str, 7); // P.I.
row.add(rec.get(CLI_COFI), 8); // C.F.
}
if (alleg == 8)
{
row.add(TR("Fallimento"), 9); // Status legale
row.add(TR("Bloccato"), 10); // Status bloccato
}
clienti.new_rec(row);
return codcf;
}
bool TPayLine_app::esporta_pagsca(const TRiga_partite& part, const TRiga_scadenze* scad, const TRectype& pag,
const TDate& dal, const TDate& al, TPayLine_recset& clienti, TPayLine_recset& movimenti,
TLog_report& log) const
{
const long codcf = export_clifo(pag.get_long(PAGSCA_SOTTOCONTO), clienti, log);
if (codcf <= 0)
return false;
TDate data = part.get(PART_DATADOC); // Data Documento
if (!data.ok())
data = part.get_date(PART_DATAREG);
if (data > al || data < dal && part.partita().chiusa())
return false;
TToken_string row(128, ';');
TString str;
row.format("%6ld", codcf);
str = data.stringa(); str.left_just(10);
row.add(str, 1);
str = part.get(PART_NUMDOC); str.left_just(8);
row.add(str, 2); // Numero Documento
if (scad == NULL)
{
row.add(row.get(1), 3); // Data riferimento
str = part.get(PART_NUMPART); str.left_just(8);
row.add(str, 4); // Numero Riferimento
}
else
{
const TRiga_partite& fatt = scad->riga();
data = fatt.get(PART_DATADOC); // Data riferimento
if (!data.ok())
data = fatt.get_date(PART_DATAREG);
str = data.stringa(); str.left_just(10);
row.add(str, 3);
str = fatt.get(PART_NUMPART); str.left_just(8);
row.add(str, 4); // Numero Riferimento
}
str = part.get(PART_DATAREG);
str.left_just(10);
row.add(str, 5); // Data registrazione
str = part.get(PART_NREG); str.right_just(7);
row.add(str, 6); // Numero registrazione
if (scad != NULL)
{
str = scad->get(SCAD_DATASCAD);
str.left_just(10);
}
else
str.spaces(10);
row.add(str, 7); // Data scadenza
const int tm = part.get_int(PART_TIPOMOV);
real imp;
if (tm == 3 && scad != NULL && scad->chiusa() && scad->rows() == 1) // Pagamento su unica rata chiusa
{
// Caso semplice: una rata pagata completamene con un solo pagamento
imp = scad->get_real(SCAD_IMPORTO); // Importo pagato = importo da pagare
}
else
{
imp = pag.get_real(PAGSCA_IMPORTO);
if (tm == 3)
{
if (pag.get_char(PAGSCA_PASSATT) == 'P')
imp += pag.get_real(PAGSCA_ABBUONI);
imp += pag.get_real(PAGSCA_RITENUTE);
imp += pag.get_real(PAGSCA_RITSOC);
}
}
str = part.get(PART_SEZ);
if (imp < ZERO)
{
imp = -imp;
str = str == "D" ? "A" : "D";
}
row.add(imp.stringa(10,2), 8); // Importo
row.add(str, 9); // Dare/Avere
switch (tm)
{
case 2: row.add("EF7#", 10); break; // Nota di credito
case 5: row.add("EF5#", 10); break; // Insoluto
default:
switch (part.get_int(PART_TIPOPAG))
{
case 3: row.add("EF3#", 10); break;// Causale pagamento con RIBA
default: row.add("EF6#", 10); break;// Causale pagamento normale
}
}
row.add(" ", 11); // Condizioni di pagamento
row.add(part.get(PART_DATAPAG), 12); // Data pagamento
movimenti.new_rec(row);
return true;
}
bool TPayLine_app::esporta_scad(const TRiga_scadenze& scad, const TDate& dal, const TDate& al,
TPayLine_recset& clienti, TPayLine_recset& movimenti, TLog_report& log) const
{
const long codcf = export_clifo(scad.get_long(PAGSCA_SOTTOCONTO), clienti, log);
if (codcf <= 0)
return false;
const TRiga_partite& part = scad.riga();
TToken_string row(255, ';');
row.format("%6ld", codcf); // Codice cliente
TString str;
str = part.get(PART_DATADOC); // Data Documento
if (str.blank())
str = part.get(PART_DATAREG);
row.add(str, 1);
const TDate datarif(str);
if (datarif > al)
return false;
if (scad.get_bool(SCAD_PAGATA) || part.get_bool(PART_CHIUSA))
{
if (datarif < dal)
return false; // Ignora vecchia partita chiusa
}
str = part.get(PART_NUMDOC); str.left_just(8);
row.add(str, 2); // Numero Documento
row.add(row.get(1), 3); // Data riferimento
str = part.get(PART_NUMPART); str.left_just(8);
row.add(str, 4); // Numero riferimento
row.add(part.get(PART_DATAREG), 5); // Data registrazione
str = part.get(PART_NREG); str.right_just(7);
row.add(str, 6); // Numero registrazione
const TDate datascad = scad.get(SCAD_DATASCAD);
row.add(datascad, 7); // Data scadenza
real importo = scad.get_real(SCAD_IMPORTO);
str = part.get(PART_SEZ);
if (importo < ZERO)
{
importo = -importo;
str = str == "D" ? "A" : "D";
}
row.add(importo.stringa(10,2), 8); // Importo
row.add(str, 9); // Dare/Avere
row.add(str[0] == 'A' ? "EF7#" : "EF1#", 10); // Causale Fattura o Nota credito
movimenti.new_rec(row);
for (int r = scad.last(); r > 0; r = scad.pred(r))
{
const TRiga_partite& rpag = part.partita().riga(r);
esporta_pagsca(rpag, &scad, scad.row(r), botime, al, clienti, movimenti, log);
}
return true;
}
void TPayLine_app::esporta_partita(long cf, int year, const TString& numpart,
const TDate& dal, const TDate& al,
TPayLine_recset& clienti, TPayLine_recset& movimenti, TLog_report& log) const
{
const TBill bill(0, 0, cf, 'C');
TPartita game(bill, year, numpart);
const bool game_over = game.chiusa(true);
bool some_rata = false;
const TDate inizio = game_over ? dal : botime;
for (int r = game.prima_fattura(); game.esiste(r); r = game.succ(r))
{
const TRiga_partite& riga = game.riga(r);
for (int s = 1; s <= riga.rate(); s++)
{
const TRiga_scadenze& rata = riga.rata(s);
some_rata |= esporta_scad(rata, inizio, al, clienti, movimenti, log);
}
}
const TRecord_array& nonass = game.unassigned();
if (nonass.rows() > 0)
{
if (game_over && !some_rata)
return; // Ignora vecchie partite chiuse
for (int u = nonass.last_row(); u > 0; u = nonass.pred_row(u))
{
const TRiga_partite& rpag = game.riga(u);
esporta_pagsca(rpag, NULL, nonass.row(u), dal, al, clienti, movimenti, log);
}
}
}
static int sort_mov(const TObject** o1, const TObject** o2)
{
const TToken_string& r1 = *(const TToken_string*)*o1;
const TToken_string& r2 = *(const TToken_string*)*o2;
long c1 = 0, c2 = 0;
r1.get(0, c1);
r2.get(0, c2);
int ret = c1 - c2;
for (int i = 3; i > 0 && ret == 0; i -= 2)
{
TDate d1, d2;
r1.get(i, d1);
r2.get(i, d2);
ret = d1 - d2;
if (ret == 0)
{
TString16 p1, p2;
r1.get(i+1, p1); p1.trim();
r2.get(i+1, p2); p2.trim();
ret = p1.compare(p2);
}
}
return ret;
}
bool TPayLine_app::ftp_send(const TFilename& filename, const TString& ftp) const
{
bool done = false;
TString srv, pat, usr, pwd;
const int at = ftp.find('@');
if (at > 0)
{
srv = ftp.mid(at+1);
usr = ftp.left(at);
if (usr.starts_with("ftp://"))
usr.ltrim(6);
const int colon = usr.find(':');
if (colon > 0)
{
pwd = usr.mid(colon+1);
usr.cut(colon);
}
}
else
{
srv = ftp;
if (srv.starts_with("ftp://"))
srv.ltrim(6);
}
const int slash = srv.find('/');
if (slash > 0)
{
pat = srv.mid(slash);
srv.cut(slash);
if (pat.full() && !pat.ends_with("/"))
pat << '/';
}
TSocketClient ftpserver;
CONNID id = ftpserver.QueryConnection("21", srv);
if (id > 0)
{
TString remote = pat;
remote << filename.name();
done = ftpserver.FtpSendFile(id, remote, filename, usr, pwd);
if (!done)
done = error_box(FR("Impossibile inviare il file %s"), (const char*)filename);
ftpserver.RemoveConnection(id);
}
else
{
done = error_box(FR("Impossibile connettersi al server %s"), (const char*)srv);
}
return done;
}
bool TPayLine_app::esporta(const TString& dir, const TString& ftp,
const TDate& al, TLog_report& log) const
{
TDate dal(al);
dal.set_day(1); // A scanso equivoci bisestili
dal.addyear(-1);
TPayLine_recset clienti;
TPayLine_recset movimenti;
TString query;
query << "USE PART SELECT NRIGA<=2\nFROM TIPOC=C\nTO TIPOC=C";
TISAM_recordset saldaconto(query);
if (saldaconto.items() > 0)
{
long last_cf = 0;
int last_anno = 0;
TString8 last_part;
const TRectype& part = saldaconto.cursor()->curr();
TProgind pi(saldaconto.items(), title());
for (bool ok = saldaconto.move_first(); ok; ok = saldaconto.move_next())
{
if (!pi.addstatus(1))
break;
const long codcf = part.get_long(SCAD_SOTTOCONTO);
const int year = part.get_int(SCAD_ANNO);
const TString8 numpart = part.get(SCAD_NUMPART);
if (codcf != last_cf || year != last_anno || numpart != last_part)
{
esporta_partita(codcf, year, numpart, dal, al, clienti, movimenti, log);
last_cf = codcf;
last_anno = year;
last_part = numpart;
}
}
}
TString msg;
log.log(0, msg);
msg << TR("Esportati ")
<< movimenti.items() << TR(" movimenti di ")
<< clienti.items() << TR(" clienti")
<< TR(" al ") << al;
log.log(0, msg);
TFilename fname_cli = dir; fname_cli.add("PLclienti.txt");
clienti.sort();
clienti.save_as(fname_cli);
TFilename fname_mov = dir; fname_mov.add("PLmovimenti.txt");
movimenti.sort(sort_mov);
bool done = movimenti.save_as(fname_mov);
if (done && ftp.full())
{
msg.cut(0);
log.log(0, msg);
msg << TR("Invio a ") << ftp;
log.log(0, msg);
TProgind pi(2, msg);
for (int i = 0; done && i < 2; i++)
{
if (!pi.addstatus(1))
break;
const TFilename& fname = i == 0 ? fname_cli : fname_mov;
done = ftp_send(fname, ftp);
if (!done)
{
msg.cut(0) << TR("Impossibile inviare il file ") << fname;
log.log_error(msg);
}
}
}
return done;
}
bool TPayLine_app::create()
{
Tdninst dn;
if (!dn.can_I_run(true))
return error_box(FR("Postazione non abilitata per %s"), (const char*)title());
return TSkeleton_application::create();
}
void TPayLine_app::main_loop()
{
TPayLine_mask m;
while (m.run() == K_ENTER)
{
const TString& dir = m.get(101);
const TDate limit = m.get(102);
const TString& ftp = m.get(103);
TString tit;
tit << title() << " al " << limit;
TLog_report log(tit);
log.kill_duplicates();
esporta(dir, ftp, limit, log);
log.preview();
}
}
int tc8200 (int argc, char* argv[])
{
TPayLine_app main_app;
main_app.run(argc, argv, TR("Esportazione PayLine"));
return 0;
}