#include #include #include #include #include #include "../cg/cgsaldac.h" #include "../cg/cg2101.h" #include "pi0002.h" #include "pi0002100a.h" #include #include /////////////////////////////////////////////////////////// // Main Mask /////////////////////////////////////////////////////////// class TPF_mask : public TAutomask { TRelation* _rel; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); bool on_sheet_event(TOperable_field& o, TField_event e, long jolly); TPartita& partita(TPartite_array& partite, int nrow); TRiga_scadenze& rata(TPartite_array& partite, int nrow); bool update_mov(bool simulation); public: bool update_mov(); void update_sheet(); bool calc_residual(const TRiga_scadenze& scad, real& impres, bool& partially_unassigned, int& tipopag) const; bool fill_row(const TRiga_partite& rp, const TRiga_scadenze& rs, TToken_string& row, bool& partially_unassigned, bool force); void update_total(bool editing = false); TPF_mask(); virtual ~TPF_mask(); }; bool TPF_mask::on_sheet_event(TOperable_field& o, TField_event e, long jolly) { TMask& m = o.mask(); switch (o.dlg()) { case F_PAGATO: if (e == fe_modify) update_total(true); break; case F_IMPORTOANT: if (e == fe_modify) update_total(true); break; case F_SHEET: switch(e) { case se_query_del: case se_query_add: return false; case se_notify_modify: update_total(); break; default: break; } break; default: break; } return true; } bool TPF_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { const int id = o.dlg(); switch (id) { case DLG_SAVEREC: if (e == fe_button && check_fields()) { update_mov(); update_sheet(); } break; case F_CLIENTE: if (e == fe_modify) update_sheet(); break; case F_CODCAUS: if (e == fe_init) { // Cerca di proporre una causale in base alla configurazione della generazione effetti const TString& codcaus = ini_get_string(CONFIG_DITTA, "ef", MOV_CODCAUS); if (codcaus.full()) { o.set(codcaus); if (!o.check()) o.reset(); } } break; case F_SHEET: return on_sheet_event(o, e, jolly); default: if (jolly > 0) return on_sheet_event(o, e, jolly); break; } return true; } TPartita& TPF_mask::partita(TPartite_array& partite, int nrow) { TSheet_field& s = sfield(F_SHEET); TToken_string& row = s.row(nrow); const int posanno = s.cid2index(F_ANNO); const int posnumpart = s.cid2index(F_PARTITA); const TBill bill(0, 0, get_long(F_CLIENTE), 'C'); TPartita& game = partite.partita(bill, row.get_int(posanno), row.get(posnumpart)); return game; } TRiga_scadenze& TPF_mask::rata(TPartite_array& partite, int nrow) { TSheet_field& s = sfield(F_SHEET); const TToken_string& row = s.row(nrow); const int posnriga = s.cid2index(F_RIGA); const int posnrata = s.cid2index(F_RATA); int nriga, nrata; row.get(posnriga, nriga); row.get(posnrata, nrata); return partita(partite, nrow).rata(nriga, nrata); } bool TPF_mask::update_mov(bool simulation) { TLog_report log(main_app().title()); bool can_write = !simulation; bool done = true; TSheet_field& s = sfield(F_SHEET); const int pospagato = s.cid2index(F_PAGATO); const int posanticip = s.cid2index(F_IMPORTOANT); const int posabi = s.cid2index(F_ABI); const int poscab = s.cid2index(F_CAB); const int posanno = s.cid2index(F_ANNO); const int posnumpart = s.cid2index(F_PARTITA); const int posnriga = s.cid2index(F_RIGA); const int posnrata = s.cid2index(F_RATA); TToken_string key; const long cliente = get_long(F_CLIENTE); key = "C"; key.add(cliente); const TRectype& clifo = cache().get(LF_CLIFO, key); TBill conto_cliente; key = get(F_CODCAUS); key.add(1); const TRectype& rcaus1 = cache().get(LF_RCAUSALI, key); const char sez1 = rcaus1.get_char(RCA_SEZIONE); const char sez2 = sez1 == 'A' ? 'D' : 'A'; conto_cliente.get(rcaus1); conto_cliente.codclifo() = cliente; if (!conto_cliente.find()) { conto_cliente.get(clifo); if (!conto_cliente.find()) { log.log(2, TR("Impossibile determinare il conto cliente:\ncontrollare la causale o l'anagrafica")); can_write = done = false; } } TPartite_array partite; FOR_EACH_SHEET_ROW(s, pos, row) { const TString8 abi = row->get(posabi); const TString8 cab = row->get(poscab); if (abi.blank() || cab.blank()) continue; const real importopag(row->get(pospagato)); const real importoant(row->get(posanticip)); const real anticipo = importoant <= importopag ? ZERO : importoant-importopag; TRiga_scadenze& scad = rata(partite, pos); TString msg; msg << TR("Elaborazione Partita ") << scad.get_int(SCAD_ANNO) << '/' << scad.get_int(SCAD_NUMPART) << TR(" Riga:") << scad.get(SCAD_NRIGA) << TR(" Rata:") << scad.get(SCAD_NRATA); log.log(0, msg); scad.put(SCAD_IMPORTOANT, anticipo); scad.put(SCAD_CODABIPR, row->get(posabi)); scad.put(SCAD_CODCABPR, row->get(poscab)); if (importopag > ZERO) { TMovimentoPN mov; TRectype& head = mov.curr(); head.put(MOV_CODCAUS, get(F_CODCAUS)); head.put(MOV_DATAREG, get(F_DATAMOV)); head.put(MOV_TOTDOC, importopag); TBill conto_banca; key = abi; key << cab; const TRectype& bnp = cache().get("BNP", key); conto_banca.set(bnp.get_int("I0"), bnp.get_int("I1"), bnp.get_long("I2")); if (!conto_banca.find()) { log.log(2, TR("Impossibile determinare il conto della banca di presentazione")); can_write = done = false; } TRectype& riga1 = mov.cg(0); riga1.put(RMV_SEZIONE, sez1); riga1.put(RMV_IMPORTO, importopag); riga1.put(RMV_ROWTYPE, 'K'); conto_cliente.put(riga1, false); conto_banca.put(riga1, true); TRectype& riga2 = mov.cg(1); riga2.put(RMV_SEZIONE, sez2); riga2.put(RMV_IMPORTO, importopag); riga2.put(RMV_ROWTYPE, 'I'); conto_banca.put(riga2, false); conto_cliente.put(riga2, true); int err = NOERR; if (can_write) { err = mov.write(true); if (err == NOERR) { TString msg; msg << TR("Generazione movimento di pagamento ") << head.get_long(MOV_NUMREG); log.log(0, msg); } else { TString msg; msg << TR("Impossibile creare il movimento di pagamento: errore ") << err; log.log(2, msg); can_write = done = false; } } if (err == NOERR) { TPartita& game = scad.partita(); TRiga_partite& rigap = game.new_row(); const int nrigp = rigap.get_int(PART_NRIGA); rigap.put(PART_NREG, head.get_long(MOV_NUMREG)); rigap.put(PART_NUMRIG, mov.cg(0).get(RMV_NUMRIG)); rigap.put(PART_SEZ, mov.cg(0).get(RMV_SEZIONE)); rigap.put(PART_DATAREG, head.get(MOV_DATAREG)); rigap.put(PART_DATADOC, head.get(MOV_DATADOC)); rigap.put(PART_DATAPAG, head.get(MOV_DATAREG)); rigap.put(PART_NUMDOC, head.get(MOV_NUMDOC)); rigap.put(PART_DESCR, head.get(MOV_DESCR)); rigap.put(PART_CODCAUS, head.get(MOV_CODCAUS)); TRectype pagsca = scad.new_row(nrigp); pagsca.put(PAGSCA_IMPORTO, importopag); pagsca.put(PAGSCA_CODABIPR, abi); pagsca.put(PAGSCA_CODCABPR, cab); conto_banca.put(pagsca, true); if (scad.get_long(SCAD_CODCAB)>0) { pagsca.put(PAGSCA_CODABI, scad.get(SCAD_CODABI)); pagsca.put(PAGSCA_CODCAB, scad.get(SCAD_CODCAB)); } else { pagsca.put(PAGSCA_CODABI, clifo.get(CLI_CODABI)); pagsca.put(PAGSCA_CODCAB, clifo.get(CLI_CODCAB)); } game.modifica_pagamento(pagsca, TValuta(), true); } } } if (can_write) { TString msg; msg << TR("Aggiornamento di ") << partite.items() << TR(" partite"); log.log(0, msg); if (!partite.write(true)) { log.log(2, TR("Errore di aggiornamento del saldaconto")); can_write = done = false; } } if (!done || !simulation) log.preview(); return done; } bool TPF_mask::update_mov() { bool done = update_mov(true); // Simulation if (done) { if (yesno_box(TR("Non sono stati rilevati errori formali:\nSi desidera proseguire con l'aggiornamento del saldaconto?"))) done = update_mov(false); // Write on DB } else error_box(TR("Sono stati rilevati errori formali che impediscono l'aggiornamento del saldaconto")); return done; } // Calcola il residuo di una rata tenendo conto anche degli eventuali // effetti non ancora contabilizzati bool TPF_mask::calc_residual(const TRiga_scadenze& scad, real& impres, bool& partially_unassigned, int& tipopag) const { tipopag = scad.get_int(SCAD_TIPOPAG); const bool valuta = scad.in_valuta(); const char tipocf = scad.get_char(SCAD_TIPOCF); TImporto importo = scad.residuo(TRUE); importo.normalize(tipocf == 'C' ? 'D' : 'A'); impres = importo.valore(); partially_unassigned = FALSE; // Contolla se ci sono pagamenti non assegnati da gestire const TRiga_partite& fattura = scad.riga(); TPartita& partita = fattura.partita(); const TRecord_array& unassigned = partita.unassigned(); if (unassigned.rows() > 0) { real tot_unassigned; // Totale pagamenti non assegnati for (int u = unassigned.last_row(); u > 0; u = unassigned.pred_row(u)) { const real imp = unassigned[u].get(valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO); tot_unassigned += imp; } // Scala non assegnati dalle rate precedenti ancora aperte const int nrata = scad.get_int(SCAD_NRATA); for (int r = 1; r < nrata; r++) { if (!fattura.rata(r).chiusa()) { TImporto res = fattura.rata(r).residuo(TRUE); tot_unassigned -= res.valore(); if (tot_unassigned <= ZERO) break; } } // Scala non assegnati dalla rata corrente if (tot_unassigned > ZERO) { if (tot_unassigned >= impres) impres = ZERO; else impres -= tot_unassigned; partially_unassigned = TRUE; } } return !impres.is_zero(); } void TPF_mask::update_total(bool editing) { const TSheet_field& s = sfield(F_SHEET); const int postop = s.cid2index(F_PAGATO); const int postoa = s.cid2index(F_IMPORTOANT); real tota, totp; FOR_EACH_SHEET_ROW_BACK(s, r, row) { if (editing && r == s.selected()) { const TMask& rm = s.sheet_row_mask(r); totp += rm.get_real(F_PAGATO); tota += rm.get_real(F_IMPORTOANT); } else { totp += real(row->get(postop)); tota += real(row->get(postoa)); } } set(F_TOTALEPAG, totp); set(F_TOTALEANT, tota); enable(DLG_SAVEREC, !tota.is_zero() || !totp.is_zero()); } bool TPF_mask::fill_row(const TRiga_partite& rp, const TRiga_scadenze& rs, TToken_string& row, bool& partially_unassigned, bool force) { int tipopag = 0; real impres; row.cut(0); bool ok = calc_residual(rs, impres, partially_unassigned, tipopag) || force; if (ok) { row.add(""); // importo pagato e' solo da inserire row.add(rs.get(SCAD_IMPORTOANT)); // importo anticipato row.add(rs.get(SCAD_CODABIPR)); row.add(rs.get(SCAD_CODCABPR)); row.add(rp.get(PART_IMPTOTDOC)); // importo fattura row.add(impres.string()); // residuo row.add(rs.get(SCAD_ANNO)); row.add(rs.get(SCAD_NUMPART)); row.add(rs.get(SCAD_NRIGA)); row.add(rs.get(SCAD_NRATA)); row.add(rs.get(SCAD_DATASCAD)); switch (tipopag) { case 1:row.add(TR("Rimessa Diretta")); break; case 2:row.add(TR("Tratta")); break; case 3:row.add(TR("Ricevuta Bancaria")); break; case 4:row.add(TR("Cessione")); break; case 5:row.add(TR("Pagherò")); break; case 6:row.add(TR("Lettera di credito")); break; case 7:row.add(TR("Tratta accettata")); break; case 8:row.add(TR("Rapporti interbancari diretti")); break; case 9:row.add(TR("Bonifico")); break; default: break; } } return ok; } void TPF_mask::update_sheet() { TSheet_field& sheet = sfield(F_SHEET); sheet.destroy(); TRelation rel(LF_PARTITE); TRectype& filter = rel.curr(); filter.put(PART_TIPOCF, 'C'); filter.put(PART_SOTTOCONTO, get(F_CLIENTE)); const char* filtro = "(CHIUSA!=\"X\")&&(TIPOMOV==1)"; TCursor partite(&rel, filtro, 1, &filter, &filter); const long items = partite.items(); partite.freeze(); if (items > 0) { TRectype& partita = partite.curr(); TProgind pi(items, TR("Caricamento partite aperte")); long last_cf = 0; int last_year = 0, games = 0; TString16 last_game; TToken_string row; for (partite = 0L; partite.pos() < items; ++partite) { if (!pi.addstatus(1)) break; if (sheet.items() > 900) // Anche troppe righe break; const long cur_cf = partita.get_long(PART_SOTTOCONTO); const int cur_year = partita.get_int(PART_ANNO); const TString& cur_game = partita.get(PART_NUMPART); if (cur_cf == last_cf && cur_year == last_year && cur_game == last_game) continue; last_cf = cur_cf; last_year = cur_year; last_game = cur_game; games++; const TPartita game(partita); const int last = game.last(); for (int riga = game.prima_fattura(); riga > 0 && riga <= last; riga = game.succ(riga)) { const TRiga_partite& rp = game.riga(riga); if (rp.is_fattura()) { for (int rata = 1; rata <= rp.rate(); rata++) { const TRiga_scadenze& rs = rp.rata(rata); if (!rs.chiusa()) { bool partially_unassigned; if (fill_row(rp, rs, row, partially_unassigned, false)) { const int numrow = sheet.items(); sheet.row(numrow) = row; } } // if rata aperta } // for ogni rata } // if e' una fattura } // for ogni fattura } // for ogni partita TString msg; msg << games << ' ' << TR("partite") << " : " << sheet.items() << ' ' << TR("scadenze aperte"); xvtil_statbar_set(msg); } // if ci sono partite sheet.force_update(); update_total(); } TPF_mask::TPF_mask() : TAutomask("pi0002100a") { } TPF_mask::~TPF_mask() { } /////////////////////////////////////////////////////////// // Main Program /////////////////////////////////////////////////////////// class TPresent_fatture : public TSkeleton_application { protected: virtual const char* extra_modules() const { return "sc"; } public: virtual bool create(); virtual void main_loop(); virtual bool firm_change_enabled() const { return false; } }; void TPresent_fatture::main_loop() { open_files(LF_TABCOM, LF_TAB, LF_CLIFO, LF_PARTITE, LF_SCADENZE, LF_PAGSCA, LF_CAUSALI, LF_RCAUSALI, 0); TPF_mask m; while (m.run() != K_QUIT) { m.reset(); } } bool TPresent_fatture::create() { //se non ha la sc non può proseguire if (!has_module(SCAUT)) return error_box(TR("Modulo non autorizzato")); return TSkeleton_application::create(); } int pi0002100(int argc, char* argv[]) { int n = 0; TPresent_fatture pe; pe.run(argc, argv, TR("Gestione anticipi fatture")); return 0; }