campo-sirio/sc/sc2400.cpp
guy 201a3466f2 Potenziamento stampa solleciti via mail
git-svn-id: svn://10.65.10.50/branches/R_10_00@22911 c028cbd2-c16b-5b4b-a496-9718f37d4682
2013-12-13 09:43:51 +00:00

533 lines
16 KiB
C++
Executable File

#include "sc2.h"
#include "sc2402.h"
#include "sc2102.h"
#include "sc2400a.h"
#include <applicat.h>
#include <progind.h>
#include <printer.h>
#include <reputils.h>
#include <clifo.h>
///////////////////////////////////////////////////////////
// Stampa solleciti
///////////////////////////////////////////////////////////
class TStampaSol_application: public TSkeleton_application
{
TString _lingua_ditta;
TSol_mask* _msk;
bool _gesval;
TSol_form* _form;
protected:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
virtual void on_firm_change();
virtual void on_config_change();
bool get_mail_address(TToken_string& to, TToken_string& cc) const;
virtual bool get_next_mail(TToken_string& to, TToken_string& cc, TToken_string& ccn,
TString& subj, TString& text, TToken_string& attach, short& ui) const;
const TString& game_key(const TRectype& part) const; // Costruisce chiave univoca per TAssoc_array partite
bool ci_sono_scadenze_aperte(const TPartita& game, const TDate& dal, const TDate& al, const TDate& data_rischio) const;
bool puoi_scartare(const TPartita& game, const TDate& datalim) const;
int print_sol(); // stampa l'elemento corrente
public:
TSol_mask& mask() const { return *_msk; }
TSol_form& form() const { return *_form; }
TCursor_sheet& sheet() { return _msk->cur_sheet(); }
bool print_selected(); // cicla la stampa sugli elementi selezionati
bool mail_selected(); // manda email agli elementi selezionati
TStampaSol_application();
virtual ~TStampaSol_application() {}
};
bool TStampaSol_application::print_selected()
{
TCursor_sheet &s = sheet();
TCursor &c = *s.cursor();
const char who = mask().get_who();
const int key = mask().get_key();
// Attiva la stampa del saldo partita
form().stampa_saldo(mask().stampa_saldo());
// filtra il cursore del form in modo che diventi uguale al cursor_sheet corrente
// Qui sarebbe bello copiarsi l'indice dell'altro cursore
TCursor &fc = *form().cursor();
fc.setkey(key);
TRectype filter(LF_CLIFO);
filter.put(CLI_TIPOCF, who);
fc.setregion(filter, filter);
const long print_all = !s.one_checked(); // se non ho selezionato nulla allora li stampo tutti
long analfabeti = 0; // persone non stampate in quanto aventi lingua errata
TPrinter& pr = printer();
pr.open();
const long items = c.items();
for (long i=0; i < items; i++)
{
if (print_all || s.checked(i))
{
fc = i; // muove il cursore alla posizione corrente
const int ret = print_sol();
if (ret < 0)
analfabeti++;
}
if (pr.frozen())
break;
}
pr.close();
if (analfabeti > 0)
warning_box(FR("%ld clienti non sono stati stampati in quanto "
"il codice lingua non corrispondeva al profilo di stampa"), analfabeti);
return true;
}
bool TStampaSol_application::ci_sono_scadenze_aperte(const TPartita& game, const TDate& dal, const TDate& al, const TDate& data_rischio) const
{
bool found = false;
for (int r = game.last(); r > 0; r = game.pred(r))
{
const TRiga_partite& row = game.riga(r);
if (row.is_fattura() && row.get_date(PART_DATAREG) <= al)
{
for (int s = row.rate(); s > 0 ;s--)
{
const TRiga_scadenze& rata = row.rata(s);
const TDate data = rata.get(SCAD_DATASCAD);
if (data >= dal && data <= al)
{
found = !rata.chiusa();
if (!found)
{
TImporto rat = rata.importo(true);
TImporto imp = rata.importo_pagato_al(true, data_rischio);
imp.normalize(rat.sezione());
const real saldo = rat.valore() + imp.valore();
found = saldo > ZERO;
}
if (found)
break;
}
}
}
}
return found;
}
const TString& TStampaSol_application::game_key(const TRectype& part) const
{
TToken_string& tok = get_tmp_string();
tok = part.get(PART_ANNO);
tok.add(part.get(PART_NUMPART));
return tok;
}
bool TStampaSol_application::puoi_scartare(const TPartita& game, const TDate& datalim) const
{
bool yes = game.chiusa();
if (yes && datalim.ok())
{
TDate last;
for (int r = game.last(); r > 0; r = game.pred(r))
{
const TRiga_partite& riga = game.riga(r);
if (riga.tipo() > tm_fattura)
{
const TDate d = riga.get(PART_DATAPAG);
if (d > last)
last = d;
}
}
yes = last < datalim;
}
return yes;
}
int TStampaSol_application::print_sol()
{
TSol_form& f = form();
// preparazione variabili per controllo lingua
const TRectype &clf= f.cursor()->file().curr();
const TString4 lincf = clf.get(CLI_CODLIN);
bool ok = true;
// controllo lingua ditta corrente
if ((f.lingua() == _lingua_ditta && !lincf.empty()) || f.lingua() != _lingua_ditta) ok= (lincf == f.lingua());
if (!ok) return -1; // cliente analfabeta
f.azzera_totali();
// filtra solo le partite del cliente selezionato
TLocalisamfile partite(LF_PARTITE);
partite.zero();
partite.put(PART_TIPOCF, clf.get(CLI_TIPOCF));
partite.put(PART_SOTTOCONTO, clf.get(CLI_CODCF));
const TRectype& parkur = partite.curr();
const TRectype filter(parkur);
bool one_printed = false; // booleano di controllo di riuscita della stampa
const bool sel_tot_saldo = f.get_sel_tot_saldo(); // selezione sul saldo totale cliente
const real sel_importo(f.get_sel_importo()); // importo di selezione
const TDate data_inizio_soll = _msk->get(F_DATAINISCAD);
const TDate data_limite_soll = f.data_limite_operazione();
const TDate data_limite_scaduto = f.data_limite_scaduto();
const TDate data_rischio = f.data_inizio_rischio();
TAssoc_array games_in_range;
if ((sel_tot_saldo && sel_importo > ZERO) || data_inizio_soll.ok())
{
real saldo;
for (int err = partite.read(_isgteq);
err == NOERR && parkur == filter;
err = partite.read(_isgreat))
{
const TPartita game(parkur);
if (!puoi_scartare(game, data_rischio))
{
if (sel_tot_saldo)
{
const real sld = game.calcola_scaduto_al(false, data_limite_soll);
saldo += sld;
}
if (data_inizio_soll.ok())
{
if (ci_sono_scadenze_aperte(game, data_inizio_soll, data_limite_soll, data_rischio))
games_in_range.add(game_key(parkur));
}
}
partite.put(PART_NRIGA, 9999);
}
if (sel_tot_saldo && sel_importo > ZERO && saldo < sel_importo)
return 0;
if (data_inizio_soll.ok() && games_in_range.empty())
return 0;
partite.curr() = filter;
}
for (int err = partite.read(_isgteq);
err == NOERR && parkur == filter;
err = partite.read(_isgreat))
{
if (data_inizio_soll.ok() && !games_in_range.is_key(game_key(parkur)))
continue; // Scarta parite fuori range di date
const TPartita game(parkur);
if (!puoi_scartare(game, data_rischio))
{
const real saldo = game.calcola_scaduto_al(false, data_limite_scaduto);
TImporto unreferenced; //Totale non assegnati per questa partita.
{
// E' giusto calcolare il saldo, comprendente i non assegnati.
// se il saldo della partita chiude in avere va sommato ad unreferenced
const TRiga_partite& sum = game.riga(game.first());
unreferenced = game.calcola_saldo_al(game.in_valuta() && f.in_valuta(),data_limite_soll, data_limite_scaduto, data_rischio);
if (unreferenced.valore() > ZERO && unreferenced.sezione() == 'A')
{
unreferenced.normalize('A'); //per i non assegnati/anticipi c'e' solo la colonna AVERE
const TString4 valuta = sum.get(PART_CODVAL);
form().totali().add(unreferenced,valuta);
}
}
if (sel_tot_saldo || (saldo > ZERO && saldo >= sel_importo ) || (saldo.is_zero() && !unreferenced.is_zero() && data_rischio < data_limite_scaduto))
{
const bool printed = form().print_game(game);
one_printed |= printed;
}
}
partite.put(PART_NRIGA, 9999);
if (printer().frozen())
break;
}
if (one_printed)
{
f.ultima_pagina();
printer().formfeed();
}
return one_printed ? 1 : 0;
}
bool TStampaSol_application::get_mail_address(TToken_string& to, TToken_string& cc) const
{
const TRectype& fc = form().cursor()->curr();
const long codcf = fc.get_long(CLI_CODCF);
TString8 clifo; clifo.format("C%06ld", codcf);
TISAM_recordset contacts("USE MULTIREL\nFROM COD=BACON FIRST=#CLIFO\nTO COD=BACON FIRST=#CLIFO");
contacts.set_var("#CLIFO", clifo);
TToken_string data;
for (bool ok = contacts.move_first(); ok; ok = contacts.move_next())
{
data = contacts.get("DATA").as_string();
FOR_EACH_TOKEN(data, tok)
{
const TFixed_string doc(tok);
if (doc.starts_with("sc2400", true) || doc.starts_with("sollec", true))
{
const TRectype& rub = cache().get(LF_CONTACT, contacts.get("SECOND").as_int());
TString80 mail = rub.get("MAIL");
if (mail.blank())
mail = rub.get("MAIL2");
if (mail.full())
{
if (to.blank())
to = mail;
else
cc.add(mail);
break;
}
}
}
}
if (to.blank())
{
TString8 key; key << "C|" << codcf;
to = cache().get(LF_CLIFO, key, CLI_DOCMAIL);
}
return to.full();
}
bool TStampaSol_application::get_next_mail(TToken_string& to, TToken_string& cc, TToken_string& ccn,
TString& subj, TString& text, TToken_string& attach, short& ui) const
{
bool ok = TApplication::get_next_mail(to, cc, ccn, subj, text, attach, ui) && get_mail_address(to, cc);
if (ok)
{
const TRectype& clifo = form().cursor()->curr();
TDate oggi = mask().get(F_DATALIMSOL);
if (!oggi.ok())
oggi = mask().get_date(F_DATASEND);
subj << TR("Sollecito ") << prefix().firm().ragione_sociale();
TString ragsoc = clifo.get(CLI_RAGSOC); ragsoc.strip_double_spaces();
text << "Spett. " << ragsoc << '\n'
<< TR("Si ricorda il rispetto delle scadenze aperte al ") << oggi << '\n'
<< TR(" riepilogate nel file allegato ") << attach << '\n'
<< prefix().firm().ragione_sociale();
if (to.full())
ui &= ~0x1; // No user interface
ui |= 0x2; // Query receipt
const long codcf = clifo.get_long(CLI_CODCF);
TFilename pdf;
ok = get_next_pdf(oggi.year(), -1, "SOLL", oggi.date2ansi(), codcf, pdf);
attach = pdf;
}
return ok;
}
struct TMail_message : public TObject
{
TToken_string _to, _cc, _ccn;
TString _subj, _text;
TToken_string _attach;
short _ui;
};
bool TStampaSol_application::mail_selected()
{
TCursor_sheet &s = sheet();
TCursor &c = *s.cursor();
const char who = mask().get_who();
const int key = mask().get_key();
// Attiva la stampa del saldo partita
form().stampa_saldo(mask().stampa_saldo());
// filtra il cursore del form in modo che diventi uguale al cursor_sheet corrente
// Qui sarebbe bello copiarsi l'indice dell'altro cursore
TCursor &fc = *form().cursor();
fc.setkey(key);
TRectype filter(LF_CLIFO);
filter.put(CLI_TIPOCF, who);
fc.setregion(filter, filter);
const long print_all = !s.one_checked(); // se non ho selezionato nulla allora li stampo tutti
TLog_report log;
TArray mail;
const long items = c.items();
if (items > 0)
{
const TDate oggi(TODAY);
TProgind pi(items);
TPrinter& pr = printer();
for (long i=0; i < items; i++)
{
if (!pi.addstatus(1))
break;
if (print_all || s.checked(i))
{
fc = i; // muove il cursore alla posizione corrente
pr.set_export_file("soll.pdf", true);
pr.open();
const int ret = print_sol();
pr.close();
if (ret > 0)
{
TString msg;
msg << fc.curr().get(CLI_RAGSOC) << ": ";
msg.strip_double_spaces();
TMail_message* m = new TMail_message;
bool done = false;
if (get_next_mail(m->_to, m->_cc, m->_ccn, m->_subj, m->_text, m->_attach, m->_ui))
{
const TFilename fn = m->_attach;
xvt_vobj_destroy(883);
done = pr.print_pdf(printer().get_txt(), fn);
if (done)
{
msg << TR("invio ") << fn.name() << TR(" a ") << m->_to;
log.log(0, msg);
mail.add(m);
}
else
{
msg << TR("Impossibile genereare ") << fn;
log.log(2, msg);
}
}
else
{
msg << TR("Impossibile trovare un indirizzo e-mail valido");
log.log(2, msg);
}
if (!done)
delete m;
}
}
}
pr.read_configuration();
}
log.preview();
if (!mail.empty())
{
TArray_sheet sheet(-1, -1, 78, 20, TR("Mail"), HR("@1|Destinatario@32|Messaggio@50"), 0, 1);
FOR_EACH_ARRAY_ITEM(mail, r, obj)
{
const TMail_message& m = *(TMail_message*)obj;
TToken_string* row = new TToken_string;
*row = "X";
row->add(m._to);
row->add(m._text.before('\n'));
sheet.add(row);
}
if (sheet.run() == K_ENTER)
{
const long m = sheet.checked();
if (m > 0 && yesno_box(FR("Confermare l'invio di %ld mail?"), m))
{
FOR_EACH_CHECKED_ROW(sheet, r, row)
{
const TMail_message& m = (const TMail_message&)mail[r];
xvt_mail_send(m._to, m._cc, m._ccn, m._subj, m._text, m._attach, m._ui);
}
}
}
}
return true;
}
bool TStampaSol_application::create()
{
TApplication::create();
open_files(LF_TABCOM, LF_TAB, LF_CAUSALI, LF_MOV, LF_RMOV, 0);
open_files(LF_NDITTE, LF_ANAG, LF_COMUNI, LF_RFORM, 0);
open_files(LF_CLIFO, LF_PARTITE, LF_SCADENZE, LF_PAGSCA ,0);
_msk = new TSol_mask("sc2400a");
return TSkeleton_application::create();
}
bool TStampaSol_application::destroy()
{
delete _msk;
return TSkeleton_application::destroy();
}
void TStampaSol_application::on_config_change()
{
TConfig c(CONFIG_DITTA, "cg");
_lingua_ditta= c.get("CodLin");
_gesval= c.get_bool("GesVal");
}
void TStampaSol_application::on_firm_change()
{
mask().reset();
mask().set(F_STAMPSALDO, "X");
}
void TStampaSol_application::main_loop()
{
TSol_mask& m = mask();
for (;;)
{
const KEY key = m.run();
if (key == K_QUIT)
break;
_form= new TSol_form(m, _gesval, F_DATALIMOP, F_DATALIMSOL, F_GGRISCHIO);
if (key == 'M')
mail_selected();
else
print_selected();
delete _form;
_form= NULL;
}
}
TStampaSol_application::TStampaSol_application(): _lingua_ditta(1), _msk(NULL), _form(NULL) {}
int sc2400(int argc, char** argv)
{
TStampaSol_application app;
app.run(argc, argv, TR("Stampa solleciti"));
return 0;
}