#include #include #include #include #include #include #include #include #include #include #include #include "tc8.h" #include "../cg/cgsaldac.h" #include #include #include #include /////////////////////////////////////////////////////////// // 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; }