2018-07-06 16:30:37 +02:00
|
|
|
|
#include <applicat.h>
|
|
|
|
|
#include <automask.h>
|
|
|
|
|
#include <config.h>
|
2018-07-25 15:53:29 +02:00
|
|
|
|
#include "fplib01.h"
|
2018-07-06 16:30:37 +02:00
|
|
|
|
#include <progind.h>
|
2018-07-25 15:53:29 +02:00
|
|
|
|
#include <cfven.h>
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
#include "../ve/velib05.h"
|
|
|
|
|
#include "../cg/cglib03.h"
|
2018-07-25 15:53:29 +02:00
|
|
|
|
#include "../fe/felib.h"
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
#include "fp0.h"
|
|
|
|
|
#include "fp0300a.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Globals
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#define LEN_HFATT 20
|
|
|
|
|
#define LEN_BFATT 50
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// TPa_mask
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class TPA_mask : public TAutomask
|
|
|
|
|
{
|
|
|
|
|
protected:
|
2018-07-24 18:09:54 +02:00
|
|
|
|
void set_filter_changed();
|
2018-07-06 16:30:37 +02:00
|
|
|
|
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
|
|
|
|
void next_page(int p);
|
|
|
|
|
bool checkNotEmpty();
|
|
|
|
|
|
|
|
|
|
void fill();
|
|
|
|
|
void init();
|
|
|
|
|
bool is_fattura(const TRectype& doc) const;
|
|
|
|
|
|
|
|
|
|
bool _filter_changed;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TPA_mask() : TAutomask("fp0300a"), _filter_changed(true)
|
|
|
|
|
{
|
2018-07-24 18:09:54 +02:00
|
|
|
|
disable(DLG_OK);
|
2018-07-06 16:30:37 +02:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool TPA_mask::is_fattura(const TRectype& doc) const
|
|
|
|
|
{
|
|
|
|
|
const TTipo_documento& td = cached_tipodoc(doc.get(DOC_TIPODOC));
|
|
|
|
|
if (!td.is_fattura()) // Tengo per buone solo le fatture e le note di credito
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const TCodice_numerazione& cn = cached_numerazione(doc.get(DOC_CODNUM));
|
|
|
|
|
return cn.tipo() == 2 && !cn.get_bool("B10"); // Controlla se fattura provvisioria esclusa da P.A.
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 16:01:13 +02:00
|
|
|
|
TString& add_filter(const TString& field, const TString& from, const TString& to)
|
|
|
|
|
{
|
|
|
|
|
TString& query = get_tmp_string();
|
|
|
|
|
const TString qf = field.find('.') < 0 ? field : field.sub(field.find('.') + 1);
|
|
|
|
|
|
|
|
|
|
if (from.full() && to.full())
|
|
|
|
|
{
|
|
|
|
|
query << "&&(BETWEEN(" << field << ", #DA" << qf << ", #A" << qf << "))";
|
|
|
|
|
}
|
|
|
|
|
else if (from.full())
|
|
|
|
|
{
|
|
|
|
|
query << "&&(" << field << ">=#DA" << qf << ")";
|
|
|
|
|
}
|
|
|
|
|
else if (to.full())
|
|
|
|
|
{
|
|
|
|
|
query << "&&(" << field << "<=#A" << qf << ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return query;
|
|
|
|
|
}
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
void TPA_mask::fill()
|
|
|
|
|
{
|
2018-07-24 18:09:54 +02:00
|
|
|
|
|
2018-07-06 16:30:37 +02:00
|
|
|
|
TSheet_field& docs = sfield(F_DOCS);
|
|
|
|
|
TString_array& sht = docs.rows_array();
|
|
|
|
|
docs.hide();
|
|
|
|
|
|
|
|
|
|
sht.destroy();
|
|
|
|
|
|
|
|
|
|
const TDate dal = get(F_DATAINI);
|
2018-07-24 18:09:54 +02:00
|
|
|
|
TString filter_selected = get(F_FATTSEL);
|
|
|
|
|
enable(DLG_OK, filter_selected != "N");
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
// Record di controllo per eventuali elaborazioni precedenti
|
|
|
|
|
TString hfatt(LEN_HFATT), bfatt(LEN_BFATT);
|
|
|
|
|
TPaf_record paf0100f("PAF0100F");
|
|
|
|
|
|
|
|
|
|
TString query;
|
|
|
|
|
|
|
|
|
|
query << "USE 33 " <<
|
2018-07-24 18:09:54 +02:00
|
|
|
|
"SELECT (BETWEEN(33.DATADOC,#DADATADOC,#ADATADOC))&&(33.TIPOCF=='C')";
|
2018-07-31 16:01:13 +02:00
|
|
|
|
|
|
|
|
|
query << add_filter("33.TIPODOC", get(F_DATIPODOC), get(F_ATIPODOC));
|
|
|
|
|
|
2018-07-06 16:30:37 +02:00
|
|
|
|
query << "\nJOIN 20 INTO TIPOCF==TIPOCF CODCF==CODCF \n" <<
|
|
|
|
|
"JOIN 17 TO 33 INTO TIPOCF==TIPOCF CODCF==CODCF \n" <<
|
|
|
|
|
"JOIN %TIP TO 33 ALIAS 400 INTO CODTAB==TIPODOC";
|
|
|
|
|
|
|
|
|
|
TISAM_recordset rec(query);
|
|
|
|
|
if (get(F_DATIPODOC).full())
|
|
|
|
|
rec.set_var("#DATIPODOC", get(F_DATIPODOC));
|
|
|
|
|
if (get(F_ATIPODOC).full())
|
|
|
|
|
rec.set_var("#ATIPODOC", get(F_ATIPODOC));
|
|
|
|
|
|
|
|
|
|
rec.set_var("#DADATADOC", get_date(F_DATAINI));
|
|
|
|
|
rec.set_var("#ADATADOC", get_date(F_DATAEND));
|
|
|
|
|
|
|
|
|
|
TProgress_monitor pi(rec.items(), NULL);
|
|
|
|
|
|
2018-07-25 10:01:48 +02:00
|
|
|
|
bool first, show, ask = !((show = (first = true)));
|
2018-07-24 18:09:54 +02:00
|
|
|
|
|
2018-07-25 10:01:48 +02:00
|
|
|
|
// Disabilito la colonna del codice ufficio
|
|
|
|
|
docs.enable_column(docs.cid2index(S_UFFICIO), false);
|
2018-07-24 18:09:54 +02:00
|
|
|
|
|
2018-07-06 16:30:37 +02:00
|
|
|
|
for (bool okc = rec.move_first(); okc; okc = rec.move_next())
|
|
|
|
|
{
|
|
|
|
|
if (!pi.add_status())
|
|
|
|
|
break;
|
|
|
|
|
const TRectype& doc = rec.cursor()->curr();
|
|
|
|
|
const TTipo_documento& td = cached_tipodoc(doc.get(DOC_TIPODOC));
|
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
// Controllo che il tipo documento sia OK
|
|
|
|
|
if (td.tipo_doc_sdi().empty() || td.reg_fisc().empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
2018-07-06 16:30:37 +02:00
|
|
|
|
bool sent = false;
|
|
|
|
|
if (chiave_paf(doc, hfatt, bfatt))
|
|
|
|
|
{
|
2018-07-24 18:09:54 +02:00
|
|
|
|
if (paf0100f.search(NULL, hfatt, bfatt))
|
|
|
|
|
{
|
|
|
|
|
if (paf0100f.sq_get("P1_GESTIONE") != filter_selected)
|
|
|
|
|
continue;
|
|
|
|
|
sent = true;
|
|
|
|
|
}
|
|
|
|
|
else if (filter_selected.not_empty())
|
|
|
|
|
continue;
|
2018-07-06 16:30:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
TToken_string& row = docs.row(-1);
|
|
|
|
|
row = sent ? " " : "X";
|
|
|
|
|
row.add(rec.get(DOC_ANNO).as_int(), 1);
|
|
|
|
|
row.add(rec.get(DOC_CODNUM).as_string());
|
|
|
|
|
row.add(rec.get(DOC_TIPODOC).as_string());
|
|
|
|
|
row.add(td.tipo_doc_sdi());
|
|
|
|
|
row.add(rec.get(DOC_NDOC).as_int());
|
|
|
|
|
row.add(rec.get(DOC_DATADOC).as_date());
|
|
|
|
|
row.add(rec.get(CFV_CODCF).as_int());
|
|
|
|
|
row.add(rec.get("20." CLI_RAGSOC).as_string());
|
2018-07-23 11:42:24 +02:00
|
|
|
|
TString rif = rec.get("17." CFV_PADESTIN).as_string();
|
|
|
|
|
if (rif.empty())
|
|
|
|
|
rif = rec.get("20.PEC").as_string();
|
2018-07-24 18:09:54 +02:00
|
|
|
|
// Se <20> ancora vuoto potrebbe essere estero
|
|
|
|
|
if(rif.empty())
|
|
|
|
|
{
|
|
|
|
|
static TString codcf; codcf.cut(0) << "C|" << rec.get(CFV_CODCF).as_string();
|
|
|
|
|
TAnagrafica a(LF_CLIFO, codcf);
|
|
|
|
|
if (a.estero())
|
|
|
|
|
rif = "XXXXXXX";
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-07-25 10:01:48 +02:00
|
|
|
|
// Segno la riga errata
|
|
|
|
|
if (first)
|
|
|
|
|
{
|
|
|
|
|
// Abilito la colonna del codice ufficio per segnalare l'errore
|
|
|
|
|
docs.enable_column(docs.cid2index(S_UFFICIO));
|
|
|
|
|
}
|
|
|
|
|
docs.set_back_and_fore_color(COLOR_RED, COLOR_WHITE, rec.current_row(), docs.cid2index(S_UFFICIO));
|
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
if (show)
|
|
|
|
|
{
|
|
|
|
|
TString msg; msg << "Trovata fattura " << rec.get(DOC_CODNUM).as_string() << "/" << rec.get(DOC_TIPODOC).as_string() << "/" << rec.get(DOC_NDOC).as_int() << " senza nessun codice destinatario/pec, Continuare?";
|
|
|
|
|
const bool force_stop = !yesno_box(msg);
|
|
|
|
|
if (!first && !ask && !force_stop)
|
|
|
|
|
{
|
|
|
|
|
show = yesno_box("Continuare a mostrare questo messaggio?");
|
|
|
|
|
ask = true;
|
|
|
|
|
}
|
|
|
|
|
if (force_stop)
|
|
|
|
|
{
|
|
|
|
|
row.cut(0);
|
|
|
|
|
docs.force_update();
|
|
|
|
|
docs.show();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-25 10:01:48 +02:00
|
|
|
|
if(rif.full())
|
|
|
|
|
docs.set_back_and_fore_color(COLOR_WHITE, COLOR_BLACK, rec.cursor()->pos(), docs.cid2index(S_UFFICIO));
|
2018-07-24 18:09:54 +02:00
|
|
|
|
row.add(rif);
|
|
|
|
|
row.add(rec.get("17." CFV_PARIFAMM).as_string());
|
|
|
|
|
row.add(rec.get("20." CLI_COFI).as_string());
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
bool split = rec.get("20." CLI_SPLITPAY).as_bool();
|
|
|
|
|
if (split)
|
|
|
|
|
{
|
|
|
|
|
const long numreg = rec.get(DOC_NUMREG).as_int();
|
|
|
|
|
if (numreg > 0)
|
|
|
|
|
{
|
|
|
|
|
const TRectype& mov = cache().get(LF_MOV, numreg);
|
|
|
|
|
split = is_split_payment(mov);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-24 18:09:54 +02:00
|
|
|
|
row.add(split ? "X" : " ");
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
const bool attach = !rec.get("COLL_GOLEM").is_empty();
|
2018-07-24 18:09:54 +02:00
|
|
|
|
row.add(attach ? "X" : " ");
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
row.add(!td.invio_xml() ? "X" : "");
|
2018-07-06 16:30:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
docs.force_update();
|
|
|
|
|
docs.show();
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
void TPA_mask::set_filter_changed()
|
2018-07-06 16:30:37 +02:00
|
|
|
|
{
|
|
|
|
|
_filter_changed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TPA_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
|
|
|
|
{
|
|
|
|
|
switch (o.dlg())
|
|
|
|
|
{
|
|
|
|
|
case DLG_RECALC:
|
|
|
|
|
if (e == fe_button)
|
|
|
|
|
next_page(1);
|
|
|
|
|
break;
|
|
|
|
|
case F_DATAINI:
|
|
|
|
|
if (e == fe_init)
|
|
|
|
|
o.set(ini_get_string(CONFIG_DITTA, "fp", "LastXML", "01-01-2018"));
|
|
|
|
|
else if (e == fe_close)
|
|
|
|
|
ini_set_string(CONFIG_DITTA, "fp", "LastXML", o.get());
|
|
|
|
|
break;
|
|
|
|
|
case F_DATAEND:
|
|
|
|
|
if (e == fe_init)
|
|
|
|
|
o.set(TDate(TODAY));
|
|
|
|
|
case F_DOCS:
|
|
|
|
|
if (e == se_query_add || e == se_query_del)
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
|
|
|
|
case DLG_USER:
|
|
|
|
|
if (e == fe_button && jolly > 0)
|
|
|
|
|
{
|
|
|
|
|
TSheet_field& docs = sfield(F_DOCS);
|
|
|
|
|
TToken_string& row = docs.row(docs.selected());
|
|
|
|
|
TRectype doc(LF_DOC);
|
|
|
|
|
doc.put(DOC_PROVV, 'D');
|
|
|
|
|
doc.put(DOC_ANNO, row.get(1));
|
|
|
|
|
doc.put(DOC_CODNUM, row.get(2));
|
|
|
|
|
doc.put(DOC_TIPODOC, row.get(3));
|
|
|
|
|
doc.put(DOC_NDOC, row.get(5));
|
|
|
|
|
if (doc.edit())
|
|
|
|
|
fill();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case DLG_ALL:
|
|
|
|
|
{
|
|
|
|
|
if (e == fe_button)
|
|
|
|
|
{
|
|
|
|
|
TSheet_field& docs = sfield(F_DOCS);
|
|
|
|
|
TString_array& sht = docs.rows_array();
|
|
|
|
|
const int items = sht.items();
|
|
|
|
|
|
|
|
|
|
if (items > 0)
|
|
|
|
|
{
|
|
|
|
|
const TString4 select = *(sht.row(0).get(0)) == 'X' ? "" : "X";
|
|
|
|
|
for (int i = 0; i < items; i++)
|
|
|
|
|
sht.row(i).add(select, 0);
|
|
|
|
|
docs.force_update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
if (e == fe_modify && jolly == 0)
|
|
|
|
|
{
|
|
|
|
|
if (o.dlg() >= START_MASK && o.dlg() <= END_MASK)
|
|
|
|
|
{
|
2018-07-24 18:09:54 +02:00
|
|
|
|
set_filter_changed();
|
2018-07-06 16:30:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPA_mask::next_page(int p)
|
|
|
|
|
{
|
|
|
|
|
TAutomask::next_page(p);
|
|
|
|
|
if (_filter_changed)
|
|
|
|
|
{
|
|
|
|
|
TSheet_field& sf = sfield(F_DOCS);
|
|
|
|
|
if (curr_win() == sf.parent())
|
|
|
|
|
{
|
|
|
|
|
fill();
|
|
|
|
|
sf.force_update();
|
|
|
|
|
_filter_changed = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TPA_mask::checkNotEmpty()
|
|
|
|
|
{
|
|
|
|
|
TSheet_field& sheet = sfield(F_DOCS);
|
|
|
|
|
TString msg;
|
|
|
|
|
|
|
|
|
|
if (sheet.empty())
|
|
|
|
|
msg = "La tabella dei movimenti <20> vuota, vuoi caricarla con i filtri selezionati?";
|
|
|
|
|
else if (_filter_changed)
|
|
|
|
|
msg = "I filtri sono stati cambiati, vuoi ricaricare la tabella con i nuovi filtri selezionati?";
|
|
|
|
|
|
|
|
|
|
if (msg.full() && yesno_box(msg))
|
|
|
|
|
{
|
|
|
|
|
next_page(1);
|
|
|
|
|
}
|
|
|
|
|
return sheet.full();
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-24 18:09:54 +02:00
|
|
|
|
|
2018-07-06 16:30:37 +02:00
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// TDoc2Paf
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class TDoc2Paf : public TSkeleton_application
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
virtual bool create();
|
|
|
|
|
virtual bool destroy();
|
|
|
|
|
virtual void main_loop();
|
|
|
|
|
|
2018-07-25 15:53:29 +02:00
|
|
|
|
TDoc2Paf() {}
|
2018-07-06 16:30:37 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void TDoc2Paf::main_loop()
|
|
|
|
|
{
|
|
|
|
|
int ndocs = 0;
|
|
|
|
|
TPA_mask mask;
|
|
|
|
|
while (mask.run() == K_ENTER)
|
|
|
|
|
{
|
|
|
|
|
TString_array& sht = mask.sfield(F_DOCS).rows_array();
|
2018-07-31 16:01:13 +02:00
|
|
|
|
TDoc_fp elab;
|
|
|
|
|
//elab.set_cache_insert(true);
|
2018-07-06 16:30:37 +02:00
|
|
|
|
if (!sht.empty())
|
|
|
|
|
{
|
2018-07-25 15:53:29 +02:00
|
|
|
|
TProgress_monitor pi(sht.items(), "Esportazione Fatture");
|
2018-07-06 16:30:37 +02:00
|
|
|
|
ndocs = 0;
|
|
|
|
|
FOR_EACH_ARRAY_ROW(sht, r, riga)
|
|
|
|
|
{
|
|
|
|
|
if (riga->starts_with("X"))
|
|
|
|
|
{
|
|
|
|
|
const int anno = riga->get_int(mask.sfield(F_DOCS).cid2index(S_ANNO));
|
|
|
|
|
const long ndoc = riga->get_long(mask.sfield(F_DOCS).cid2index(S_NDOC));
|
|
|
|
|
const TFixed_string codnum(riga->get(mask.sfield(F_DOCS).cid2index(S_CODNUM))); // lascio sapientemente per ultima la get di una stringa
|
|
|
|
|
const TDoc_key key(anno, codnum, ndoc);
|
2018-07-25 15:53:29 +02:00
|
|
|
|
if (elab.doc_to_paf(key))
|
2018-07-06 16:30:37 +02:00
|
|
|
|
ndocs++;
|
|
|
|
|
}
|
|
|
|
|
if (!pi.add_status(1))
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-07-31 16:01:13 +02:00
|
|
|
|
}
|
|
|
|
|
if (ndocs > 0)
|
|
|
|
|
{
|
|
|
|
|
if (elab.commit() > 0)
|
2018-07-24 18:13:05 +02:00
|
|
|
|
{
|
2018-07-31 16:01:13 +02:00
|
|
|
|
message_box(FR("Sono stati elaborati %d documenti"), ndocs);
|
2018-07-24 18:13:05 +02:00
|
|
|
|
}
|
2018-07-31 16:01:13 +02:00
|
|
|
|
else
|
|
|
|
|
error_box("Errore durante il salvataggio");
|
|
|
|
|
elab.show_log();
|
2018-07-06 16:30:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TDoc2Paf::create()
|
|
|
|
|
{
|
|
|
|
|
open_files(LF_TAB, LF_TABCOM, LF_TABMOD, LF_ANAG,
|
|
|
|
|
LF_CLIFO, LF_CFVEN, LF_CFBAN, LF_NDITTE,
|
|
|
|
|
LF_DOC, LF_RIGHEDOC, 0);
|
|
|
|
|
|
|
|
|
|
TRectype cfven(LF_CFVEN);
|
2018-07-25 15:53:29 +02:00
|
|
|
|
if (cfven.length(CFV_PADESTIN) != 7) // Nuova lunghezza per privati
|
2018-07-17 16:31:00 +02:00
|
|
|
|
return error_box(TR("Database non convertito per fatturazione F.P."));
|
2018-07-06 16:30:37 +02:00
|
|
|
|
|
|
|
|
|
return check_tables() && TSkeleton_application::create();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TDoc2Paf::destroy()
|
|
|
|
|
{
|
|
|
|
|
db().sq_disconnect();
|
|
|
|
|
return TSkeleton_application::destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int fp0300(int argc, char* argv[])
|
|
|
|
|
{
|
|
|
|
|
TDoc2Paf d2p;
|
2018-07-17 16:31:00 +02:00
|
|
|
|
d2p.run(argc, argv, TR("Fatturazione F.P."));
|
2018-07-06 16:30:37 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|