#include #include #include #include #include "../cg/cgsaldac.h" #include "sc1100.h" class TDeletepart_app : public TSkeleton_application { TArchive _arc; TArray _to_zap; // Array contenente le chiavi delle partite da eliminare TDate _datalimite; TString _desc; char _unit; TFilename _tmp_dir; TIsamtempfile *_tpart,*_tscad,*_tpagsca; TLocalisamfile *_part,*_scad,*_pagsca; protected: void backup_delete_partite(); // Backup e cancellazione delle partite da eliminare void restore_partite(); // Ripristino partite cancellate void delete_partite_restored(); // Cancellazione partite ripristinate void create_tmp_files(bool create=TRUE); void delete_tmp_files(bool remove=TRUE); virtual bool create(); virtual bool destroy(); virtual void main_loop(); public: TDate& datalimite() { return _datalimite; } TDeletepart_app() {}; ~TDeletepart_app() {}; }; void TDeletepart_app::backup_delete_partite() { TPartita *partita; TRecnotype total = 0; int err; err = _part->lock(); if (err != NOERR) { error_box(FR("Il file partite non puo' essere bloccato in modo esclusivo." " Nessuna partita cancellata. Errore %d."),err); return; } create_tmp_files(); _part->zero(); // Scorre il file delle partite { TProgind p(10, TR("Ricerca e copia delle partite da eliminare..."), TRUE, FALSE, 10); for (_part->first();_part->good() && !p.iscancelled();_part->read(_isgreat)) { const char tipocf = _part->get_char(PART_TIPOCF); const long codcf = _part->get_long(PART_SOTTOCONTO); const int anno = _part->get_int(PART_ANNO); const TString16 num_part(_part->get(PART_NUMPART)); TBill conto(0,0,codcf,tipocf); partita = new TPartita(conto,anno,num_part); bool to_delete = TRUE; // Scorre le righe di questa partita partendo dall'ultima int r=partita->last(); if (r == 0) to_delete = FALSE; for (;r>0 && to_delete && !p.iscancelled();r=partita->pred(r)) { TRiga_partite& row = partita->riga(r); // Passa alla prossima se trova almeno una riga di partita che non sia CHIUSA o // che abbia la data di registrazione maggiore della data limite // Ovvero: tutte le righe della partita in esame devono avere il flag // CHIUSA settato a TRUE e DATAREG <= della data limite if (!row.get_bool(PART_CHIUSA) || row.get_date(PART_DATAREG) > _datalimite) to_delete = FALSE; // Se TIPOMOV != 1 e' inutile controllare la partita. // N.B. TIPOMOV = 1 quando la partita si riferisce alle scadenze di una fattura if (to_delete && row.get_int(PART_TIPOMOV) == 1) { // Scorre le rate di scadenza per questa riga di partita for (int n=row.rate();(n>0 && to_delete && !p.iscancelled()); n--) { if (row.rata(n).get_date(SCAD_DATASCAD) > _datalimite) to_delete = FALSE; } } } if (to_delete && !p.iscancelled()) // Se TRUE la partita puo' essere eliminata! { // Memorizza la chiave della partita in un array TToken_string id(30); id = _part->get(PART_TIPOCF); id.add(_part->get(PART_SOTTOCONTO)); id.add(_part->get(PART_ANNO)); id.add(_part->get(PART_NUMPART)); _to_zap.add(id); // Memorizza le righe della partita, scadenze e pagsca sui file temporanei // Scorre le righe di partita da eliminare e le scrive sul file temporaneo for (int x=partita->last();x > 0 && err==NOERR;x=partita->pred(x)) { TRiga_partite& row = partita->riga(x); err = _tpart->write(row); // Scorre le righe di scadenza per questa riga di partita e le scrive for (int y=row.rate();y > 0 && err==NOERR; y--) { const TRiga_scadenze& r_scad = row.rata(y); err=_tscad->write(r_scad); // Scorre le righe dei pagamenti relativi alla scadenza e le scrive for (int z=r_scad.last();z > 0 && err==NOERR;z=r_scad.pred(z)) { TRectype pag(r_scad.row(z)); err=_tpagsca->write(pag); } } } total++; } delete partita; _part->put(PART_NRIGA,9999); // Forza la rilettura della prossima partita } // end of for if (p.iscancelled()) total=0; } if (total != 0) if (err==NOERR) { const char * dir = &_tmp_dir[1]; delete_tmp_files(FALSE); //Close tmp files only bool rt = _arc.backup(dir,_unit,_desc,FALSE);// Backup delle partite da eliminare, prefix unnecessary create_tmp_files(FALSE); // Reopen tmp files. if (rt) { // Effettiva cancellazione delle partite TString80 caption(TR("Cancellazione di ")); caption.add_plural(total, TR("partita")); if (!yesno_box(caption)) _to_zap.destroy(); TProgind pi(total, caption, FALSE, TRUE, 10); const int items = _to_zap.items(); for (int i = 0; i < items; i++) { TToken_string& id = (TToken_string&)_to_zap[i]; id.restart(); const char tipocf = id.get_char(); const long codcf = id.get_long(); const int anno = id.get_int(); const TString16 num=id.get(); TBill conto(0,0,codcf,tipocf); partita = new TPartita(conto,anno,num); partita->remove(); delete partita; pi.addstatus(1); } } } else error_box(FR("Errore %d scrivendo sui files temporanei." " La cancellazione delle partite chiuse non verra' effettuata."),err); // Cerca scadenze e pagamenti senza partite: solo su richiesta TString80 caption(TR("Cancellazione scadenze e pagamenti senza partite")); if (err == NOERR && yesno_box(caption)) { TString16 lastpart; int lastanno = 0; TProgind p(10, caption, TRUE, FALSE, 10); // Esamina le scadenze... for (_scad->first(); !_scad->eof() && err == NOERR; _scad->next()) { _part->zero(); _part->put(PART_TIPOCF, _scad->get(SCAD_TIPOCF)); _part->put(PART_GRUPPO, _scad->get(SCAD_GRUPPO)); _part->put(PART_CONTO, _scad->get(SCAD_CONTO)); _part->put(PART_SOTTOCONTO,_scad->get(SCAD_SOTTOCONTO)); lastanno = _scad->get_int(SCAD_ANNO); _part->put(PART_ANNO, lastanno); lastpart = _scad->get(SCAD_NUMPART); _part->put(PART_NUMPART, lastpart); _part->put(PART_NRIGA, _scad->get(SCAD_NRIGA)); if (_part->read(_isequal) != NOERR) err = _scad->remove(); } if (err != NOERR) error_box(FR("Errore %d nella cancellazione delle scadenze %d/%s"), err, lastanno, (const char *)lastpart); else { // ... e i pagamenti for (_pagsca->first(); !_pagsca->eof() && err == NOERR; _pagsca->next()) { _part->zero(); _part->put(PART_TIPOCF, _pagsca->get(PAGSCA_TIPOC)); _part->put(PART_GRUPPO, _pagsca->get(PAGSCA_GRUPPO)); _part->put(PART_CONTO, _pagsca->get(PAGSCA_CONTO)); _part->put(PART_SOTTOCONTO,_pagsca->get(PAGSCA_SOTTOCONTO)); lastanno = _pagsca->get_int(PAGSCA_ANNO); _part->put(PART_ANNO, lastanno); lastpart = _pagsca->get(PAGSCA_NUMPART); _part->put(PART_NUMPART, lastpart); _part->put(PART_NRIGA, _pagsca->get(PAGSCA_NRIGA)); if (_part->read(_isequal) != NOERR) err = _pagsca->remove(); } if (err != NOERR) error_box(FR("Errore %d nella cancellazione dei pagamenti %d/%s"), err, lastanno, (const char *) lastpart); } } delete_tmp_files(); // Physical remove of tmp files _part->unlock(); } void TDeletepart_app::restore_partite() { int err = _part->lock(); if (err != NOERR) { error_box(FR("Il file partite non puo' essere bloccato in modo esclusivo." " Nessuna partita ripristinata. Errore %d."),err); return ; } const char* dir =& _tmp_dir[1]; // Cut out % sign if (_arc.restore(dir,_unit,FALSE,FALSE)) { create_tmp_files(FALSE); // In realta' ci sono gia' // Credo di poter andare a colpo sicuro nel trasferimento // di questi miserabili record, ovvero: se sono stati tolti prima // non dovrebbero esserci piu'... (Colombo's Egg...). Al limite riscrive i record // gia' presenti. const TRecnotype items = _tpart->items() + _tscad->items() + _tpagsca->items(); TProgind pi(items, TR("Ripristino partite eliminate"), FALSE, TRUE, 10); for (_tpart->first();_tpart->good() && err==NOERR;_tpart->next()) { _tpart->put(PART_RICARICATA,TRUE); if ((err=_part->write(_tpart->curr())) == _isreinsert) err=_part->rewrite(_tpart->curr()); pi.addstatus(1); } if (err != NOERR) error_box(FR("Errore %d ripristinando il file PARTITE."),err); else { for (_tscad->first();_tscad->good() && err==NOERR;_tscad->next()) { if ((err=_scad->write(_tscad->curr())) == _isreinsert) err=_scad->rewrite(_tscad->curr()); pi.addstatus(1); } if (err != NOERR) error_box(FR("Errore %d ripristinando il file SCADENZE."),err); else { for (_tpagsca->first();_tpagsca->good() && err==NOERR;_tpagsca->next()) { if ((err=_pagsca->write(_tpagsca->curr())) == _isreinsert) err=_pagsca->rewrite(_tpagsca->curr()); pi.addstatus(1); } if (err != NOERR) error_box(FR("Errore %d ripristinando il file PAGSCA."),err); } } delete_tmp_files(); // Removes tmp files! } else error_box(TR("Errore nel ripristino dei file da dischetto. Nessuna partita ripristinata.")); _part->unlock(); } void TDeletepart_app::delete_partite_restored() { TRecnotype total = 0; TPartita* partita; int err = _part->lock(); if (err != NOERR) { error_box(FR("Il file partite non puo' essere bloccato in modo esclusivo." " Nessuna partita cancellata. Errore %d."), err); return; } _part->zero(); TProgind p(10, TR("Eliminazione partite ricaricate..."), TRUE, FALSE); for (_part->first();_part->good();_part->read(_isgreat)) { if (_part->get_bool(PART_RICARICATA)) { const char tipocf = _part->get_char(PART_TIPOCF); const long codcf = _part->get_long(PART_SOTTOCONTO); const int anno = _part->get_int(PART_ANNO); const TString16 num_part(_part->get(PART_NUMPART)); TBill conto(0,0,codcf,tipocf); partita = new TPartita(conto,anno,num_part); partita->remove(); delete partita; total++; } _part->put(PART_NRIGA,9999); // Forza la rilettura della prossima partita } if (total != 0) message_box(FR("Eliminate %ld partite ricaricate."),total); _part->unlock(); } void TDeletepart_app::create_tmp_files(bool create) { _tpart = new TIsamtempfile(LF_PARTITE, "f1", create); _tscad = new TIsamtempfile(LF_SCADENZE, "f2", create); _tpagsca = new TIsamtempfile(LF_PAGSCA, "f3", create); } void TDeletepart_app::delete_tmp_files(bool remove) { if (remove) // Cosi' posso forzare la cancellazione in chiusura { _tpart->set_autodel(); _tscad->set_autodel(); _tpagsca->set_autodel(); } delete _tpart; delete _tscad; delete _tpagsca; } bool TDeletepart_app::create() { open_files(LF_TABCOM, LF_TAB, LF_PCON, LF_PARTITE, LF_SCADENZE, LF_PAGSCA, 0); _part = new TLocalisamfile(LF_PARTITE); _scad = new TLocalisamfile(LF_SCADENZE); _pagsca = new TLocalisamfile(LF_PAGSCA); return TSkeleton_application::create(); } bool TDeletepart_app::destroy() { delete _part; delete _scad; delete _pagsca; return TSkeleton_application::destroy(); } void TDeletepart_app::main_loop() { TMask m("sc1100a"); while (m.run() != K_QUIT) { _datalimite = m.get(F_DATE); _unit = m.get(F_UNIT)[0]; _desc = m.get(F_DESC); int scelta = m.get_int(F_OPERAZIONE); switch (scelta) { case 1: backup_delete_partite(); break; case 2: restore_partite(); break; case 3: delete_partite_restored(); break; default: break; } } } int sc1100(int argc, char** argv) { TDeletepart_app a; a.run(argc, argv, TR("Archiviazione partite pareggiate")); return 0; }