201a3466f2
git-svn-id: svn://10.65.10.50/branches/R_10_00@22911 c028cbd2-c16b-5b4b-a496-9718f37d4682
533 lines
16 KiB
C++
Executable File
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;
|
|
}
|