#include "sc0300a.h" #include "../cg/cgsalda3.h" #include #include #include #include #include #include #include #include class TPareggio_tree : public TObject_tree { TPartite_array _games; protected: virtual TFieldtypes get_var(const TString& name, TVariant& var) const; public: bool init(const TBill& bill, const TString& valuta, bool nc, int stato); // Stato: 1=aperte; 2=chiuse; 0 o 3 = tutte TPartita& partita(const TRectype& rec) const; const TRectype* node2rec(const TString& id); }; TPartita& TPareggio_tree::partita(const TRectype& rec) const { return ((TPartite_array&)_games).partita(rec); } const TRectype* TPareggio_tree::node2rec(const TString& id) { const TRectype* rec = NULL; if (id.blank() || goto_node(id)) { const TObject* obj = curr_node(); if (obj->is_kind_of(CLASS_RECTYPE)) rec = (const TRectype*)obj; } return rec; } TFieldtypes TPareggio_tree::get_var(const TString& name, TVariant& var) const { TFieldtypes ft = _nullfld; const TObject* obj = curr_node(); if (obj != NULL) { if (obj->is_kind_of(CLASS_RECTYPE)) { const TRectype& rec = *(const TRectype*)obj; ft = rec.type(name); if (ft != _nullfld) { if (ft == _realfld) { var = rec.get_real(name).stringa(0, 2); ft = _alfafld; } else var = rec.get(name); } else { if (name.starts_with("PART.", true)) { const TString& fld = name.after("."); if (rec.num() == LF_SCADENZE) { const int nriga = rec.get_int(SCAD_NRIGA); const TPartita& game = partita(rec); var = game.riga(nriga).get(fld); ft = _alfafld; } else { var = rec.get(fld); ft = _alfafld; } } else if (name == "RESIDUO") { TImporto saldo; switch (rec.num()) { case LF_SCADENZE: if (!rec.get_bool(SCAD_PAGATA)) { const TPartita& game = partita(rec); const TRiga_scadenze& s = game.rata(rec.get_int(SCAD_NRIGA), rec.get_int(SCAD_NRATA)); saldo = s.residuo(true); } break; case LF_PARTITE: if (!rec.get_bool(PART_CHIUSA)) { const TPartita& game = partita(rec); saldo = game.calcola_saldo(true); } break; default: break; } var = saldo.valore().stringa(0, 2); ft = _alfafld; } } } else { if (name == PART_NUMPART) { const real& year = *(real*)obj; var = year.integer(); ft = _intfld; } } } return ft; } bool TPareggio_tree::init(const TBill& bill, const TString& valuta, bool nc, int stato) { goto_root(); kill_node(); TString filter; if (bill.tipo() > ' ') filter << PART_TIPOCF << '=' << bill.tipo(); else { filter << PART_GRUPPO << '=' << bill.gruppo() << ' '; filter << PART_CONTO << '=' << bill.conto(); } filter << ' ' << PART_SOTTOCONTO << '=' << bill.sottoconto(); TString query; query << "USE PART SELECT (NRIGA<9999)&&(TIPOMOV<=" << (nc ? tm_nota_credito : tm_fattura) << ')' << "\nFROM " << filter << "\nTO " << filter; TISAM_recordset games(query); const TRectype& rec = games.cursor()->curr(); int last_year = 0; TString80 id_year, id_rec; TProgind pi(games.items(), nc ? TR("Caricamento note di credito") : TR("Caricamento fatture")); for (bool ok = games.move_first(); ok; ok = games.move_next()) { if (!pi.addstatus(1)) break; const TString& codval = rec.get(PART_CODVAL); if (!same_values(codval, valuta)) continue; const tipo_movimento tm = (tipo_movimento)rec.get_int(PART_TIPOMOV); bool add_riga = true; if (nc) { add_riga = !rec.get_bool(PART_CHIUSA); if (add_riga) { // Se filtro le note di credito cerco di riconoscere le fatture negative if (tm == tm_fattura) { const char sezione_positiva = bill.tipo() == 'C' ? 'D' : 'A'; TImporto importo(rec.get_char(PART_SEZ), rec.get_real(PART_IMPORTO)); importo.normalize(); add_riga = sezione_positiva != importo.sezione(); // Ignora fattura positiva } else { const int nriga = rec.get_int(PART_NRIGA); const TPartita& game = partita(rec); add_riga = ((TPartita&)game).unassigned().exist(nriga); } } } else { if (stato == 1 || stato == 2) { const bool chiusa = rec.get_bool(PART_CHIUSA); if (chiusa) add_riga = stato == 2; else add_riga = stato == 1; } if (add_riga) { const char sezione_positiva = bill.tipo() == 'C' ? 'D' : 'A'; TImporto importo(rec.get_char(PART_SEZ), rec.get_real(PART_IMPORTO)); importo.normalize(); add_riga = sezione_positiva == importo.sezione(); // Ignora fattura negativa } } if (!add_riga) continue; const int year = rec.get_int(PART_ANNO); if (year != last_year) { goto_root(); while(goto_rbrother()); add_rbrother(real(year)); last_year = year; curr_id(id_year); id_rec.cut(0); } if (nc) { if (id_rec.full()) { goto_node(id_rec); add_rbrother(rec); } else add_son(rec); curr_id(id_rec); } else { TPartita& game = partita(rec); const TRiga_partite& riga = game.riga(rec.get_int(PART_NRIGA)); for (int rata = 1; rata <= riga.rate(); rata++) { const TRiga_scadenze& s = riga.rata(rata); bool add_rata = true; if (stato == 1 || stato == 2) { const bool chiusa = s.get_bool(SCAD_PAGATA); if (chiusa) add_rata = stato == 2; else add_rata = stato == 1; } if (add_rata) { if (id_rec.full()) add_rbrother(s); else add_son(s); curr_id(id_rec); } } } } if (goto_node(id_year)) expand(); return goto_root(); } /////////////////////////////////////////////////////////// // TScad_mask /////////////////////////////////////////////////////////// class TScad_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TScad_mask() : TAutomask("sc0300b") {} }; bool TScad_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_TUTTE: if (e == se_query_add || e == se_query_del) return false; break; default: break; } return true; } /////////////////////////////////////////////////////////// // TPareggio_mask /////////////////////////////////////////////////////////// class TPareggio_mask : public TAutomask { TPareggio_tree _nc, _ft; long _numreg; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); const TString& causale_nc_reg(const TString& reg) const; bool converti(const TRectype& rec); bool abbuona_rata(const real& imp, const TRectype& nota, TRiga_scadenze& scad); bool elabora(const TRectype& nota, const TPointer_array& fatture); public: TPareggio_mask(); }; // Cerca una causale di nota di credito sul registro reg const TString& TPareggio_mask::causale_nc_reg(const TString& reg) const { if (reg.full()) { const TString& codcaus = get(get(F_TIPO) == "C" ? F_CODCAUS_C : F_CODCAUS_F); const TString& cr = cache().get(LF_CAUSALI, codcaus, CAU_REG); if (cr == reg) return codcaus; // Siamo fortunati: va bene la causale standard TISAM_recordset recset("USE CAUS SELECT (REG=#CODREG)&&(TIPOMOV=2)"); recset.set_var("#CODREG", reg); if (recset.move_first()) return recset.get(CAU_CODCAUS).as_string(); } return EMPTY_STRING; } bool TPareggio_mask::converti(const TRectype& rec) { CHECK(rec.num() == LF_PARTITE, "Solo partite, grazie!"); const long numreg = rec.get_long(PART_NREG); const TString4 codreg = rec.get(PART_REG); const TString4 codcau = causale_nc_reg(codreg); if (codcau.blank()) return error_box(FR("E' necessario creare una causale di note di credito sul registro %s"), (const char*)codreg); TString msg; msg << TR("Si desidera trasformare la fattura in nota di credito con causale ") << codcau << '\n' << cache().get(LF_CAUSALI, codcau, CAU_DESCR); if (!yesno_box(msg)) return false; int err = NOERR; if (numreg > 0) { TLocalisamfile mov(LF_MOV); mov.curr().put(MOV_NUMREG, numreg); err = mov.read(_isequal, _lock); if (err == NOERR) { mov.put(MOV_CODCAUS, codcau); mov.put(MOV_TIPOMOV, tm_nota_credito); err = mov.rewrite(); } if (err != NOERR) return error_box(FR("Impossibile modificare il movimento %ld: errore %d"), numreg, err); } if (err == NOERR) { TPartita& game = _nc.partita(rec); const int nriga = game.prima_fattura(numreg); if (nriga > 0) { TRiga_partite& fatt = game.riga(nriga); fatt.put(PART_CODCAUS, codcau); fatt.put(PART_TIPOMOV, tm_nota_credito); TRectype& pag = game.unassigned().row(nriga, true); pag.put(PAGSCA_IMPORTO, fatt.get(PART_IMPORTO)); err = game.rewrite() ? NOERR : _islocked; } else err = _iskeynotfound; } if (err != NOERR) return error_box(FR("Impossibile modificare la partita associata la movimento %ld: errore %d"), numreg, err); return true; } bool TPareggio_mask::abbuona_rata(const real& imp, const TRectype& nota, TRiga_scadenze& scad) { const TValuta valuta(scad.riga()); const char* imp_field = valuta.in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; TPartita& old_nc = _nc.partita(nota); TPartita& ft = scad.partita(); TRiga_partite& new_nc = ft.new_row(); new_nc.put(PART_SEZ, scad.riga().get_char(PART_SEZ) == 'D' ? 'A' : 'D'); new_nc.put(PART_NREG, nota.get(PART_NREG)); new_nc.put(PART_CODCAUS, nota.get(PART_CODCAUS)); new_nc.put(PART_REG, nota.get(PART_REG)); new_nc.put(PART_NUMDOC, nota.get(PART_NUMDOC)); new_nc.put(PART_DATADOC, nota.get(PART_DATADOC)); TRectype new_pag = scad.new_row(new_nc.get_int(PART_NRIGA)); new_pag.put(imp_field, imp); ft.modifica_pagamento(new_pag, valuta, true); TRectype unass = old_nc.unassigned().row(nota.get_int(PART_NRIGA)); if (new_nc.get(PART_SEZ) == nota.get(PART_SEZ)) unass.add(imp_field, -imp); else unass.add(imp_field, imp); old_nc.modifica_pagamento(unass, valuta, true); return true; } bool TPareggio_mask::elabora(const TRectype& nota, const TPointer_array& scadenze) { CHECK(nota.num() == LF_PARTITE, "Solo partite, grazie!"); const tipo_movimento tm = (tipo_movimento)nota.get_int(PART_TIPOMOV); if (tm == tm_fattura && !converti(nota)) return false; TScad_mask ass; const TString& codval = get(F_CODVAL); ass.set(F_CODVAL, codval); TSheet_field& sheet = ass.sfield(F_TUTTE); real residuo_nc = abs(nota.get_real(is_true_value(codval) ? PART_IMPORTOVAL : PART_IMPORTO)); TString_array rate; FOR_EACH_ARRAY_ITEM(scadenze, i, s) { const TRiga_scadenze& scad = *(TRiga_scadenze*)s; TToken_string& row = sheet.row(-1); const real residuo_scad = scad.residuo(true).valore(); real imp = residuo_nc; if (imp > residuo_scad) imp = residuo_scad; row.add(imp.string()); residuo_nc -= imp; row.add(residuo_scad.string()); row.add(scad.importo(true).valore().string()); row.add(scad.get(SCAD_DATASCAD)); } if (ass.run() == K_ENTER) { FOR_EACH_SHEET_ROW(sheet, r, row) { const real imp = row->get(0); if (imp > ZERO) { TRiga_scadenze& scad = (TRiga_scadenze&)scadenze[r]; abbuona_rata(imp, nota, scad); } } } return true; } bool TPareggio_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { //case F_SOTTOCONTO: case F_CLIENTE: case F_FORNITORE: case F_CODVAL: case F_TUTTE: if (e == fe_modify && !o.empty()) { TWait_cursor hourglass; const short id = efield(F_FORNITORE).active() ? F_FORNITORE : (efield(F_SOTTOCONTO).active() ? F_SOTTOCONTO : F_CLIENTE); TBill bill; bill.get(*this, F_GRUPPO, F_CONTO, id, F_TIPO); const int tipo = get_int(F_TUTTE); const TString& codval = get(F_CODVAL); _nc.init(bill, codval, true, 1); // Solo aperte _ft.init(bill, codval, false, tipo); tfield(F_NC_TREE).set_tree(&_nc); tfield(F_FT_TREE).set_tree(&_ft); _numreg = 0; disable(DLG_LINK); disable(DLG_RECALC); } break; case F_CODCAUS_C: case F_CODCAUS_F: if (e == fe_init) { TEdit_field& e = (TEdit_field&)o; TCursor& cur = *e.browse()->cursor(); cur = 0L; e.set(cur.curr().get(CAU_CODCAUS)); } break; case F_NC_TREE: case F_FT_TREE: if (e == fe_button || e == fe_modify) { TTree_field& tf = (TTree_field&)o; TVariant var; if (tf.tree()->get_var("PART.NREG", var)) _numreg = var.as_int(); else _numreg = 0L; enable(DLG_LINK, _numreg > 0); bool can_conv = false; if (_numreg > 0 && o.dlg() == F_NC_TREE) { TLocalisamfile mov(LF_MOV); mov.put(MOV_NUMREG, _numreg); can_conv = mov.read() == NOERR && mov.get_int(MOV_TIPOMOV) == tm_fattura; } enable(DLG_RECALC, can_conv); } break; case DLG_LINK: if (_numreg > 0) { TRectype mov(LF_MOV); mov.put(MOV_NUMREG, _numreg); if (mov.edit()) send_key(K_SPACE, F_TUTTE, &o); } break; case DLG_RECALC: if (e == fe_button) { TTree_field& nc = tfield(F_NC_TREE); TPareggio_tree* nct = (TPareggio_tree*)nc.tree(); const TRectype* nota = nct->node2rec(EMPTY_STRING); if (nota != NULL && converti(*nota)) send_key(K_SPACE, F_TUTTE, &o); } break; case DLG_ELABORA: if (e == fe_button) { TTree_field& nc = tfield(F_NC_TREE); TTree_field& ft = tfield(F_FT_TREE); TPareggio_tree* nct = (TPareggio_tree*)nc.tree(); const TRectype* nota = nct->node2rec(EMPTY_STRING); if (nota == NULL) return error_box(TR("Selezionare una nota di credito nel pannello di sinistra")); TPointer_array fatture; TString_array a; if (ft.selection(a) > 0) { TPareggio_tree* ftt = (TPareggio_tree*)ft.tree(); FOR_EACH_ARRAY_ROW(a, r, riga) { const TRectype* rec = ftt->node2rec(*riga); if (rec) fatture.add((TRectype*)rec); } } if (fatture.items() > 0) elabora(*nota, fatture); else return error_box(TR("Selezionare almeno una fattura nel pannello di destra")); } break; default: break; } return true; } TPareggio_mask::TPareggio_mask() : TAutomask("sc0300a"), _numreg(0L) { RCT rct_nc; field(F_NC_TREE).get_rect(rct_nc); RCT rct_ft; field(F_FT_TREE).get_rect(rct_ft); rct_nc.right = rct_ft.left-8; rct_ft.right = rct_ft.left + rct_nc.right - rct_nc.left; field(F_NC_TREE).set_rect(rct_nc); field(F_FT_TREE).set_rect(rct_ft); } /////////////////////////////////////////////////////////// // TPareggio_partite /////////////////////////////////////////////////////////// class TPareggio_partite : public TSkeleton_application { protected: virtual void main_loop(); }; void TPareggio_partite::main_loop() { const int anno = xvt_vobj_get_attr(NULL_WIN, ATTR_APPL_VERSION_YEAR); if (anno > 2101) { TPareggio_mask pm; pm.run(); } else error_box(TR("Versione non supportata: %d"), anno); } /////////////////////////////////////////////////////////// // Main /////////////////////////////////////////////////////////// int sc0300(int argc, char* argv[]) { TPareggio_partite pp; pp.run(argc, argv, TR("Pareggio Partite")); return 0; }