diff --git a/cg/cg2100.cpp b/cg/cg2100.cpp index 9bb06c54e..dad3580fc 100755 --- a/cg/cg2100.cpp +++ b/cg/cg2100.cpp @@ -1,1253 +1,1253 @@ -#include -#include -#include -#include -#include -#include - -#include "pagament.h" - -#include "cg2100.h" -#include "cg2102.h" -#include "cg21sld.h" - -// Nomi dei campi -#include -#include -#include - -TPrimanota_application::TPrimanota_application() -: _rel(NULL), _lastreg(0), _mode(0), _iva(nessuna_iva), _causale(NULL), _giornale(NULL) -{ - memset(_msk, 0, sizeof(_msk)); -} - - -TMask* TPrimanota_application::load_mask(int n) -{ - if (_msk[n] != NULL) - return _msk[n]; - - if (n == 1 || n == 2) - { - const int d = 3-n; - if (_msk[d] != NULL) - { - delete _msk[d]; - _msk[d] = NULL; - } - } - - TFilename name("cg2100"); name << char(n == 3 ? 'o' : 'a'+n); - TMask* m = new TMask(name); - - switch (n) - { - case 0: - if (m) - { - m->set_handler(F_NUMREG, num_handler); - m->set_handler(F_CODCAUS, caus_query_handler); - m->set_handler(F_DATAREG, datareg_handler); - m->set_handler(F_DATACOMP, datacomp_handler); - - TConfig c(CONFIG_STUDIO, "cg"); - - // Scelta primo campo col focus - _firstfocus = c.get_bool("PoCuDr") ? F_DATAREG : F_CODCAUS; - m->first_focus(_firstfocus); - - // Registra e inserisci immediatamente un nuovo movimento - _savenew = !c.get_bool("Cg21SN"); - } - break; - case 2: - if (m) - { - m->set_handler(F_DATADOC, doc_handler); - m->set_handler(F_NUMDOC, doc_handler); - m->set_handler(F_DATA74TER, data74ter_handler); - m->set_handler(F_PROTIVA, protiva_handler); - m->set_handler(F_CLIENTE, clifo_handler); - m->set_handler(F_FORNITORE, clifo_handler); - m->set_handler(F_TOTALE, totale_handler); - m->set_handler(F_RITFIS, ritfis_handler); - m->set_handler(F_RITSOC, ritsoc_handler); - m->set_handler(F_CORRLIRE, corrlire_handler); - m->set_handler(F_CORRVALUTA, corrvaluta_handler); - m->set_handler(F_CODIVA, main_codiva_handler); - m->set_handler(F_OCCASEDIT, occas_handler); - m->set_handler(F_SOLAIVA, solaiva_handler); - m->set_handler(F_SHEETIVA, iva_handler); - m->set_handler(F_CODPAG, codpag_handler); - - TSheet_field& is = (TSheet_field&)m->field(F_SHEETIVA); - is.set_notify(iva_notify); - TMask& ism = is.sheet_mask(); - ism.set_handler(101, imponibile_handler); - ism.set_handler(102, codiva_handler); - ism.set_handler(103, detrazione_handler); - ism.set_handler(104, imposta_handler); - ism.set_handler(109, iva_sottoconto_handler); - ism.set_handler(209, sheet_clifo_handler); - ism.set_handler(309, sheet_clifo_handler); - - // add saldaconto - TSheet_field& ps = (TSheet_field&)m->field(FS_RATESHEET); - ps.set_notify(pag_notify); - - } - _iva_showed = FALSE; - case 1: - if (m) - { - m->first_focus(_firstfocus); - m->set_handler(F_DATAREG, datareg_handler); - m->set_handler(F_DATACOMP, datacomp_handler); - m->set_handler(F_DESCR, descr_handler); - m->set_handler(F_CODCAUS, caus_modify_handler); - m->set_handler(F_SHEETCG, cg_handler); - - TSheet_field& cg = (TSheet_field&)m->field(F_SHEETCG); - cg.set_notify(cg_notify); - TMask& cgm = cg.sheet_mask(); - - if (n == 1) // movimento non IVA - { - m->set_handler(S_TOTDOC, totdoc_handler); - } - - cgm.set_handler(101, dareavere_handler); - cgm.set_handler(102, dareavere_handler); - cgm.set_handler(105, cg_conto_handler); - cgm.set_handler(106, suspended_handler); - cgm.set_handler(206, sheet_clifo_handler); - cgm.set_handler(306, sheet_clifo_handler); - cgm.set_handler(112, suspended_handler); - cgm.set_handler(113, suspended_handler); - cgm.set_handler(213, sheet_clifo_handler); - cgm.set_handler(313, sheet_clifo_handler); - } - break; - case 3: - m->set_handler(O_CODICE, occas_code_handler); - break; - default: - CHECKD(0, "Che cavolo di maschera e' la ", n); - break; - } - - return _msk[n] = m; -} - - -bool TPrimanota_application::user_create() -{ - _tabcom = new TLocalisamfile(LF_TABCOM); - _tab = new TLocalisamfile(LF_TAB); - _caus = new TLocalisamfile(LF_CAUSALI); - _rcaus = new TLocalisamfile(LF_RCAUSALI); - _clifo = new TLocalisamfile(LF_CLIFO); - _pcon = new TLocalisamfile(LF_PCON); - _attiv = new TLocalisamfile(LF_ATTIV); - _saldo = new TLocalisamfile(LF_SALDI); - _comuni = new TLocalisamfile(LF_COMUNI); - _occas = new TLocalisamfile(LF_OCCAS); - _nditte = new TLocalisamfile(LF_NDITTE); - _scadenze = new TLocalisamfile(LF_SCADENZE); - _pagamenti = new TLocalisamfile(LF_PAGSCA); - - _rel = new TMovimentoPN; - _rel->add(LF_PARTITE, "NREG=NUMREG", 2); // Collega la partita aperta dalla fattura - - _causale = new TCausale(); - _giornale = new TLibro_giornale(); - - set_search_field(F_NUMREG); // Set field for default search - - _pag = NULL; - _pag_rows = NULL; - _is_saldaconto = FALSE; - - load_mask(0); - - return TRUE; -} - - -bool TPrimanota_application::save_and_new() const -{ return _savenew; } - - -bool TPrimanota_application::user_destroy() -{ - for (int m = 3; m >= 0; m--) - if (_msk[m] != NULL) delete _msk[m]; - - if (_pag) delete _pag; - - delete _giornale; - delete _causale; - delete _rel; - - delete _scadenze; - delete _nditte; - delete _occas; - delete _comuni; - delete _saldo; - delete _attiv; - delete _pcon; - delete _clifo; - delete _rcaus; - delete _caus; - delete _tab; - delete _tabcom; - - return TRUE; -} - -// Legge la causale di codice cod ed il relativo registro dell'anno year -// Certified 99% -bool TPrimanota_application::read_caus(const char* cod, int year) -{ - bool ok = TRUE; - - if (cod != NULL) - ok = causale().read(cod, year); - - bool nob = FALSE, dob = FALSE; - TipoIVA iva = nessuna_iva; - _is_saldaconto = FALSE; - - if (ok) - { - _is_saldaconto = gestione_saldaconto() && causale().saldaconto(); - dob = _is_saldaconto | causale().data_doc(); - nob = _is_saldaconto | causale().num_doc(); - iva = causale().iva(); - } - - TMask* m = _msk[iva == nessuna_iva ? 1 : 2]; - if (m == NULL) return TRUE; - - const bool ins = m->insert_mode(); - - m->efield(F_NUMDOC).check_type(nob ? CHECK_REQUIRED : CHECK_NORMAL); // Num. doc. obbligatorio - m->efield(F_DATADOC).check_type(dob ? CHECK_REQUIRED : CHECK_NORMAL); // Data doc. obbligatoria - - if (iva == nessuna_iva) - { - TMask& cgm = cgs().sheet_mask(); - cgm.set_handler(100, _is_saldaconto ? showpartite_handler : NULL); // bottoncino riga - cgm.enable(100, _is_saldaconto); - m->show(S_TIPORIGA, _is_saldaconto); - } - else - { - m->enable_page(2, _is_saldaconto); - - m->efield(F_CODPAG).check_type(_is_saldaconto ? CHECK_REQUIRED : CHECK_NORMAL);// Cod. pag. obbligatorio - - m->show(F_ANNORIF, _is_saldaconto); // Mostra/nasconde anno e riferimento partita - m->show(F_NUMRIF, _is_saldaconto); - - m->enable(F_ANNORIF, ins); // Dis/abilita anno e riferimento partita - m->enable(F_NUMRIF, ins); - m->field(F_NUMRIF).set_justify(iva == iva_acquisti ? _num_for : _num_cli); - - const bool av = causale().reg().agenzia_viaggi(); - m->show(F_DATA74TER, av); - if (!av) m->reset(F_DATA74TER); - - if (ins) - { - const long protiva = causale().reg().protocol() + 1; - m->set(F_PROTIVA, protiva); // Aggiorna protocollo IVA - } - } - - if (ins && !ci_sono_importi()) - { - cgs().reset(); - for (int i = 1; i < causale().size(); i++) - { - const TRectype* rcaus = (TRectype*)causale().objptr(i); - if (rcaus == NULL) continue; // Evita eventuali righe nulle - - const int nriga = rcaus->get_int(RCA_NRIGA); - if (nriga < 1) continue; // Considera solo righe reali (non riempimenti) - - TBill tc; causale().bill(nriga, tc); - if (tc.gruppo() < 1) continue; // Considera solo gruppi validi - - if (tc.tipo() > ' ' && tc.ok()) - { - TBill clifo(0, 0, tc.sottoconto(), tc.tipo()); - if (clifo.find() && clifo.conto() != 0) // Legge gruppo e conto - tc = clifo; - } - - int err = 0; - if (tc.descrizione() == "Sconosciuto") err = 1; else - if (tc.sospeso()) err = 2; - - if (err) - { - error_box("Il conto della riga %d della causale e' %s", - i, err == 1 ? "sconosciuto" : "sospeso"); - continue; - } - - const char sezione = rcaus->get_char(RCA_SEZIONE); - const TImporto zero('D', ZERO); - const TString80 desc(causale().desc_agg(i)); - - if (nriga == 1) m->set(F_DESCR, desc); - - if (iva == nessuna_iva) - { - char tipr = ' '; - if (_is_saldaconto) - if (nriga < 12 && nriga != 10) continue; // Si considerano solo le spese - - const int pos = set_cgs_row(-1, zero, tc, desc, tipr); - if (sezione > ' ' && tipr != ' ') - cgs().disable_cell(pos, sezione == 'A' ? 0 : 1); - } - else - { - if (nriga >= 2 && nriga <= 9) - continue; // Conti per IVA detraibile e non, ritenute sociali e fiscali - - const char tipo = nriga == 1 ? 'T' : ' '; - if (nriga == 1 && tc.tipo() > ' ' && tc.ok()) - m->set(tc.tipo() == 'C' ? F_CLIENTE : F_FORNITORE, tc.sottoconto()); - set_cgs_row(-1,zero,tc,desc,tipo); - } - } - fill_sheet(*m); - } - - return ok; -} - - -// Certified 100% -void TPrimanota_application::print() -{ - TExternal_app stampa("cg3 -0"); - stampa.run(); -} - - -bool TPrimanota_application::changing_mask(int mode) -{ - if (mode == MODE_QUERY) - { - const bool flag = _mode != MODE_QUERY; - -#if XVT_OS == XVT_OS_WIN - if (flag && _iva != nessuna_iva && !_iva_showed) - { - WINDOW w = ivas().parent(); -#if XVT_OS == 400 - xvt_vobj_set_visible(w, TRUE); - xvt_vobj_raise(w); - xvt_app_process_pending_events(); - xvt_vobj_set_visible(w, FALSE); -#else - show_window(w, TRUE); - set_front_window(w); - process_events(); - show_window(w, FALSE); -#endif - _iva_showed = TRUE; - } -#endif - return flag; - } - _iva = iva_errata; - return TRUE; -} - - -TMask* TPrimanota_application::get_mask(int mode) -{ - int annoes = 0, annoiva = 0; - TString16 caus; - - _mode = mode; - - switch (mode) - { - case MODE_INS: - annoes = _msk[0]->get_int(F_ANNOES); - annoiva = _msk[0]->get_int(F_ANNOIVA); - caus = _msk[0]->get(F_CODCAUS); - break; - case MODE_MOD: - annoes = _rel->lfile().get_int("ANNOES"); - annoiva = _rel->lfile().get_int("ANNOIVA"); - caus = _rel->lfile().get("CODCAUS"); - break; - default: - return load_mask(0); - } - - if (giornale().year() != annoes) - giornale().read(annoes); - - if (caus != causale().codice() || causale().reg().year() != annoiva) - causale().read(caus, annoiva); - _iva = causale().iva(); - - return load_mask(_iva == nessuna_iva ? 1 : 2); -} - - -void TPrimanota_application::on_firm_change() -{ - TRelation_application::on_firm_change(); - _rel->lfile().last(); - _lastreg = _rel->lfile().get_long(MOV_NUMREG); // Init last registration number -} - -void TPrimanota_application::on_config_change() -{ - TConfig cnf(CONFIG_DITTA); - _ges_val = cnf.get_bool("GesVal"); - _ges_sal = cnf.get_bool("GesSal"); - _num_cli = cnf.get_bool("NrCliDx"); - _num_for = cnf.get_bool("NrForDx"); -} - - -void TPrimanota_application::init_mask(TMask& m) -{ - disable_menu_item(M_FILE_PRINT); - - read_caus(NULL, 0); // Setta campi obbligatori - fill_sheet(m); - - const bool valintra = causale().valintra(); - const bool corrisp = causale().corrispettivi(); - - if (_iva == nessuna_iva) - { - m.enable(-5, _is_saldaconto); // Abilita campi saldaconto - } - else - { - char clig, forg; - if (_iva == iva_acquisti) - { - forg = 's'; - clig = 'h'; - } - else - { - forg = 'h'; - clig = corrisp ? 'h' : 's'; - } - m.send_key(K_SHIFT+K_CTRL+clig, -1); // GROUP 1 (clienti) - m.send_key(K_SHIFT+K_CTRL+forg, -2); // GROUP 2 (fornitori) - if (corrisp) m.hide(F_STATOPAIV); - - // Show/Hide campi valuta: F_VALUTAINTRA, F_CAMBIOINTRA, F_CORRLIRE, F_CORRVAL (GROUP 4) - m.show(-4, valintra); - - m.show(F_CODIVA, m.mode() == MODE_INS); // Codice IVA standard - } - - // Show/Hide campi valuta: F_VALUTA, F_CAMBIO, F_DATACAMBIO (GROUP 3) - const bool valuta = _ges_val && causale().valuta(); - m.show(-3, valuta); -} - -void TPrimanota_application::init_query_mode(TMask& m) -{ - enable_menu_item(M_FILE_PRINT); - - const TDate inco(TODAY); - const char* oggi = inco.string(); - m.set(F_DATAREG, oggi); - m.set(F_DATACOMP, oggi); -} - - -void TPrimanota_application::fill_sheet(TMask& m) const -{ - if (_iva != nessuna_iva || !is_saldaconto()) - { - TSheet_field& cgs = (TSheet_field&)m.field(F_SHEETCG); - for (int r = cgs.items(); r < 16; r++) cgs.row(r); - } - - if (_iva != nessuna_iva) - { - TSheet_field& ivas = (TSheet_field&)m.field(F_SHEETIVA); - for (int r = ivas.items(); r < 16; r++) ivas.row(r); - ivas.enable_column(2, _iva == iva_acquisti); // Tipo detrazione - ivas.enable_column(4, !m.insert_mode()); // Tipo costo ricavo - } -} - - -// Ritorna il prossimo numero di registrazione libero -// Certified 100% -const char* TPrimanota_application::get_next_key() -{ - TToken_string k(80); - k.add(F_NUMREG); k.add(_lastreg+1); - - if (_rel->good()) // Not reinsert - { - TMask& m = curr_mask(); - if (m.insert_mode()) - { - k.add(F_CODCAUS); k.add(m.get(F_CODCAUS)); // Ricopia causale - k.add(F_DATAREG); k.add(m.get(F_DATAREG)); // data operazione - k.add(F_DATACOMP); k.add(m.get(F_DATACOMP)); // competenza - - if (iva() == iva_vendite) - { - k.add(F_DATADOC); k.add(m.get(F_DATADOC)); // Ricopia data documento - - const long n = m.get_long(F_NUMDOC); - if (n > 0) - { k.add(F_NUMDOC); k.add(n+1); } // incrementa numero documento - } - } - } - - return strcpy(__tmp_string, k); -} - - -void TPrimanota_application::init_insert_mode(TMask& m) -{ - init_mask(m); - - m.first_focus(_firstfocus); - - if (causale().reg().agenzia_viaggi()) - m.set(F_DATA74TER, m.get(F_DATAREG)); - - if (iva() != nessuna_iva) - { - occas_mask().reset(); - - const TString16 dt(m.get(F_DATAREG)); - set_pagamento(NULL,dt); - set_scadenze(m); - } - else - _partite.destroy(); - - _saldi.reset(); // Inizializza saldi -} - - -void TPrimanota_application::init_modify_mode(TMask& m) -{ - init_mask(m); - calcola_saldo(); // Verifica eventuali sbilanci contabili - if (iva() == nessuna_iva) - _partite.destroy(); -} - -// Controlla sulla causale se il segno del totale documento (ritsoc=FALSE) -// o quello delle ritenute sociali (ritsoc=TRUE) e' invertito rispetto al normale -bool TPrimanota_application::test_swap(bool ritsoc) -{ - bool s = FALSE; - - const char sez = ritsoc ? causale().sezione_ritsoc() : causale().sezione_clifo(); - s = (iva() == iva_vendite) ^ sez == 'D'; - return s; -} - - -int TPrimanota_application::read(TMask& m) -{ - m.autoload(_rel); - - cgs().reset(); - - if (iva() != nessuna_iva) - { - ivas().reset(); - - const TString16 occode(_rel->lfile().get("OCFPI")); - occas_mask().set(O_CODICE, occode); - - const char clifo = _rel->lfile().get_char("TIPO"); - if (_iva == iva_acquisti && clifo == 'C') - error_box("Registrazione di acquisto attribuita ad un cliente"); else - if (_iva == iva_vendite && clifo == 'F') - error_box("Registrazione di vendita attribuita ad un fornitore"); - } - - // Inizializza cambio - real cambio(_rel->lfile().get("CAMBIO")); - if (cambio < 1.0) cambio = 1.0; - m.set_exchange(FALSE, cambio); - - _saldi.reset(); // Azzera saldi - _saldi.set_movprovv(_rel->lfile().get_char("PROVVIS") > ' '); - _saldi.set_movap(causale().apertura()); - _saldi.set_anno_es(m.get_int(F_ANNOES)); - _saldi.set_num_ulmov(m.get_long(F_NUMREG)); - _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); - - for (int i = 0; i < _rel->cg_items(); i++) - { - const TRectype& r = _rel->cg(i); - TToken_string& riga = cgs().row(i); // Vuota la riga - - TImporto import(r.get_char("SEZIONE"), r.get_real("IMPORTO")); - import.add_to(riga, 0); // Dare/Avere 101-102 - - TBill conto; conto.get(r); - riga.add(conto.string(0x3)); // Conto 103-107 - - _saldi.aggiorna(conto, import, FALSE); - - riga.add(""); // Codice descrizione 108 - riga.add(r.get("DESCR")); // Descrizione riga 109 - - conto.get(r, TRUE); - riga.add(conto.string(0x3)); // Contropartita 110-114 - riga.add(r.get("NUMGIO")); - const char tipo = r.get_char("ROWTYPE"); - riga.add(tipo); // Tipo di riga 115 - - disable_cgs_cells(i, tipo); - } - - if (_iva == nessuna_iva) - return _rel->status(); - - const bool solaiva = i == 0; - m.set(F_SOLAIVA, solaiva ? "X" : " "); - m.field(F_SOLAIVA).on_hit(); - - const bool to_swap = test_swap(FALSE); - if (to_swap) - { - real totdoc(m.get(F_TOTALE)); - totdoc = -totdoc; - m.set(F_TOTALE, totdoc.string()); - } - for (i = 0; i < _rel->iva_items(); i++) - { - TRectype& r = _rel->iva(i); - TToken_string& riga = ivas().row(i); - - real imponibile(r.get("IMPONIBILE")); - if (to_swap) imponibile = -imponibile; - riga.add(imponibile.string()); // Imponibile 101 - - riga.add(r.get("CODIVA")); // IVA 102 - riga.add(r.get("TIPODET")); // Detrazione 103 - - real imposta(r.get("IMPOSTA")); - if (to_swap) imposta = -imposta; - if (imponibile.sign() * imposta.sign() < 0) - { - warning_box("Registrazione con imponibile e imposta con segni discordi:\n" - "assegnato il segno dell'imponibile"); - imposta = -imposta; - } - riga.add(imposta.string()); // Imposta 104 - - TBill c; c.get(r); - c.add_to(riga, 4, 0x7); // Conto 105-110 - } - - calcola_imp(); // Calcola totale imponibile ed imposte - TString16 dt(m.get(F_DATAREG)); - set_pagamento(m.get(F_CODPAG), dt); - if (!read_scadenze(m)) - set_scadenze(m); - - return _rel->status(); -} - - -// Trasferisce i dati da maschera a movimento di prima nota -void TPrimanota_application::mask2rel(const TMask& m) -{ - m.autosave(_rel); - - const long numreg = m.get_long(F_NUMREG); - const TDate datareg(m.get(F_DATAREG)); - const int annoes = m.get_int(F_ANNOES); - - _saldi.set_movprovv(m.get(F_PROVVISORIO)[0] > ' '); - _saldi.set_movap(causale().apertura()); - _saldi.set_anno_es(annoes); - _saldi.set_num_ulmov(numreg); - _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); - - _rel->destroy_rows(numreg); // Destroy all records - cgs_pack(); // Destroy all null rows - - TArray& rows = cgs().rows_array(); - - // Controlla se e' un movimento con righe contabili - if (iva() == nessuna_iva || !m.get_bool(F_SOLAIVA)) - { - for (int i = 0; i < rows.items(); i++) - { - TToken_string& row = (TToken_string&)rows[i]; - - TImporto n; n = row; - const TBill conto(row, 2, 0x3); - _saldi.aggiorna(conto, n, TRUE); - - TRectype &r = _rel->cg(i); - r.zero(); - - r.put("NUMREG", numreg); // Numero registrazione - r.put("ANNOES", annoes); // Anno esercizio - r.put("DATAREG", datareg); // Data di registrazione - r.put("NUMRIG", i+1); // Numero riga - - r.put("SEZIONE", n.sezione()); // Sezione - r.put("IMPORTO", n.valore()); // Importo - conto.put(r); // Conto - - row.get(); // Codice descrizione (ignorato) - const char* descr = row.get(); // Descrizione aggiuntiva - if (i > 0 || m.get(F_DESCR) != descr) // Salva la prima descrizione se diversa da testata - r.put("DESCR", descr); // Descrizione riga - - r.put("TIPOCC", row.get()); // Contropartita - r.put("GRUPPOC", row.get()); - r.put("CONTOC", row.get()); - r.put("SOTTOCONTC", row.get()); - row.get(); // Descrizione contropartita - r.put("NUMGIO", row.get()); // Numero riga giornale - r.put("ROWTYPE", row.get()); // Tipo riga - } - } - - if (_iva == nessuna_iva) return; - - if (causale().corrispettivi()) - { - TRectype& rec = _rel->lfile().curr(); - rec.put("TIPO", ""); - rec.put("CODCF", ""); // Azzera il cliente nei movimenti dei corrispettivi - } - else - { - _rel->lfile().put("TIPO", clifo()); - - int err = ~NOERR; - if (m.field(F_OCCASEDIT).active()) // Se e' un occasionale - { - TRelation occas(LF_OCCAS); - const TMask& om = occas_mask(); - om.autosave(&occas); // Salva i dati anagrafici - - err = occas.write(); - if (err == _isreinsert) - err = occas.rewrite(); - - if (err == NOERR) - _rel->lfile().put("OCFPI", occas_mask().get(O_CODICE)); - else - error_box("Errore di scrittura sul file dei clienti/fornitori occasionali: %d", err); - } - if (err) _rel->lfile().zero("OCFPI"); - } - - const bool intra = causale().intra(); - const bool to_swap = test_swap(FALSE); - if (to_swap) - { - real totale = _rel->lfile().get("TOTDOC"); - totale = -totale; - _rel->lfile().put("TOTDOC", totale); - } - - ivas_pack(); - TArray& irows = ivas().rows_array(); - for (int i = 0; i < irows.items(); i++) - { - TToken_string& row = (TToken_string&)irows[i]; - - TRectype &r = _rel->iva(i); - r.zero(); - r.put("ANNOES", annoes); // Anno d'esercizio della testata (che ca$$ata!) - r.put("NUMREG", numreg); - r.put("INTRA", intra); // Causale intra (che ca$$ata!) - r.put("NUMRIG", i+1); - - real imponibile(row.get(0)); - if (to_swap) imponibile = -imponibile; - r.put("IMPONIBILE", imponibile); - - r.put("CODIVA", row.get()); - r.put("TIPODET", row.get()); - - real imposta(row.get()); - if (to_swap) imposta = -imposta; - r.put("IMPOSTA", imposta); - - r.put("TIPOCR", row.get()); - - const TBill c(row, -1, 0x1); - const int rimp = bill2pos(c, 'I')+1; - r.put("RIGAIMP", rimp); - c.put(r); - } -} - - -void TPrimanota_application::check_saldi() -{ - TString_array& rows = cgs().rows_array(); - const int anno = _rel->lfile().get_int("ANNOES"); - - for (int i = 0; i < rows.items(); i++) - { - TToken_string& row = (TToken_string&)rows[i]; - TBill conto(row, 2, 0x3); - conto.find(); - const char sez = conto.sezione(); - if (sez > ' ') - { - const TConto* c = _saldi.find(conto, anno); - if (c && !c->saldo_finale().is_zero() && c->saldo_finale().sezione() != sez) - warning_box("Il conto della riga %i ha un saldo finale in %s, " - "contrariamente a quanto indicato sul piano dei conti", - i+1, sez == 'A' ? "dare" : "avere"); - } - } -} - - -int TPrimanota_application::write(const TMask& m) -{ - static int lasterr = NOERR; - - const long numreg = m.get_long(F_NUMREG); - if (numreg > _lastreg) _lastreg = numreg; // Aggiorna ultima registrazione libera - - if (lasterr == NOERR) - mask2rel(m); // Altrimenti raddoppia i saldi! - - const int err = _rel->write(TRUE); - if (err == NOERR) - { - _saldi.registra(); - check_saldi(); - - if (iva() != nessuna_iva) - { - causale().reg().reread(); // Aggiorna protocollo IVA - if (_is_saldaconto) - { - if (m.page_enabled(2)) - write_scadenze(m); - } - else - { - if (!m.get_bool(F_SOLAIVA)) - { - const TString16 causimm(causale().causale_inc_imm()); - if (causimm.not_empty()) - genera_incasso(causimm); // Genera incasso immediato - } - } - } - else - { - if (_is_saldaconto) - { - const long nreg = numreg - (lasterr == _isreinsert ? 1 : 0); - _partite.update_reg_num(nreg, _rel->lfile().curr()); - _partite.write(); - } - } - - link_m770(); - } - - lasterr = err; - return err; -} - - -int TPrimanota_application::rewrite(const TMask& m) -{ - mask2rel(m); - const int err = _rel->rewrite(TRUE); - if (err == NOERR) - { - _saldi.registra(); - check_saldi(); - - if (_is_saldaconto) - { - if (iva() != nessuna_iva) - write_scadenze(m); - else - _partite.rewrite(); - } - - link_m770(); - } - - return err; -} - - -bool TPrimanota_application::remove() -{ - const bool ok = TRelation_application::remove(); - if (ok) - { - _saldi.registra(); - check_saldi(); - - if (_is_saldaconto && iva() == nessuna_iva) - { - notify_cgline_deletion(0); // Notify deletion of all cg lines - _partite.rewrite(); - } - } - return ok; -} - - -HIDDEN bool incasso_handler(TMask_field& f, KEY k) -{ - if (k == K_ENTER) - { - TMask& m = f.mask(); - TImporto tot(m.get(I_SEZIONE1)[0], (real)m.get(F_TOTALE)); - - for (int i = 2; i < 5; i++) - { - const int sid = i == 2 ? I_SEZIONE2 : (i == 3 ? I_SEZIONE3 : I_SEZIONE4); - const real val(m.get(sid+1)); - const TImporto imp(m.get(sid)[0], val); - tot += imp; - } - if (!tot.is_zero()) - return f.error_box("Il movimento e' sbilaciato di %s", tot.valore().string(".")); - } - return TRUE; -} - - -void TPrimanota_application::genera_incasso(const char* causimm) -{ - TMask m("cg2100i"); - if (iva() == iva_acquisti) m.set_caption("Movimento di pagamento immediato"); - - m.set_handler(F_DATAREG, datareg_handler); - m.set_handler(F_DATACOMP, datacomp_handler); - m.set_handler(F_TOTALE, incasso_handler); - - TCausale caus(causimm); // Causale da usare - - if (caus.data_doc()) m.efield(F_DATADOC).check_type(CHECK_REQUIRED); - if (caus.num_doc()) m.efield(F_NUMDOC).check_type(CHECK_REQUIRED); - - m.set(F_DATAREG, curr_mask().get(F_DATAREG)); - m.set(F_DATACOMP, curr_mask().get(F_DATACOMP)); - m.set(F_DATADOC, curr_mask().get(F_DATADOC)); - m.set(F_NUMDOC, curr_mask().get(F_NUMDOC)); - m.set(F_NUMREG, _lastreg+1); // Incrementa numero di registrazione - m.set(F_DESCR, caus.desc_agg(1)); // Descrizione - m.set(F_CODCAUS, causimm); // Cambia causale - m.set(F_DESCRCAUS, caus.descrizione()); - - m.set(I_SEZIONE1, caus.sezione_clifo() == 'D' ? "D" : "A"); - m.set(F_TOTALE, curr_mask().get(F_TOTALE)); - - m.set(F_CLIFO, _rel->cg(0).get("TIPOC")); - m.set(F_GRUPPOCLIFO, _rel->cg(0).get("GRUPPO")); - m.set(F_CONTOCLIFO, _rel->cg(0).get("CONTO")); - const TString& clifo = _rel->cg(0).get("SOTTOCONTO"); - m.set(F_CLIENTE, clifo); m.set(F_FORNITORE, clifo); m.set(I_SOTTOCONTO, clifo); - - TBill conto; caus.bill(2, conto); // Conto della seconda riga della causale - m.set(I_SEZIONE2, caus.sezione_clifo() == 'D' ? "A" : "D"); - m.set(I_IMPORTO2, curr_mask().get(F_TOTALE)); - m.set(I_GRUPPO2, conto.gruppo()); - m.set(I_CONTO2, conto.conto()); - m.set(I_SOTTOCONTO2, conto.sottoconto()); - - if (m.run() == K_SAVE) - { - TMovimentoPN inc; // Nuovo movimento di incasso immediato - - inc.lfile().zero(); - m.autosave(&inc); - inc.lfile().put("TIPODOC", caus.tipo_doc()); // Tipo documento - inc.lfile().put("REG", caus.reg().name()); // Registro - - const int annoes = m.get_int(F_ANNOES); - const TString16 datareg = m.get(F_DATAREG); - long num = m.get_long(F_NUMREG); - - inc.destroy_rows(num); - - TRectype& r = inc.cg(0); - r.zero(); - r.put("NUMREG", num); - r.put("NUMRIG", 1); - r.put("DATAREG", datareg); - r.put("ANNOES", annoes); - r.put("SEZIONE", m.get(I_SEZIONE1)); - r.put("IMPORTO", m.get(F_TOTALE)); - r.put("TIPOC", m.get(F_CLIFO)); - r.put("GRUPPO", m.get(F_GRUPPOCLIFO)); - r.put("CONTO", m.get(F_CONTOCLIFO)); - - short clifo_id; - switch (m.get(F_CLIFO)[0]) - { - case 'C': - clifo_id = F_CLIENTE; break; - case 'F': - clifo_id = F_FORNITORE; break; - default : - clifo_id = I_SOTTOCONTO; break; - } - r.put("SOTTOCONTO", m.get(clifo_id)); - r.put("DESCR", m.get(F_DESCR)); - r.put("TIPOCC", " "); - r.put("GRUPPOC", m.get(I_GRUPPO2)); - r.put("CONTOC", m.get(I_CONTO2)); - r.put("SOTTOCONTC", m.get(I_SOTTOCONTO2)); - - r.put("ROWTYPE", " "); - - for (int i = 2; i < 5; i++) - { - const int sid = i == 2 ? I_SEZIONE2 : (i == 3 ? I_SEZIONE3 : I_SEZIONE4); - const TString& imp = m.get(sid+1); - if (imp.empty()) break; - - TRectype& r = inc.cg(i-1); - r.zero(); - r.put("IMPORTO", imp); - r.put("NUMREG", num); - r.put("NUMRIG", i); - r.put("DATAREG", datareg); - r.put("ANNOES", annoes); - r.put("SEZIONE", m.get(sid)); - r.put("TIPOC", ' '); - r.put("GRUPPO", m.get(sid+2)); - r.put("CONTO", m.get(sid+3)); - r.put("SOTTOCONTO", m.get(sid+4)); - if (i == 2) - r.put("DESCR", caus.desc_agg(2)); - - r.put("TIPOCC", m.get(F_CLIFO)); - r.put("GRUPPOC", m.get(F_GRUPPOCLIFO)); - r.put("CONTOC", m.get(F_CONTOCLIFO)); - r.put("SOTTOCONTC", m.get(clifo_id)); - - r.put("ROWTYPE", " "); - } - - while (inc.write() == _isreinsert) // In caso di riscrittura - { - num++; // Incrementa numero registrazione - inc.lfile().put("NUMREG", num); - } - - if (inc.good()) - { - if (num > _lastreg) _lastreg = num; - - _saldi.reset(); // Inizializza saldi - _saldi.set_movprovv(FALSE); - _saldi.set_movap(FALSE); - _saldi.set_anno_es(m.get_int(F_ANNOES)); - _saldi.set_num_ulmov(_lastreg); - _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); - for (int r = 0; r < inc.cg_items(); r++) - { - const TRectype& rec = inc.cg(r); - TBill c; c.get(rec); - const TImporto im(rec.get_char("SEZIONE"), rec.get_real("IMPORTO")); - _saldi.aggiorna(c, im, TRUE); - } - _saldi.registra(); - check_saldi(); - } - } -} - - -long TPrimanota_application::calcola_m770(int tipo_coll, real& spese, real& compenso, - real& iva, real& ritfis) -{ - const int m770 = causale().link_m770(); - long forn = 0; - - if (tipo_coll == 1) - { - TString_array& riva = ivas().rows_array(); - TCodiceIVA codiva; - for (int i = 0; i < riva.items(); i++) - { - TToken_string& row = riva.row(i); - codiva.read(row.get(1)); - const TString& tipoiva = codiva.tipo(); - - const real imponibile(row.get(0)); - if ((tipoiva == "ES" || tipoiva == "NI" ||tipoiva == "NS") && riva.items() > 1) - { - if (m770 != 5) - spese += imponibile; - } - else - compenso += imponibile; - - const real imposta(row.get(3)); - iva += imposta; - } - - i = type2pos('F'); - if (i >= 0) - { - TImporto imp; imp = cgs().row(i); - ritfis = imp.valore(); - } - } - - if (tipo_coll == 3 || tipo_coll == 6) - { - TBill zio; causale().bill(1, zio); - TImporto imp; - - TString_array& rcg = cgs().rows_array(); - for (int i = 0; i < rcg.items(); i++) - { - TToken_string& row = rcg.row(i); - imp = row; - if (tipo_coll == 3) - { - const char cf = row.get_char(2); - if (cf == 'F') - { - if (forn == 0) - forn = row.get_long(5); - else - { - forn = 0; - compenso = ZERO; - break; - } - compenso = imp.valore(); - } - } else - if (tipo_coll == 6) - compenso += imp.valore(); - } - } - - return forn; -} - - -bool TPrimanota_application::link_m770() -{ - const int m770 = causale().link_m770(); - if (!has_module(4) || iva() == iva_vendite || m770 == 0) - return FALSE; - - int tipo_coll = 0; - char tipper = ' '; - long codper = 0; - real spese, compenso, imposte, ritenute; - - if (iva() == iva_acquisti) - { - if (m770 == 1 || m770 == 5) - { - TLocalisamfile fornitori(LF_CLIFO); - fornitori.put("TIPOCF", "F"); - fornitori.put("CODCF", curr_mask().get(F_FORNITORE)); - fornitori.read(); - tipper = fornitori.get_char(CLI_TIPOAPER); - codper = fornitori.get_long(CLI_CODANAGPER); - if (codper > 0) - calcola_m770(tipo_coll = 1, spese, compenso, imposte, ritenute); - } - } - else - switch (m770) - { - case 1: - { - const long f = calcola_m770(tipo_coll = 3, spese, compenso, imposte, ritenute); - if (f != 0) - { - TLocalisamfile fornitori(LF_CLIFO); - fornitori.put("TIPOCF", "F"); - fornitori.put("CODCF", f); - fornitori.read(); - tipper = fornitori.get_char(CLI_TIPOAPER); - codper = fornitori.get_long(CLI_CODANAGPER); - } - else tipo_coll = 7; - } - break; - case 2: - tipo_coll = 4; - break; - case 6: - calcola_m770(tipo_coll = 6, spese, compenso, imposte, ritenute); - break; - default: - break; - } - - if (tipo_coll) - { - TToken_string s(80); - s.add(tipo_coll); - s.add(curr_mask().insert_mode() ? "I" : "M"); - s.add(tipper); - s.add(codper); - s.add(curr_mask().get(F_NUMREG)); - s.add(curr_mask().get(F_NUMDOC)); - s.add(curr_mask().get(F_DATADOC)); - if (iva() == iva_acquisti) - s.add(curr_mask().get(F_TOTALE)); - else - s.add(""); - s.add(spese.string()); - s.add(compenso.string()); - s.add(imposte.string()); - s.add(ritenute.string()); - - const char* name = (tipo_coll == 4) ? "770 -1" : "770 -0"; - TMessage m(name, "LINK770", s); - m.send(); - - TExternal_app a(name); - a.run(); - } - - return tipo_coll > 0; -} - - -int cg2100 (int argc, char** argv) -{ - TPrimanota_application a; - a.run(argc, argv, "Prima nota"); - return 0; -} +#include +#include +#include +#include +#include +#include + +#include "pagament.h" + +#include "cg2100.h" +#include "cg2102.h" +#include "cg21sld.h" + +// Nomi dei campi +#include +#include +#include + +TPrimanota_application::TPrimanota_application() +: _rel(NULL), _lastreg(0), _mode(0), _iva(nessuna_iva), _causale(NULL), _giornale(NULL) +{ + memset(_msk, 0, sizeof(_msk)); +} + + +TMask* TPrimanota_application::load_mask(int n) +{ + if (_msk[n] != NULL) + return _msk[n]; + + if (n == 1 || n == 2) + { + const int d = 3-n; + if (_msk[d] != NULL) + { + delete _msk[d]; + _msk[d] = NULL; + } + } + + TFilename name("cg2100"); name << char(n == 3 ? 'o' : 'a'+n); + TMask* m = new TMask(name); + + switch (n) + { + case 0: + if (m) + { + m->set_handler(F_NUMREG, num_handler); + m->set_handler(F_CODCAUS, caus_query_handler); + m->set_handler(F_DATAREG, datareg_handler); + m->set_handler(F_DATACOMP, datacomp_handler); + + TConfig c(CONFIG_STUDIO, "cg"); + + // Scelta primo campo col focus + _firstfocus = c.get_bool("PoCuDr") ? F_DATAREG : F_CODCAUS; + m->first_focus(_firstfocus); + + // Registra e inserisci immediatamente un nuovo movimento + _savenew = !c.get_bool("Cg21SN"); + } + break; + case 2: + if (m) + { + m->set_handler(F_DATADOC, doc_handler); + m->set_handler(F_NUMDOC, doc_handler); + m->set_handler(F_DATA74TER, data74ter_handler); + m->set_handler(F_PROTIVA, protiva_handler); + m->set_handler(F_CLIENTE, clifo_handler); + m->set_handler(F_FORNITORE, clifo_handler); + m->set_handler(F_TOTALE, totale_handler); + m->set_handler(F_RITFIS, ritfis_handler); + m->set_handler(F_RITSOC, ritsoc_handler); + m->set_handler(F_CORRLIRE, corrlire_handler); + m->set_handler(F_CORRVALUTA, corrvaluta_handler); + m->set_handler(F_CODIVA, main_codiva_handler); + m->set_handler(F_OCCASEDIT, occas_handler); + m->set_handler(F_SOLAIVA, solaiva_handler); + m->set_handler(F_SHEETIVA, iva_handler); + m->set_handler(F_CODPAG, codpag_handler); + + TSheet_field& is = (TSheet_field&)m->field(F_SHEETIVA); + is.set_notify(iva_notify); + TMask& ism = is.sheet_mask(); + ism.set_handler(101, imponibile_handler); + ism.set_handler(102, codiva_handler); + ism.set_handler(103, detrazione_handler); + ism.set_handler(104, imposta_handler); + ism.set_handler(109, iva_sottoconto_handler); + ism.set_handler(209, sheet_clifo_handler); + ism.set_handler(309, sheet_clifo_handler); + + // add saldaconto + TSheet_field& ps = (TSheet_field&)m->field(FS_RATESHEET); + ps.set_notify(pag_notify); + + } + _iva_showed = FALSE; + case 1: + if (m) + { + m->first_focus(_firstfocus); + m->set_handler(F_DATAREG, datareg_handler); + m->set_handler(F_DATACOMP, datacomp_handler); + m->set_handler(F_DESCR, descr_handler); + m->set_handler(F_CODCAUS, caus_modify_handler); + m->set_handler(F_SHEETCG, cg_handler); + + TSheet_field& cg = (TSheet_field&)m->field(F_SHEETCG); + cg.set_notify(cg_notify); + TMask& cgm = cg.sheet_mask(); + + if (n == 1) // movimento non IVA + { + m->set_handler(S_TOTDOC, totdoc_handler); + } + + cgm.set_handler(101, dareavere_handler); + cgm.set_handler(102, dareavere_handler); + cgm.set_handler(105, cg_conto_handler); + cgm.set_handler(106, suspended_handler); + cgm.set_handler(206, sheet_clifo_handler); + cgm.set_handler(306, sheet_clifo_handler); + cgm.set_handler(112, suspended_handler); + cgm.set_handler(113, suspended_handler); + cgm.set_handler(213, sheet_clifo_handler); + cgm.set_handler(313, sheet_clifo_handler); + } + break; + case 3: + m->set_handler(O_CODICE, occas_code_handler); + break; + default: + CHECKD(0, "Che cavolo di maschera e' la ", n); + break; + } + + return _msk[n] = m; +} + + +bool TPrimanota_application::user_create() +{ + _tabcom = new TLocalisamfile(LF_TABCOM); + _tab = new TLocalisamfile(LF_TAB); + _caus = new TLocalisamfile(LF_CAUSALI); + _rcaus = new TLocalisamfile(LF_RCAUSALI); + _clifo = new TLocalisamfile(LF_CLIFO); + _pcon = new TLocalisamfile(LF_PCON); + _attiv = new TLocalisamfile(LF_ATTIV); + _saldo = new TLocalisamfile(LF_SALDI); + _comuni = new TLocalisamfile(LF_COMUNI); + _occas = new TLocalisamfile(LF_OCCAS); + _nditte = new TLocalisamfile(LF_NDITTE); + _scadenze = new TLocalisamfile(LF_SCADENZE); + _pagamenti = new TLocalisamfile(LF_PAGSCA); + + _rel = new TMovimentoPN; + _rel->add(LF_PARTITE, "NREG=NUMREG", 2); // Collega la partita aperta dalla fattura + + _causale = new TCausale(); + _giornale = new TLibro_giornale(); + + set_search_field(F_NUMREG); // Set field for default search + + _pag = NULL; + _pag_rows = NULL; + _is_saldaconto = FALSE; + + load_mask(0); + + return TRUE; +} + + +bool TPrimanota_application::save_and_new() const +{ return _savenew; } + + +bool TPrimanota_application::user_destroy() +{ + for (int m = 3; m >= 0; m--) + if (_msk[m] != NULL) delete _msk[m]; + + if (_pag) delete _pag; + + delete _giornale; + delete _causale; + delete _rel; + + delete _scadenze; + delete _nditte; + delete _occas; + delete _comuni; + delete _saldo; + delete _attiv; + delete _pcon; + delete _clifo; + delete _rcaus; + delete _caus; + delete _tab; + delete _tabcom; + + return TRUE; +} + +// Legge la causale di codice cod ed il relativo registro dell'anno year +// Certified 99% +bool TPrimanota_application::read_caus(const char* cod, int year) +{ + bool ok = TRUE; + + if (cod != NULL) + ok = causale().read(cod, year); + + bool nob = FALSE, dob = FALSE; + TipoIVA iva = nessuna_iva; + _is_saldaconto = FALSE; + + if (ok) + { + _is_saldaconto = gestione_saldaconto() && causale().saldaconto(); + dob = _is_saldaconto | causale().data_doc(); + nob = _is_saldaconto | causale().num_doc(); + iva = causale().iva(); + } + + TMask* m = _msk[iva == nessuna_iva ? 1 : 2]; + if (m == NULL) return TRUE; + + const bool ins = m->insert_mode(); + + m->efield(F_NUMDOC).check_type(nob ? CHECK_REQUIRED : CHECK_NORMAL); // Num. doc. obbligatorio + m->efield(F_DATADOC).check_type(dob ? CHECK_REQUIRED : CHECK_NORMAL); // Data doc. obbligatoria + + if (iva == nessuna_iva) + { + TMask& cgm = cgs().sheet_mask(); + cgm.set_handler(100, _is_saldaconto ? showpartite_handler : NULL); // bottoncino riga + cgm.enable(100, _is_saldaconto); + m->show(S_TIPORIGA, _is_saldaconto); + } + else + { + m->enable_page(2, _is_saldaconto); + + m->efield(F_CODPAG).check_type(_is_saldaconto ? CHECK_REQUIRED : CHECK_NORMAL);// Cod. pag. obbligatorio + + m->show(F_ANNORIF, _is_saldaconto); // Mostra/nasconde anno e riferimento partita + m->show(F_NUMRIF, _is_saldaconto); + + m->enable(F_ANNORIF, ins); // Dis/abilita anno e riferimento partita + m->enable(F_NUMRIF, ins); + m->field(F_NUMRIF).set_justify(iva == iva_acquisti ? _num_for : _num_cli); + + const bool av = causale().reg().agenzia_viaggi(); + m->show(F_DATA74TER, av); + if (!av) m->reset(F_DATA74TER); + + if (ins) + { + const long protiva = causale().reg().protocol() + 1; + m->set(F_PROTIVA, protiva); // Aggiorna protocollo IVA + } + } + + if (ins && !ci_sono_importi()) + { + cgs().reset(); + for (int i = 1; i < causale().size(); i++) + { + const TRectype* rcaus = (TRectype*)causale().objptr(i); + if (rcaus == NULL) continue; // Evita eventuali righe nulle + + const int nriga = rcaus->get_int(RCA_NRIGA); + if (nriga < 1) continue; // Considera solo righe reali (non riempimenti) + + TBill tc; causale().bill(nriga, tc); + if (tc.gruppo() < 1) continue; // Considera solo gruppi validi + + if (tc.tipo() > ' ' && tc.ok()) + { + TBill clifo(0, 0, tc.sottoconto(), tc.tipo()); + if (clifo.find() && clifo.conto() != 0) // Legge gruppo e conto + tc = clifo; + } + + int err = 0; + if (tc.descrizione() == "Sconosciuto") err = 1; else + if (tc.sospeso()) err = 2; + + if (err) + { + error_box("Il conto della riga %d della causale e' %s", + i, err == 1 ? "sconosciuto" : "sospeso"); + continue; + } + + const char sezione = rcaus->get_char(RCA_SEZIONE); + const TImporto zero('D', ZERO); + const TString80 desc(causale().desc_agg(i)); + + if (nriga == 1) m->set(F_DESCR, desc); + + if (iva == nessuna_iva) + { + char tipr = ' '; + if (_is_saldaconto) + if (nriga < 12 && nriga != 10) continue; // Si considerano solo le spese + + const int pos = set_cgs_row(-1, zero, tc, desc, tipr); + if (sezione > ' ' && tipr != ' ') + cgs().disable_cell(pos, sezione == 'A' ? 0 : 1); + } + else + { + if (nriga >= 2 && nriga <= 9) + continue; // Conti per IVA detraibile e non, ritenute sociali e fiscali + + const char tipo = nriga == 1 ? 'T' : ' '; + if (nriga == 1 && tc.tipo() > ' ' && tc.ok()) + m->set(tc.tipo() == 'C' ? F_CLIENTE : F_FORNITORE, tc.sottoconto()); + set_cgs_row(-1,zero,tc,desc,tipo); + } + } + fill_sheet(*m); + } + + return ok; +} + + +// Certified 100% +void TPrimanota_application::print() +{ + TExternal_app stampa("cg3 -0"); + stampa.run(); +} + + +bool TPrimanota_application::changing_mask(int mode) +{ + if (mode == MODE_QUERY) + { + const bool flag = _mode != MODE_QUERY; + +#if XVT_OS == XVT_OS_WIN + if (flag && _iva != nessuna_iva && !_iva_showed) + { + WINDOW w = ivas().parent(); +#if XVT_OS == 400 + xvt_vobj_set_visible(w, TRUE); + xvt_vobj_raise(w); + xvt_app_process_pending_events(); + xvt_vobj_set_visible(w, FALSE); +#else + show_window(w, TRUE); + set_front_window(w); + process_events(); + show_window(w, FALSE); +#endif + _iva_showed = TRUE; + } +#endif + return flag; + } + _iva = iva_errata; + return TRUE; +} + + +TMask* TPrimanota_application::get_mask(int mode) +{ + int annoes = 0, annoiva = 0; + TString16 caus; + + _mode = mode; + + switch (mode) + { + case MODE_INS: + annoes = _msk[0]->get_int(F_ANNOES); + annoiva = _msk[0]->get_int(F_ANNOIVA); + caus = _msk[0]->get(F_CODCAUS); + break; + case MODE_MOD: + annoes = _rel->lfile().get_int("ANNOES"); + annoiva = _rel->lfile().get_int("ANNOIVA"); + caus = _rel->lfile().get("CODCAUS"); + break; + default: + return load_mask(0); + } + + if (giornale().year() != annoes) + giornale().read(annoes); + + if (caus != causale().codice() || causale().reg().year() != annoiva) + causale().read(caus, annoiva); + _iva = causale().iva(); + + return load_mask(_iva == nessuna_iva ? 1 : 2); +} + + +void TPrimanota_application::on_firm_change() +{ + TRelation_application::on_firm_change(); + _rel->lfile().last(); + _lastreg = _rel->lfile().get_long(MOV_NUMREG); // Init last registration number +} + +void TPrimanota_application::on_config_change() +{ + TConfig cnf(CONFIG_DITTA); + _ges_val = cnf.get_bool("GesVal"); + _ges_sal = cnf.get_bool("GesSal"); + _num_cli = cnf.get_bool("NrCliDx"); + _num_for = cnf.get_bool("NrForDx"); +} + + +void TPrimanota_application::init_mask(TMask& m) +{ + disable_menu_item(M_FILE_PRINT); + + read_caus(NULL, 0); // Setta campi obbligatori + fill_sheet(m); + + const bool valintra = causale().valintra(); + const bool corrisp = causale().corrispettivi(); + + if (_iva == nessuna_iva) + { + m.enable(-5, _is_saldaconto); // Abilita campi saldaconto + } + else + { + char clig, forg; + if (_iva == iva_acquisti) + { + forg = 's'; + clig = 'h'; + } + else + { + forg = 'h'; + clig = corrisp ? 'h' : 's'; + } + m.send_key(K_SHIFT+K_CTRL+clig, -1); // GROUP 1 (clienti) + m.send_key(K_SHIFT+K_CTRL+forg, -2); // GROUP 2 (fornitori) + if (corrisp) m.hide(F_STATOPAIV); + + // Show/Hide campi valuta: F_VALUTAINTRA, F_CAMBIOINTRA, F_CORRLIRE, F_CORRVAL (GROUP 4) + m.show(-4, valintra); + + m.show(F_CODIVA, m.mode() == MODE_INS); // Codice IVA standard + } + + // Show/Hide campi valuta: F_VALUTA, F_CAMBIO, F_DATACAMBIO (GROUP 3) + const bool valuta = _ges_val && causale().valuta(); + m.show(-3, valuta); +} + +void TPrimanota_application::init_query_mode(TMask& m) +{ + enable_menu_item(M_FILE_PRINT); + + const TDate inco(TODAY); + const char* oggi = inco.string(); + m.set(F_DATAREG, oggi); + m.set(F_DATACOMP, oggi); +} + + +void TPrimanota_application::fill_sheet(TMask& m) const +{ + if (_iva != nessuna_iva || !is_saldaconto()) + { + TSheet_field& cgs = (TSheet_field&)m.field(F_SHEETCG); + for (int r = cgs.items(); r < 16; r++) cgs.row(r); + } + + if (_iva != nessuna_iva) + { + TSheet_field& ivas = (TSheet_field&)m.field(F_SHEETIVA); + for (int r = ivas.items(); r < 16; r++) ivas.row(r); + ivas.enable_column(2, _iva == iva_acquisti); // Tipo detrazione + ivas.enable_column(4, !m.insert_mode()); // Tipo costo ricavo + } +} + + +// Ritorna il prossimo numero di registrazione libero +// Certified 100% +const char* TPrimanota_application::get_next_key() +{ + TToken_string k(80); + k.add(F_NUMREG); k.add(_lastreg+1); + + if (_rel->good()) // Not reinsert + { + TMask& m = curr_mask(); + if (m.insert_mode()) + { + k.add(F_CODCAUS); k.add(m.get(F_CODCAUS)); // Ricopia causale + k.add(F_DATAREG); k.add(m.get(F_DATAREG)); // data operazione + k.add(F_DATACOMP); k.add(m.get(F_DATACOMP)); // competenza + + if (iva() == iva_vendite) + { + k.add(F_DATADOC); k.add(m.get(F_DATADOC)); // Ricopia data documento + + const long n = m.get_long(F_NUMDOC); + if (n > 0) + { k.add(F_NUMDOC); k.add(n+1); } // incrementa numero documento + } + } + } + + return strcpy(__tmp_string, k); +} + + +void TPrimanota_application::init_insert_mode(TMask& m) +{ + init_mask(m); + + m.first_focus(_firstfocus); + + if (causale().reg().agenzia_viaggi()) + m.set(F_DATA74TER, m.get(F_DATAREG)); + + if (iva() != nessuna_iva) + { + occas_mask().reset(); + + const TString16 dt(m.get(F_DATAREG)); + set_pagamento(NULL,dt); + set_scadenze(m); + } + else + _partite.destroy(); + + _saldi.reset(); // Inizializza saldi +} + + +void TPrimanota_application::init_modify_mode(TMask& m) +{ + init_mask(m); + calcola_saldo(); // Verifica eventuali sbilanci contabili + if (iva() == nessuna_iva) + _partite.destroy(); +} + +// Controlla sulla causale se il segno del totale documento (ritsoc=FALSE) +// o quello delle ritenute sociali (ritsoc=TRUE) e' invertito rispetto al normale +bool TPrimanota_application::test_swap(bool ritsoc) +{ + bool s = FALSE; + + const char sez = ritsoc ? causale().sezione_ritsoc() : causale().sezione_clifo(); + s = (iva() == iva_vendite) ^ sez == 'D'; + return s; +} + + +int TPrimanota_application::read(TMask& m) +{ + m.autoload(_rel); + + cgs().reset(); + + if (iva() != nessuna_iva) + { + ivas().reset(); + + const TString16 occode(_rel->lfile().get("OCFPI")); + occas_mask().set(O_CODICE, occode); + + const char clifo = _rel->lfile().get_char("TIPO"); + if (_iva == iva_acquisti && clifo == 'C') + error_box("Registrazione di acquisto attribuita ad un cliente"); else + if (_iva == iva_vendite && clifo == 'F') + error_box("Registrazione di vendita attribuita ad un fornitore"); + } + + // Inizializza cambio + real cambio(_rel->lfile().get("CAMBIO")); + if (cambio < 1.0) cambio = 1.0; + m.set_exchange(FALSE, cambio); + + _saldi.reset(); // Azzera saldi + _saldi.set_movprovv(_rel->lfile().get_char("PROVVIS") > ' '); + _saldi.set_movap(causale().apertura()); + _saldi.set_anno_es(m.get_int(F_ANNOES)); + _saldi.set_num_ulmov(m.get_long(F_NUMREG)); + _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); + + for (int i = 0; i < _rel->cg_items(); i++) + { + const TRectype& r = _rel->cg(i); + TToken_string& riga = cgs().row(i); // Vuota la riga + + TImporto import(r.get_char("SEZIONE"), r.get_real("IMPORTO")); + import.add_to(riga, 0); // Dare/Avere 101-102 + + TBill conto; conto.get(r); + riga.add(conto.string(0x3)); // Conto 103-107 + + _saldi.aggiorna(conto, import, FALSE); + + riga.add(""); // Codice descrizione 108 + riga.add(r.get("DESCR")); // Descrizione riga 109 + + conto.get(r, TRUE); + riga.add(conto.string(0x3)); // Contropartita 110-114 + riga.add(r.get("NUMGIO")); + const char tipo = r.get_char("ROWTYPE"); + riga.add(tipo); // Tipo di riga 115 + + disable_cgs_cells(i, tipo); + } + + if (_iva == nessuna_iva) + return _rel->status(); + + const bool solaiva = i == 0; + m.set(F_SOLAIVA, solaiva ? "X" : " "); + m.field(F_SOLAIVA).on_hit(); + + const bool to_swap = test_swap(FALSE); + if (to_swap) + { + real totdoc(m.get(F_TOTALE)); + totdoc = -totdoc; + m.set(F_TOTALE, totdoc.string()); + } + for (i = 0; i < _rel->iva_items(); i++) + { + TRectype& r = _rel->iva(i); + TToken_string& riga = ivas().row(i); + + real imponibile(r.get("IMPONIBILE")); + if (to_swap) imponibile = -imponibile; + riga.add(imponibile.string()); // Imponibile 101 + + riga.add(r.get("CODIVA")); // IVA 102 + riga.add(r.get("TIPODET")); // Detrazione 103 + + real imposta(r.get("IMPOSTA")); + if (to_swap) imposta = -imposta; + if (imponibile.sign() * imposta.sign() < 0) + { + warning_box("Registrazione con imponibile e imposta con segni discordi:\n" + "assegnato il segno dell'imponibile"); + imposta = -imposta; + } + riga.add(imposta.string()); // Imposta 104 + + TBill c; c.get(r); + c.add_to(riga, 4, 0x7); // Conto 105-110 + } + + calcola_imp(); // Calcola totale imponibile ed imposte + TString16 dt(m.get(F_DATAREG)); + set_pagamento(m.get(F_CODPAG), dt); + if (!read_scadenze(m)) + set_scadenze(m); + + return _rel->status(); +} + + +// Trasferisce i dati da maschera a movimento di prima nota +void TPrimanota_application::mask2rel(const TMask& m) +{ + m.autosave(_rel); + + const long numreg = m.get_long(F_NUMREG); + const TDate datareg(m.get(F_DATAREG)); + const int annoes = m.get_int(F_ANNOES); + + _saldi.set_movprovv(m.get(F_PROVVISORIO)[0] > ' '); + _saldi.set_movap(causale().apertura()); + _saldi.set_anno_es(annoes); + _saldi.set_num_ulmov(numreg); + _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); + + _rel->destroy_rows(numreg); // Destroy all records + cgs_pack(); // Destroy all null rows + + TArray& rows = cgs().rows_array(); + + // Controlla se e' un movimento con righe contabili + if (iva() == nessuna_iva || !m.get_bool(F_SOLAIVA)) + { + for (int i = 0; i < rows.items(); i++) + { + TToken_string& row = (TToken_string&)rows[i]; + + TImporto n; n = row; + const TBill conto(row, 2, 0x3); + _saldi.aggiorna(conto, n, TRUE); + + TRectype &r = _rel->cg(i); + r.zero(); + + r.put("NUMREG", numreg); // Numero registrazione + r.put("ANNOES", annoes); // Anno esercizio + r.put("DATAREG", datareg); // Data di registrazione + r.put("NUMRIG", i+1); // Numero riga + + r.put("SEZIONE", n.sezione()); // Sezione + r.put("IMPORTO", n.valore()); // Importo + conto.put(r); // Conto + + row.get(); // Codice descrizione (ignorato) + const char* descr = row.get(); // Descrizione aggiuntiva + if (i > 0 || m.get(F_DESCR) != descr) // Salva la prima descrizione se diversa da testata + r.put("DESCR", descr); // Descrizione riga + + r.put("TIPOCC", row.get()); // Contropartita + r.put("GRUPPOC", row.get()); + r.put("CONTOC", row.get()); + r.put("SOTTOCONTC", row.get()); + row.get(); // Descrizione contropartita + r.put("NUMGIO", row.get()); // Numero riga giornale + r.put("ROWTYPE", row.get()); // Tipo riga + } + } + + if (_iva == nessuna_iva) return; + + if (causale().corrispettivi()) + { + TRectype& rec = _rel->lfile().curr(); + rec.put("TIPO", ""); + rec.put("CODCF", ""); // Azzera il cliente nei movimenti dei corrispettivi + } + else + { + _rel->lfile().put("TIPO", clifo()); + + int err = ~NOERR; + if (m.field(F_OCCASEDIT).active()) // Se e' un occasionale + { + TRelation occas(LF_OCCAS); + const TMask& om = occas_mask(); + om.autosave(&occas); // Salva i dati anagrafici + + err = occas.write(); + if (err == _isreinsert) + err = occas.rewrite(); + + if (err == NOERR) + _rel->lfile().put("OCFPI", occas_mask().get(O_CODICE)); + else + error_box("Errore di scrittura sul file dei clienti/fornitori occasionali: %d", err); + } + if (err) _rel->lfile().zero("OCFPI"); + } + + const bool intra = causale().intra(); + const bool to_swap = test_swap(FALSE); + if (to_swap) + { + real totale = _rel->lfile().get("TOTDOC"); + totale = -totale; + _rel->lfile().put("TOTDOC", totale); + } + + ivas_pack(); + TArray& irows = ivas().rows_array(); + for (int i = 0; i < irows.items(); i++) + { + TToken_string& row = (TToken_string&)irows[i]; + + TRectype &r = _rel->iva(i); + r.zero(); + r.put("ANNOES", annoes); // Anno d'esercizio della testata (che ca$$ata!) + r.put("NUMREG", numreg); + r.put("INTRA", intra); // Causale intra (che ca$$ata!) + r.put("NUMRIG", i+1); + + real imponibile(row.get(0)); + if (to_swap) imponibile = -imponibile; + r.put("IMPONIBILE", imponibile); + + r.put("CODIVA", row.get()); + r.put("TIPODET", row.get()); + + real imposta(row.get()); + if (to_swap) imposta = -imposta; + r.put("IMPOSTA", imposta); + + r.put("TIPOCR", row.get()); + + const TBill c(row, -1, 0x1); + const int rimp = bill2pos(c, 'I')+1; + r.put("RIGAIMP", rimp); + c.put(r); + } +} + + +void TPrimanota_application::check_saldi() +{ + TString_array& rows = cgs().rows_array(); + const int anno = _rel->lfile().get_int("ANNOES"); + + for (int i = 0; i < rows.items(); i++) + { + TToken_string& row = (TToken_string&)rows[i]; + TBill conto(row, 2, 0x3); + conto.find(); + const char sez = conto.sezione(); + if (sez > ' ') + { + const TConto* c = _saldi.find(conto, anno); + if (c && !c->saldo_finale().is_zero() && c->saldo_finale().sezione() != sez) + warning_box("Il conto della riga %i ha un saldo finale in %s, " + "contrariamente a quanto indicato sul piano dei conti", + i+1, sez == 'A' ? "dare" : "avere"); + } + } +} + + +int TPrimanota_application::write(const TMask& m) +{ + static int lasterr = NOERR; + + const long numreg = m.get_long(F_NUMREG); + if (numreg > _lastreg) _lastreg = numreg; // Aggiorna ultima registrazione libera + + if (lasterr == NOERR) + mask2rel(m); // Altrimenti raddoppia i saldi! + + const int err = _rel->write(TRUE); + if (err == NOERR) + { + _saldi.registra(); + check_saldi(); + + if (iva() != nessuna_iva) + { + causale().reg().reread(); // Aggiorna protocollo IVA + if (_is_saldaconto) + { + if (m.page_enabled(2)) + write_scadenze(m); + } + else + { + if (!m.get_bool(F_SOLAIVA)) + { + const TString16 causimm(causale().causale_inc_imm()); + if (causimm.not_empty()) + genera_incasso(causimm); // Genera incasso immediato + } + } + } + else + { + if (_is_saldaconto) + { + const long nreg = numreg - (lasterr == _isreinsert ? 1 : 0); + _partite.update_reg_num(nreg, _rel->lfile().curr()); + _partite.write(); + } + } + + link_m770(); + } + + lasterr = err; + return err; +} + + +int TPrimanota_application::rewrite(const TMask& m) +{ + mask2rel(m); + const int err = _rel->rewrite(TRUE); + if (err == NOERR) + { + _saldi.registra(); + check_saldi(); + + if (_is_saldaconto) + { + if (iva() != nessuna_iva) + write_scadenze(m); + else + _partite.rewrite(); + } + + link_m770(); + } + + return err; +} + + +bool TPrimanota_application::remove() +{ + const bool ok = TRelation_application::remove(); + if (ok) + { + _saldi.registra(); + check_saldi(); + + if (_is_saldaconto && iva() == nessuna_iva) + { + notify_cgline_deletion(0); // Notify deletion of all cg lines + _partite.rewrite(); + } + } + return ok; +} + + +HIDDEN bool incasso_handler(TMask_field& f, KEY k) +{ + if (k == K_ENTER) + { + TMask& m = f.mask(); + TImporto tot(m.get(I_SEZIONE1)[0], (real)m.get(F_TOTALE)); + + for (int i = 2; i < 5; i++) + { + const int sid = i == 2 ? I_SEZIONE2 : (i == 3 ? I_SEZIONE3 : I_SEZIONE4); + const real val(m.get(sid+1)); + const TImporto imp(m.get(sid)[0], val); + tot += imp; + } + if (!tot.is_zero()) + return f.error_box("Il movimento e' sbilaciato di %s", tot.valore().string(".")); + } + return TRUE; +} + + +void TPrimanota_application::genera_incasso(const char* causimm) +{ + TMask m("cg2100i"); + if (iva() == iva_acquisti) m.set_caption("Movimento di pagamento immediato"); + + m.set_handler(F_DATAREG, datareg_handler); + m.set_handler(F_DATACOMP, datacomp_handler); + m.set_handler(F_TOTALE, incasso_handler); + + TCausale caus(causimm); // Causale da usare + + if (caus.data_doc()) m.efield(F_DATADOC).check_type(CHECK_REQUIRED); + if (caus.num_doc()) m.efield(F_NUMDOC).check_type(CHECK_REQUIRED); + + m.set(F_DATAREG, curr_mask().get(F_DATAREG)); + m.set(F_DATACOMP, curr_mask().get(F_DATACOMP)); + m.set(F_DATADOC, curr_mask().get(F_DATADOC)); + m.set(F_NUMDOC, curr_mask().get(F_NUMDOC)); + m.set(F_NUMREG, _lastreg+1); // Incrementa numero di registrazione + m.set(F_DESCR, caus.desc_agg(1)); // Descrizione + m.set(F_CODCAUS, causimm); // Cambia causale + m.set(F_DESCRCAUS, caus.descrizione()); + + m.set(I_SEZIONE1, caus.sezione_clifo() == 'D' ? "D" : "A"); + m.set(F_TOTALE, curr_mask().get(F_TOTALE)); + + m.set(F_CLIFO, _rel->cg(0).get("TIPOC")); + m.set(F_GRUPPOCLIFO, _rel->cg(0).get("GRUPPO")); + m.set(F_CONTOCLIFO, _rel->cg(0).get("CONTO")); + const TString& clifo = _rel->cg(0).get("SOTTOCONTO"); + m.set(F_CLIENTE, clifo); m.set(F_FORNITORE, clifo); m.set(I_SOTTOCONTO, clifo); + + TBill conto; caus.bill(2, conto); // Conto della seconda riga della causale + m.set(I_SEZIONE2, caus.sezione_clifo() == 'D' ? "A" : "D"); + m.set(I_IMPORTO2, curr_mask().get(F_TOTALE)); + m.set(I_GRUPPO2, conto.gruppo()); + m.set(I_CONTO2, conto.conto()); + m.set(I_SOTTOCONTO2, conto.sottoconto()); + + if (m.run() == K_SAVE) + { + TMovimentoPN inc; // Nuovo movimento di incasso immediato + + inc.lfile().zero(); + m.autosave(&inc); + inc.lfile().put("TIPODOC", caus.tipo_doc()); // Tipo documento + inc.lfile().put("REG", caus.reg().name()); // Registro + + const int annoes = m.get_int(F_ANNOES); + const TString16 datareg = m.get(F_DATAREG); + long num = m.get_long(F_NUMREG); + + inc.destroy_rows(num); + + TRectype& r = inc.cg(0); + r.zero(); + r.put("NUMREG", num); + r.put("NUMRIG", 1); + r.put("DATAREG", datareg); + r.put("ANNOES", annoes); + r.put("SEZIONE", m.get(I_SEZIONE1)); + r.put("IMPORTO", m.get(F_TOTALE)); + r.put("TIPOC", m.get(F_CLIFO)); + r.put("GRUPPO", m.get(F_GRUPPOCLIFO)); + r.put("CONTO", m.get(F_CONTOCLIFO)); + + short clifo_id; + switch (m.get(F_CLIFO)[0]) + { + case 'C': + clifo_id = F_CLIENTE; break; + case 'F': + clifo_id = F_FORNITORE; break; + default : + clifo_id = I_SOTTOCONTO; break; + } + r.put("SOTTOCONTO", m.get(clifo_id)); + r.put("DESCR", m.get(F_DESCR)); + r.put("TIPOCC", " "); + r.put("GRUPPOC", m.get(I_GRUPPO2)); + r.put("CONTOC", m.get(I_CONTO2)); + r.put("SOTTOCONTC", m.get(I_SOTTOCONTO2)); + + r.put("ROWTYPE", " "); + + for (int i = 2; i < 5; i++) + { + const int sid = i == 2 ? I_SEZIONE2 : (i == 3 ? I_SEZIONE3 : I_SEZIONE4); + const TString& imp = m.get(sid+1); + if (imp.empty()) break; + + TRectype& r = inc.cg(i-1); + r.zero(); + r.put("IMPORTO", imp); + r.put("NUMREG", num); + r.put("NUMRIG", i); + r.put("DATAREG", datareg); + r.put("ANNOES", annoes); + r.put("SEZIONE", m.get(sid)); + r.put("TIPOC", ' '); + r.put("GRUPPO", m.get(sid+2)); + r.put("CONTO", m.get(sid+3)); + r.put("SOTTOCONTO", m.get(sid+4)); + if (i == 2) + r.put("DESCR", caus.desc_agg(2)); + + r.put("TIPOCC", m.get(F_CLIFO)); + r.put("GRUPPOC", m.get(F_GRUPPOCLIFO)); + r.put("CONTOC", m.get(F_CONTOCLIFO)); + r.put("SOTTOCONTC", m.get(clifo_id)); + + r.put("ROWTYPE", " "); + } + + while (inc.write() == _isreinsert) // In caso di riscrittura + { + num++; // Incrementa numero registrazione + inc.lfile().put("NUMREG", num); + } + + if (inc.good()) + { + if (num > _lastreg) _lastreg = num; + + _saldi.reset(); // Inizializza saldi + _saldi.set_movprovv(FALSE); + _saldi.set_movap(FALSE); + _saldi.set_anno_es(m.get_int(F_ANNOES)); + _saldi.set_num_ulmov(_lastreg); + _saldi.set_data_ulmov((TDate)m.get(F_DATAREG)); + for (int r = 0; r < inc.cg_items(); r++) + { + const TRectype& rec = inc.cg(r); + TBill c; c.get(rec); + const TImporto im(rec.get_char("SEZIONE"), rec.get_real("IMPORTO")); + _saldi.aggiorna(c, im, TRUE); + } + _saldi.registra(); + check_saldi(); + } + } +} + + +long TPrimanota_application::calcola_m770(int tipo_coll, real& spese, real& compenso, + real& iva, real& ritfis) +{ + const int m770 = causale().link_m770(); + long forn = 0; + + if (tipo_coll == 1) + { + TString_array& riva = ivas().rows_array(); + TCodiceIVA codiva; + for (int i = 0; i < riva.items(); i++) + { + TToken_string& row = riva.row(i); + codiva.read(row.get(1)); + const TString& tipoiva = codiva.tipo(); + + const real imponibile(row.get(0)); + if ((tipoiva == "ES" || tipoiva == "NI" ||tipoiva == "NS") && riva.items() > 1) + { + if (m770 != 5) + spese += imponibile; + } + else + compenso += imponibile; + + const real imposta(row.get(3)); + iva += imposta; + } + + i = type2pos('F'); + if (i >= 0) + { + TImporto imp; imp = cgs().row(i); + ritfis = imp.valore(); + } + } + + if (tipo_coll == 3 || tipo_coll == 6) + { + TBill zio; causale().bill(1, zio); + TImporto imp; + + TString_array& rcg = cgs().rows_array(); + for (int i = 0; i < rcg.items(); i++) + { + TToken_string& row = rcg.row(i); + imp = row; + if (tipo_coll == 3) + { + const char cf = row.get_char(2); + if (cf == 'F') + { + if (forn == 0) + forn = row.get_long(5); + else + { + forn = 0; + compenso = ZERO; + break; + } + compenso = imp.valore(); + } + } else + if (tipo_coll == 6) + compenso += imp.valore(); + } + } + + return forn; +} + + +bool TPrimanota_application::link_m770() +{ + const int m770 = causale().link_m770(); + if (!has_module(4) || iva() == iva_vendite || m770 == 0) + return FALSE; + + int tipo_coll = 0; + char tipper = ' '; + long codper = 0; + real spese, compenso, imposte, ritenute; + + if (iva() == iva_acquisti) + { + if (m770 == 1 || m770 == 5) + { + TLocalisamfile fornitori(LF_CLIFO); + fornitori.put("TIPOCF", "F"); + fornitori.put("CODCF", curr_mask().get(F_FORNITORE)); + fornitori.read(); + tipper = fornitori.get_char(CLI_TIPOAPER); + codper = fornitori.get_long(CLI_CODANAGPER); + if (codper > 0) + calcola_m770(tipo_coll = 1, spese, compenso, imposte, ritenute); + } + } + else + switch (m770) + { + case 1: + { + const long f = calcola_m770(tipo_coll = 3, spese, compenso, imposte, ritenute); + if (f != 0) + { + TLocalisamfile fornitori(LF_CLIFO); + fornitori.put("TIPOCF", "F"); + fornitori.put("CODCF", f); + fornitori.read(); + tipper = fornitori.get_char(CLI_TIPOAPER); + codper = fornitori.get_long(CLI_CODANAGPER); + } + else tipo_coll = 7; + } + break; + case 2: + tipo_coll = 4; + break; + case 6: + calcola_m770(tipo_coll = 6, spese, compenso, imposte, ritenute); + break; + default: + break; + } + + if (tipo_coll) + { + TToken_string s(80); + s.add(tipo_coll); + s.add(curr_mask().insert_mode() ? "I" : "M"); + s.add(tipper); + s.add(codper); + s.add(curr_mask().get(F_NUMREG)); + s.add(curr_mask().get(F_NUMDOC)); + s.add(curr_mask().get(F_DATADOC)); + if (iva() == iva_acquisti) + s.add(curr_mask().get(F_TOTALE)); + else + s.add(""); + s.add(spese.string()); + s.add(compenso.string()); + s.add(imposte.string()); + s.add(ritenute.string()); + + const char* name = (tipo_coll == 4) ? "770 -1" : "770 -0"; + TMessage m(name, "LINK770", s); + m.send(); + + TExternal_app a(name); + a.run(); + } + + return tipo_coll > 0; +} + + +int cg2100 (int argc, char** argv) +{ + TPrimanota_application a; + a.run(argc, argv, "Prima nota"); + return 0; +} diff --git a/cg/cg2100.h b/cg/cg2100.h index dd21055a2..853e67d94 100755 --- a/cg/cg2100.h +++ b/cg/cg2100.h @@ -1,129 +1,129 @@ -#ifndef __CG2100_H -#define __CG2100_H - -#define F_CODDITTA 101 -#define F_RAGSOC 102 -#define F_DATAREG 103 -#define F_NUMREG 104 -#define F_CODCAUS 105 -#define F_DESCRCAUS 106 -#define F_DOCUMENTO 107 -#define F_TIPODOC 108 -#define F_CODREG 109 -#define F_PROTIVA 110 -#define F_RIEPILOGO 111 -#define F_DESCR 112 -#define F_DATADOC 113 -#define F_NUMDOC 114 -#define F_ANNOES 115 -#define F_DATACOMP 116 -#define F_ANNOIVA 117 -#define F_CLIFO 150 -#define F_CLIENTE 151 -#define F_RAGSOCCLIENTE 152 -#define F_STATOPAIV 153 -#define F_PIVACLIENTE 154 -#define F_COFICLIENTE 155 -#define F_FORNITORE 161 -#define F_RAGSOCFORNITORE 162 -#define F_PIVAFORNITORE 164 -#define F_COFIFORNITORE 165 -#define F_GRUPPOCLIFO 170 -#define F_CONTOCLIFO 171 -#define F_TOTALE 118 -#define F_CODIVA 119 -#define F_RITFIS 120 -#define F_RITSOC 121 -#define F_CODPAG 122 -#define F_ANNORIF 123 -#define F_NUMRIF 124 -#define F_PROVVISORIO 129 -#define F_TIPOMOV 130 -#define F_OCCASEDIT 131 -#define F_SOLAIVA 132 -#define F_CORRLIRE 133 -#define F_CORRVALUTA 134 -#define F_DATA74TER 135 -#define F_DESCAGG 136 -#define F_DARE 137 -#define F_AVERE 138 -#define F_IMPONIBILI 139 -#define F_IMPOSTE 140 -#define F_VALUTAINTRA 141 -#define F_CAMBIOINTRA 142 -#define F_STAMPATO 143 -#define F_REGST 144 -#define F_SHEETCG 190 -#define F_SHEETIVA 191 - -// Campi ripetuti sulla seconda pagina -#define H_DATAREG 201 -#define H_NUMREG 202 -#define H_CODCAUS 203 -#define H_DESCRCAUS 204 -#define H_ANNOES 205 - -// Maschera clienti/fornitori occasionali -#define O_CODICE 100 -#define O_RAGSOC 101 -#define O_STATO 102 -#define O_COMUNE 103 -#define O_DENCOM 104 -#define O_CAP 105 -#define O_INDIRIZZO 106 -#define O_NUMERO 107 -#define O_SESSO 110 -#define O_DATANAS 111 -#define O_STATONAS 112 -#define O_COMUNENAS 113 -#define O_DENCOMNAS 114 - -// Maschera incasso/pagamento immediato -#define I_SEZIONE1 201 -#define I_IMPORTO1 202 -#define I_SOTTOCONTO 203 - -#define I_SEZIONE2 210 -#define I_IMPORTO2 211 -#define I_GRUPPO2 212 -#define I_CONTO2 213 -#define I_SOTTOCONTO2 214 - -#define I_SEZIONE3 220 -#define I_IMPORTO3 221 -#define I_GRUPPO3 222 -#define I_CONTO3 223 -#define I_SOTTOCONTO3 224 - -#define I_SEZIONE4 230 -#define I_IMPORTO4 231 -#define I_GRUPPO4 232 -#define I_CONTO4 233 -#define I_SOTTOCONTO4 234 - -// Saldaconto -#define S_TOTDOC 301 -#define S_TOTDOCVAL 302 -#define S_VALUTA 303 -#define S_DATACAMBIO 304 -#define S_CAMBIO 305 -#define S_TIPORIGA 306 - -// copie 2a pag. -#define K_CODDITTA 401 -#define K_RAGSOC 402 -#define K_DATAREG 403 -#define K_NUMREG 404 -#define K_CODCAUS 405 -#define K_DESCRCAUS 406 -#define K_DOCUMENTO 407 -#define K_TIPODOC 408 -#define K_PROTIVA 409 -#define K_PROVVISORIO 410 -#define K_DESCR 411 -#define K_DATADOC 412 -#define K_NUMDOC 413 -#define K_ANNOES 414 -#define K_DATACOMP 415 - -#endif +#ifndef __CG2100_H +#define __CG2100_H + +#define F_CODDITTA 101 +#define F_RAGSOC 102 +#define F_DATAREG 103 +#define F_NUMREG 104 +#define F_CODCAUS 105 +#define F_DESCRCAUS 106 +#define F_DOCUMENTO 107 +#define F_TIPODOC 108 +#define F_CODREG 109 +#define F_PROTIVA 110 +#define F_RIEPILOGO 111 +#define F_DESCR 112 +#define F_DATADOC 113 +#define F_NUMDOC 114 +#define F_ANNOES 115 +#define F_DATACOMP 116 +#define F_ANNOIVA 117 +#define F_CLIFO 150 +#define F_CLIENTE 151 +#define F_RAGSOCCLIENTE 152 +#define F_STATOPAIV 153 +#define F_PIVACLIENTE 154 +#define F_COFICLIENTE 155 +#define F_FORNITORE 161 +#define F_RAGSOCFORNITORE 162 +#define F_PIVAFORNITORE 164 +#define F_COFIFORNITORE 165 +#define F_GRUPPOCLIFO 170 +#define F_CONTOCLIFO 171 +#define F_TOTALE 118 +#define F_CODIVA 119 +#define F_RITFIS 120 +#define F_RITSOC 121 +#define F_CODPAG 122 +#define F_ANNORIF 123 +#define F_NUMRIF 124 +#define F_PROVVISORIO 129 +#define F_TIPOMOV 130 +#define F_OCCASEDIT 131 +#define F_SOLAIVA 132 +#define F_CORRLIRE 133 +#define F_CORRVALUTA 134 +#define F_DATA74TER 135 +#define F_DESCAGG 136 +#define F_DARE 137 +#define F_AVERE 138 +#define F_IMPONIBILI 139 +#define F_IMPOSTE 140 +#define F_VALUTAINTRA 141 +#define F_CAMBIOINTRA 142 +#define F_STAMPATO 143 +#define F_REGST 144 +#define F_SHEETCG 190 +#define F_SHEETIVA 191 + +// Campi ripetuti sulla seconda pagina +#define H_DATAREG 201 +#define H_NUMREG 202 +#define H_CODCAUS 203 +#define H_DESCRCAUS 204 +#define H_ANNOES 205 + +// Maschera clienti/fornitori occasionali +#define O_CODICE 100 +#define O_RAGSOC 101 +#define O_STATO 102 +#define O_COMUNE 103 +#define O_DENCOM 104 +#define O_CAP 105 +#define O_INDIRIZZO 106 +#define O_NUMERO 107 +#define O_SESSO 110 +#define O_DATANAS 111 +#define O_STATONAS 112 +#define O_COMUNENAS 113 +#define O_DENCOMNAS 114 + +// Maschera incasso/pagamento immediato +#define I_SEZIONE1 201 +#define I_IMPORTO1 202 +#define I_SOTTOCONTO 203 + +#define I_SEZIONE2 210 +#define I_IMPORTO2 211 +#define I_GRUPPO2 212 +#define I_CONTO2 213 +#define I_SOTTOCONTO2 214 + +#define I_SEZIONE3 220 +#define I_IMPORTO3 221 +#define I_GRUPPO3 222 +#define I_CONTO3 223 +#define I_SOTTOCONTO3 224 + +#define I_SEZIONE4 230 +#define I_IMPORTO4 231 +#define I_GRUPPO4 232 +#define I_CONTO4 233 +#define I_SOTTOCONTO4 234 + +// Saldaconto +#define S_TOTDOC 301 +#define S_TOTDOCVAL 302 +#define S_VALUTA 303 +#define S_DATACAMBIO 304 +#define S_CAMBIO 305 +#define S_TIPORIGA 306 + +// copie 2a pag. +#define K_CODDITTA 401 +#define K_RAGSOC 402 +#define K_DATAREG 403 +#define K_NUMREG 404 +#define K_CODCAUS 405 +#define K_DESCRCAUS 406 +#define K_DOCUMENTO 407 +#define K_TIPODOC 408 +#define K_PROTIVA 409 +#define K_PROVVISORIO 410 +#define K_DESCR 411 +#define K_DATADOC 412 +#define K_NUMDOC 413 +#define K_ANNOES 414 +#define K_DATACOMP 415 + +#endif diff --git a/cg/cg2100b.uml b/cg/cg2100b.uml index 2d191b55e..b7fd8304e 100755 --- a/cg/cg2100b.uml +++ b/cg/cg2100b.uml @@ -1,375 +1,375 @@ -#include "cg2100.h" - -TOOLBAR "" 0 20 0 2 - -#include - -ENDPAGE - -PAGE "OPERAZIONE DI PRIMA NOTA" -1 -1 77 20 - -GROUPBOX DLG_NULL 78 3 -BEGIN - PROMPT 1 0 "@BMovimento di sola contabilita'" -END - -NUMBER F_CODDITTA 5 -BEGIN - PROMPT 3 1 "Ditta " - FLAGS "DFR" - USE LF_NDITTE KEY 1 - INPUT CODDITTA F_CODDITTA - OUTPUT K_CODDITTA CODDITTA - OUTPUT F_RAGSOC RAGSOC - CHECKTYPE NORMAL -END - -STRING F_RAGSOC 50 -BEGIN - PROMPT 17 1 "Ragione " - FLAGS "D" - MESSAGE COPY,K_RAGSOC -END - -NUMBER F_NUMREG 7 -BEGIN - PROMPT 56 3 "Operazione n. " - FIELD NUMREG - FLAGS "DGR" - MESSAGE COPY,K_NUMREG -END - -DATE F_DATAREG -BEGIN - PROMPT 1 3 "Data operazione " - HELP "Data in cui viene effettuata l'operazione" - FIELD DATAREG - CHECKTYPE REQUIRED - MESSAGE COPY,K_DATAREG -END - - -DATE F_DATACOMP -BEGIN - PROMPT 1 4 "Data di competenza " - HELP "Data di competenza dell'operazione" - FIELD DATACOMP - CHECKTYPE REQUIRED - MESSAGE COPY,K_DATACOMP -END - -NUMBER F_ANNOES 4 -BEGIN - PROMPT 56 4 "Esercizio " - FIELD ANNOES - MESSAGE COPY,K_ANNOES - FLAGS "DGZ" -END - -STRING F_CODCAUS 3 -BEGIN - PROMPT 1 5 "Causale " - HELP "Codice della causale generante l'operazione" - FLAGS "UZ" - FIELD CODCAUS - USE LF_CAUSALI - INPUT CODCAUS F_CODCAUS - DISPLAY "Codice" CODCAUS - DISPLAY "Descrizione@50" DESCR - DISPLAY "Tipo" TIPODOC - DISPLAY "Registro" REG - OUTPUT F_CODCAUS CODCAUS - OUTPUT F_DESCRCAUS DESCR - OUTPUT F_TIPODOC TIPODOC - OUTPUT F_TIPOMOV TIPOMOV - CHECKTYPE NORMAL - ADD RUN cg0 -4 - MESSAGE COPY,K_CODCAUS -END - -STRING F_DESCRCAUS 50 -BEGIN - PROMPT 25 5 "" - HELP "Descrizione della causale generante l'operazione" - USE LF_CAUSALI KEY 2 - INPUT DESCR F_DESCRCAUS - DISPLAY "Descrizione@50" DESCR - DISPLAY "Codice" CODCAUS - COPY OUTPUT F_CODCAUS - MESSAGE COPY,K_DESCRCAUS -END - -LIST F_PROVVISORIO 1 25 -BEGIN - PROMPT 1 6 "Movimento provvisorio " - HELP "Indicare se si tratta di movimento provvisorio" - FIELD PROVVIS - ITEM " |No (movimento normale)" - ITEM "P|Si (cancellabile)" - MESSAGE COPY,K_PROVVISORIO -END - -STRING F_TIPODOC 2 -BEGIN - PROMPT 60 6 "Tipo documento " - FIELD TIPODOC - FLAGS "DG" - MESSAGE COPY,K_TIPODOC -END - -NUMBER F_TIPOMOV 1 -BEGIN - PROMPT 32 6 "Tipo movimento " - FIELD LF_MOV->TIPOMOV - FLAGS "H" -END - -DATE F_DATADOC -BEGIN - PROMPT 1 7 "Data del documento " - HELP "Data del documento generante il movimento" - FIELD DATADOC - WARNING "Specificare una data del documento non superiore a quella dell'operazione" - VALIDATE DATE_CMP_FUNC <= F_DATAREG - MESSAGE COPY,K_DATADOC -END - -STRING F_NUMDOC 7 -BEGIN - PROMPT 56 7 "Documento n. " - HELP "Numero del documento generante il movimento" - FIELD NUMDOC - WARNING "La causale impone di specificare il numero documento" - MESSAGE COPY,K_NUMDOC -END - -NUMBER F_ANNOIVA 4 -BEGIN - FLAGS "H" -END - -STRING F_DESCAGG 5 -BEGIN - PROMPT 1 8 "Descrizione " - HELP "Codice descrizione del movimento di contabilita'" - FLAGS "UZ" - USE %DPN - INPUT CODTAB F_DESCAGG - DISPLAY "Codice" CODTAB - DISPLAY "Descrizione@50" S0 - OUTPUT F_DESCAGG CODTAB - OUTPUT F_DESCR S0 - CHECKTYPE NORMAL -END - -STRING F_DESCR 50 -BEGIN - PROMPT 25 8 "" - HELP "Descrizione del movimento di contabilita'" - FIELD DESCR - USE %DPN KEY 2 - INPUT S0 F_DESCR - DISPLAY "Descrizione@50" S0 - DISPLAY "Codice" CODTAB - COPY OUTPUT F_DESCAGG -END - -GROUPBOX DLG_NULL 78 8 -BEGIN - PROMPT 1 10 "Voci per saldaconto" -END - -NUMBER S_TOTDOC 15 0 -BEGIN - PROMPT 2 11 "Totale documento " - FLAGS "R" - PICTURE "." - GROUP 5 -END - -NUMBER S_TOTDOCVAL 15 2 -BEGIN - PROMPT 44 11 "Totale in valuta " - HELP "" - FLAGS "R" - PICTURE ".2" - GROUP 3 -END - - -STRING S_VALUTA 3 -BEGIN - PROMPT 2 13 "Valuta " - HELP "Codice della valuta per movimento" - FIELD LF_MOV->CODVAL - FLAGS "U" - GROUP 3 - USE %VAL - INPUT CODTAB S_VALUTA - DISPLAY "Codice" CODTAB - DISPLAY "Nome@50" S0 - DISPLAY "Ultimo cambio@15" R10 - DISPLAY "Ultimo aggiornamento" D0 - OUTPUT S_VALUTA CODTAB - OUTPUT S_CAMBIO R10 - CHECKTYPE NORMAL -END - -DATE S_DATACAMBIO -BEGIN - PROMPT 22 13 "Data cambio " - FLAGS "R" - USE CAM - INPUT CODTAB[1,3] S_VALUTA - INPUT CODTAB[4,11] S_DATACAMBIO - DISPLAY "Valuta" CODTAB[1,3] - DISPLAY "Data@10" D0 - DISPLAY "Cambio@18" R10 - OUTPUT S_VALUTA CODTAB[1,3] - OUTPUT S_DATACAMBIO D0 - OUTPUT S_CAMBIO R10 - GROUP 3 -END - -NUMBER S_CAMBIO 15 5 -BEGIN - PROMPT 54 13 "Cambio " - HELP "Cambio della valuta" - FIELD LF_MOV->CAMBIO - FLAGS "RU" - GROUP 3 - PICTURE ".5" -END - -ENDPAGE - -PAGE "OPERAZIONE DI PRIMA NOTA" -1 -1 77 20 - -GROUPBOX DLG_NULL 78 3 -BEGIN - PROMPT 1 0 "@BMovimento di sola contabilita'" -END - -NUMBER K_CODDITTA 5 -BEGIN - PROMPT 3 1 "Ditta " - FLAGS "D" -END - -STRING K_RAGSOC 50 -BEGIN - PROMPT 17 1 "Ragione " - FLAGS "D" -END - -NUMBER K_NUMREG 7 -BEGIN - PROMPT 56 3 "Operazione n. " - FLAGS "RD" -END - -DATE K_DATAREG -BEGIN - PROMPT 1 3 "Data operazione " - FLAGS "D" -END - -DATE K_DATACOMP -BEGIN - PROMPT 1 4 "Data di competenza " - FLAGS "D" -END - -NUMBER K_ANNOES 4 -BEGIN - PROMPT 56 4 "Esercizio " - FLAGS "DZ" -END - -STRING K_CODCAUS 3 -BEGIN - PROMPT 1 5 "Causale " - FLAGS "D" -END - -STRING K_DESCRCAUS 50 -BEGIN - PROMPT 25 5 "" - FLAGS "D" -END - -LIST K_PROVVISORIO 1 25 -BEGIN - PROMPT 1 6 "Movimento provvisorio " - ITEM " |No (movimento normale)" - ITEM "P|Si (cancellabile)" - FLAGS "D" -END - -STRING K_TIPODOC 2 -BEGIN - PROMPT 60 6 "Tipo documento " - FLAGS "D" -END - -DATE K_DATADOC -BEGIN - PROMPT 1 7 "Data del documento " - FLAGS "D" -END - -STRING K_NUMDOC 7 -BEGIN - PROMPT 38 7 "Num. " - FLAGS "D" -END - -LIST S_TIPORIGA 1 13 -BEGIN - PROMPT 60 7 "Riga " - ITEM "K|Saldaconto" - ITEM "S|Spese" -END - -SPREADSHEET F_SHEETCG -BEGIN - PROMPT 0 8 "" - ITEM "Dare@15" - ITEM "Avere@15" - ITEM "CF@1" - ITEM "Gr." - ITEM "Co." - ITEM "Sottoc.@6" - ITEM "Descrizione conto@50" - ITEM "Codice" - ITEM "Descrizione riga@50" - ITEM "CF@1" - ITEM "Gr./c@3" - ITEM "Co./c@3" - ITEM "Sottoc./c@6" - ITEM "Descrizione contropartita@50" - ITEM "Giornale" - ITEM " @1" -END - -NUMBER F_DARE 15 -BEGIN - PROMPT 1 -1 "Sbilancio Dare " - FLAGS "DRV" - PICTURE "." -END - -NUMBER F_AVERE 15 -BEGIN - PROMPT 41 -1 "Sbilancio Avere " - FLAGS "DRV" - PICTURE "." -END - -ENDPAGE - -ENDMASK - -#include "cg21cg.uml" - - z +#include "cg2100.h" + +TOOLBAR "" 0 20 0 2 + +#include + +ENDPAGE + +PAGE "OPERAZIONE DI PRIMA NOTA" -1 -1 77 20 + +GROUPBOX DLG_NULL 78 3 +BEGIN + PROMPT 1 0 "@BMovimento di sola contabilita'" +END + +NUMBER F_CODDITTA 5 +BEGIN + PROMPT 3 1 "Ditta " + FLAGS "DFR" + USE LF_NDITTE KEY 1 + INPUT CODDITTA F_CODDITTA + OUTPUT K_CODDITTA CODDITTA + OUTPUT F_RAGSOC RAGSOC + CHECKTYPE NORMAL +END + +STRING F_RAGSOC 50 +BEGIN + PROMPT 17 1 "Ragione " + FLAGS "D" + MESSAGE COPY,K_RAGSOC +END + +NUMBER F_NUMREG 7 +BEGIN + PROMPT 56 3 "Operazione n. " + FIELD NUMREG + FLAGS "DGR" + MESSAGE COPY,K_NUMREG +END + +DATE F_DATAREG +BEGIN + PROMPT 1 3 "Data operazione " + HELP "Data in cui viene effettuata l'operazione" + FIELD DATAREG + CHECKTYPE REQUIRED + MESSAGE COPY,K_DATAREG +END + + +DATE F_DATACOMP +BEGIN + PROMPT 1 4 "Data di competenza " + HELP "Data di competenza dell'operazione" + FIELD DATACOMP + CHECKTYPE REQUIRED + MESSAGE COPY,K_DATACOMP +END + +NUMBER F_ANNOES 4 +BEGIN + PROMPT 56 4 "Esercizio " + FIELD ANNOES + MESSAGE COPY,K_ANNOES + FLAGS "DGZ" +END + +STRING F_CODCAUS 3 +BEGIN + PROMPT 1 5 "Causale " + HELP "Codice della causale generante l'operazione" + FLAGS "UZ" + FIELD CODCAUS + USE LF_CAUSALI + INPUT CODCAUS F_CODCAUS + DISPLAY "Codice" CODCAUS + DISPLAY "Descrizione@50" DESCR + DISPLAY "Tipo" TIPODOC + DISPLAY "Registro" REG + OUTPUT F_CODCAUS CODCAUS + OUTPUT F_DESCRCAUS DESCR + OUTPUT F_TIPODOC TIPODOC + OUTPUT F_TIPOMOV TIPOMOV + CHECKTYPE NORMAL + ADD RUN cg0 -4 + MESSAGE COPY,K_CODCAUS +END + +STRING F_DESCRCAUS 50 +BEGIN + PROMPT 25 5 "" + HELP "Descrizione della causale generante l'operazione" + USE LF_CAUSALI KEY 2 + INPUT DESCR F_DESCRCAUS + DISPLAY "Descrizione@50" DESCR + DISPLAY "Codice" CODCAUS + COPY OUTPUT F_CODCAUS + MESSAGE COPY,K_DESCRCAUS +END + +LIST F_PROVVISORIO 1 25 +BEGIN + PROMPT 1 6 "Movimento provvisorio " + HELP "Indicare se si tratta di movimento provvisorio" + FIELD PROVVIS + ITEM " |No (movimento normale)" + ITEM "P|Si (cancellabile)" + MESSAGE COPY,K_PROVVISORIO +END + +STRING F_TIPODOC 2 +BEGIN + PROMPT 60 6 "Tipo documento " + FIELD TIPODOC + FLAGS "DG" + MESSAGE COPY,K_TIPODOC +END + +NUMBER F_TIPOMOV 1 +BEGIN + PROMPT 32 6 "Tipo movimento " + FIELD LF_MOV->TIPOMOV + FLAGS "H" +END + +DATE F_DATADOC +BEGIN + PROMPT 1 7 "Data del documento " + HELP "Data del documento generante il movimento" + FIELD DATADOC + WARNING "Specificare una data del documento non superiore a quella dell'operazione" + VALIDATE DATE_CMP_FUNC <= F_DATAREG + MESSAGE COPY,K_DATADOC +END + +STRING F_NUMDOC 7 +BEGIN + PROMPT 56 7 "Documento n. " + HELP "Numero del documento generante il movimento" + FIELD NUMDOC + WARNING "La causale impone di specificare il numero documento" + MESSAGE COPY,K_NUMDOC +END + +NUMBER F_ANNOIVA 4 +BEGIN + FLAGS "H" +END + +STRING F_DESCAGG 5 +BEGIN + PROMPT 1 8 "Descrizione " + HELP "Codice descrizione del movimento di contabilita'" + FLAGS "UZ" + USE %DPN + INPUT CODTAB F_DESCAGG + DISPLAY "Codice" CODTAB + DISPLAY "Descrizione@50" S0 + OUTPUT F_DESCAGG CODTAB + OUTPUT F_DESCR S0 + CHECKTYPE NORMAL +END + +STRING F_DESCR 50 +BEGIN + PROMPT 25 8 "" + HELP "Descrizione del movimento di contabilita'" + FIELD DESCR + USE %DPN KEY 2 + INPUT S0 F_DESCR + DISPLAY "Descrizione@50" S0 + DISPLAY "Codice" CODTAB + COPY OUTPUT F_DESCAGG +END + +GROUPBOX DLG_NULL 78 8 +BEGIN + PROMPT 1 10 "Voci per saldaconto" +END + +NUMBER S_TOTDOC 15 0 +BEGIN + PROMPT 2 11 "Totale documento " + FLAGS "R" + PICTURE "." + GROUP 5 +END + +NUMBER S_TOTDOCVAL 15 2 +BEGIN + PROMPT 44 11 "Totale in valuta " + HELP "" + FLAGS "R" + PICTURE ".2" + GROUP 3 +END + + +STRING S_VALUTA 3 +BEGIN + PROMPT 2 13 "Valuta " + HELP "Codice della valuta per movimento" + FIELD LF_MOV->CODVAL + FLAGS "U" + GROUP 3 + USE %VAL + INPUT CODTAB S_VALUTA + DISPLAY "Codice" CODTAB + DISPLAY "Nome@50" S0 + DISPLAY "Ultimo cambio@15" R10 + DISPLAY "Ultimo aggiornamento" D0 + OUTPUT S_VALUTA CODTAB + OUTPUT S_CAMBIO R10 + CHECKTYPE NORMAL +END + +DATE S_DATACAMBIO +BEGIN + PROMPT 22 13 "Data cambio " + FLAGS "R" + USE CAM + INPUT CODTAB[1,3] S_VALUTA + INPUT CODTAB[4,11] S_DATACAMBIO + DISPLAY "Valuta" CODTAB[1,3] + DISPLAY "Data@10" D0 + DISPLAY "Cambio@18" R10 + OUTPUT S_VALUTA CODTAB[1,3] + OUTPUT S_DATACAMBIO D0 + OUTPUT S_CAMBIO R10 + GROUP 3 +END + +NUMBER S_CAMBIO 15 5 +BEGIN + PROMPT 54 13 "Cambio " + HELP "Cambio della valuta" + FIELD LF_MOV->CAMBIO + FLAGS "RU" + GROUP 3 + PICTURE ".5" +END + +ENDPAGE + +PAGE "OPERAZIONE DI PRIMA NOTA" -1 -1 77 20 + +GROUPBOX DLG_NULL 78 3 +BEGIN + PROMPT 1 0 "@BMovimento di sola contabilita'" +END + +NUMBER K_CODDITTA 5 +BEGIN + PROMPT 3 1 "Ditta " + FLAGS "D" +END + +STRING K_RAGSOC 50 +BEGIN + PROMPT 17 1 "Ragione " + FLAGS "D" +END + +NUMBER K_NUMREG 7 +BEGIN + PROMPT 56 3 "Operazione n. " + FLAGS "RD" +END + +DATE K_DATAREG +BEGIN + PROMPT 1 3 "Data operazione " + FLAGS "D" +END + +DATE K_DATACOMP +BEGIN + PROMPT 1 4 "Data di competenza " + FLAGS "D" +END + +NUMBER K_ANNOES 4 +BEGIN + PROMPT 56 4 "Esercizio " + FLAGS "DZ" +END + +STRING K_CODCAUS 3 +BEGIN + PROMPT 1 5 "Causale " + FLAGS "D" +END + +STRING K_DESCRCAUS 50 +BEGIN + PROMPT 25 5 "" + FLAGS "D" +END + +LIST K_PROVVISORIO 1 25 +BEGIN + PROMPT 1 6 "Movimento provvisorio " + ITEM " |No (movimento normale)" + ITEM "P|Si (cancellabile)" + FLAGS "D" +END + +STRING K_TIPODOC 2 +BEGIN + PROMPT 60 6 "Tipo documento " + FLAGS "D" +END + +DATE K_DATADOC +BEGIN + PROMPT 1 7 "Data del documento " + FLAGS "D" +END + +STRING K_NUMDOC 7 +BEGIN + PROMPT 38 7 "Num. " + FLAGS "D" +END + +LIST S_TIPORIGA 1 13 +BEGIN + PROMPT 60 7 "Riga " + ITEM "K|Saldaconto" + ITEM "S|Spese" +END + +SPREADSHEET F_SHEETCG +BEGIN + PROMPT 0 8 "" + ITEM "Dare@15" + ITEM "Avere@15" + ITEM "CF@1" + ITEM "Gr." + ITEM "Co." + ITEM "Sottoc.@6" + ITEM "Descrizione conto@50" + ITEM "Codice" + ITEM "Descrizione riga@50" + ITEM "CF@1" + ITEM "Gr./c@3" + ITEM "Co./c@3" + ITEM "Sottoc./c@6" + ITEM "Descrizione contropartita@50" + ITEM "Giornale" + ITEM " @1" +END + +NUMBER F_DARE 15 +BEGIN + PROMPT 1 -1 "Sbilancio Dare " + FLAGS "DRV" + PICTURE "." +END + +NUMBER F_AVERE 15 +BEGIN + PROMPT 41 -1 "Sbilancio Avere " + FLAGS "DRV" + PICTURE "." +END + +ENDPAGE + +ENDMASK + +#include "cg21cg.uml" + + z diff --git a/cg/cg2102.cpp b/cg/cg2102.cpp index 5f0ed05f0..a268f8c35 100755 --- a/cg/cg2102.cpp +++ b/cg/cg2102.cpp @@ -1,1962 +1,1962 @@ -#include -#include -#include -#include - -#include "cg2100.h" -#include "cg2102.h" -#include "cg21sld.h" - -#include -#include - -/////////////////////////////////////////////////////////// -// Funzioni di decodifica/calcolo -/////////////////////////////////////////////////////////// - -HIDDEN char row_type(const TToken_string& s) -{ - const int l = s.len()-1; - return l > 0 ? s[l] : ' '; -} - -// Determina il tipo IVA da causale+anno -// Certified 100% -TipoIVA TPrimanota_application::cau2IVA(const char* causale, int annoiva) -{ - TipoIVA i = nessuna_iva; - - if (*causale > ' ') - { - TCausale& c = app().causale(); - if (c.read(causale, annoiva)) - i = c.iva(); - else - { - error_box("Causale errata: '%s'", causale); - i = iva_errata; - } - } - - return i; -} - -// Calcolo della percentuale di un dato codice IVA -// Certified 99% -const real& TPrimanota_application::cod2IVA(const TMask& m) -{ - static TString16 _codiva; - static real _percent; - - if (app().iva() == iva_acquisti && m.get_int(103) == 3) - return ZERO; - - const TString& codiva = m.get(102); - if (_codiva != codiva) - { - _codiva = codiva; - TCodiceIVA c(_codiva); - _percent = c.percentuale(); - } - - return _percent; -} - - -// Scorpora dall'imponibile la percentuale d'imposta(0.0%-100.0%) e ritorna l'imposta stessa -// Certified 99% Non sono sicurissimo degli imponibili negativi -real TPrimanota_application::scorpora(real& imponibile, const real& percent) -{ - real imposta = abs(imponibile) * percent / (percent + 100.0); imposta.ceil(); - if (imponibile.sign() < 0) imposta = -imposta; - imponibile -= imposta; - return imposta; -} - - -// Calcola il totale del documento tenenod conto del segno della prima riga e di quella delle -// ritenute sociali sulla causale -real TPrimanota_application::totale_documento() -{ - const TMask& m = curr_mask(); - - const bool swapt = test_swap(FALSE); // Totale invertito ? - const bool swaps = test_swap(TRUE); // Ritenute sociali invertite ? - - real tot(m.get(F_TOTALE)); // Legge totale - const real ritfis(m.get(F_RITFIS)); - tot += ritfis; // Somma ritenute fiscali - - real ritsoc(m.get(F_RITSOC)); - if (swapt ^ swaps) - ritsoc = -ritsoc; - tot += ritsoc; // Somma ritenute sociali con segno - - return tot; -} - - -bool TPrimanota_application::showpartite_handler(TMask_field& f, KEY k) -{ - bool ok = TRUE; - TMask& m = f.mask(); - - if (m.get(116) == "K") - { - TSheet_field& s = *m.get_sheet(); - const int riga = s.selected(); - if (k == K_SPACE) - { - const bool dirty = app().edit_partite(riga); - if (dirty) - { - if (m.field(103).enabled()) - app().disable_cgs_cells(riga, 'K'); - k = K_ENTER; - } - } - - if (k == K_ENTER) - { - const int currig = riga+1; - const long curreg = app().curr_mask().get_long(F_NUMREG); - TImporto importo; - const TString& imp = m.get(101); - if (imp.not_empty()) - importo.set('D', real(imp)); - else - importo.set('A', real(m.get(102))); - - const TImporto speso(app()._partite.importo_speso(curreg, currig)); - - if (importo != speso) - { - ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" - "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); - if (ok) - { - const bool dare = speso.sezione() == 'D'; - m.set(101, dare ? speso.valore().string() : ""); - m.set(102, dare ? "" : speso.valore().string()); - } - } - } - } - return ok; -} - - -// Determina se un codice sospeso o no -// Certified 99% -bool TPrimanota_application::suspended_handler(TMask_field& f, KEY k) -{ - if (f.to_check(k)) - { - CHECKD(f.is_edit(), "Can't check suspension of a non edit-field ", f.dlg()); - const TEdit_field& c = (const TEdit_field&)f; - const TBrowse* b = c.browse(); - CHECKD(b, "Can't check suspension of a edit-field without a USE ", f.dlg()); - const TLocalisamfile& i = b->cursor()->file(); - // Tabella File - const char* sf = i.tab() ? "B2" : "SOSPESO"; - const bool suspended = i.get_bool(sf); - if (suspended) - { - sf = f.get(); - return f.error_box("Il codice '%s' e' sospeso e non puo' essere utilizzato", sf); - } - } - return TRUE; -} - - -// Determina se un codice detrazione e' di tipo detraibile o no -// Certified 70% -bool TPrimanota_application::detraibile(TToken_string& row) -{ - if (app().iva() == iva_vendite) // Vendite sempre detraibili - return TRUE; - - const int tipo_det = row.get_int(2); // Leggi tipo detraibilita - if (tipo_det != 0) - return FALSE; - - const real& prorata = app().causale().reg().prorata(); - return prorata < 100.0; // Se prorata = 100% e' indetraibile -} - -/////////////////////////////////////////////////////////// -// Funzioni di ricerca -/////////////////////////////////////////////////////////// - -int TPrimanota_application::type2pos(char tipo) -{ - TString_array& cg = app().cgs().rows_array(); - for (int i = 0; i < cg.items(); i++) - { - const TToken_string& s = cg.row(i); - const char t = row_type(s); - if (t == tipo) - return i; - } - return -1; -} - - -// Trova nelle righe contabili un conto nelle righe di tipo prescelto -int TPrimanota_application::bill2pos(const TBill& conto, char tipo) -{ - TString_array& cg = app().cgs().rows_array(); - for (int i = 0; i < cg.items(); i++) - { - TToken_string& s = cg.row(i); - const char t = row_type(s); - if (t == tipo) - { - const TBill c(s, 3, 0x0); - if (c == conto) - return i; - } - } - return -1; -} - - -// Trova nelle righe contabili un conto di contropartita per il conto dato -int TPrimanota_application::bill2contr(const TBill& conto, char sezione) const -{ - TString_array& rows = cgs().rows_array(); - for (int i = 0; i < rows.items(); i++) - { - TToken_string& r = rows.row(i); - const real dare(r.get(0)); - const char sez = dare.is_zero() ? 'A' : 'D'; - if (sez == sezione) // Devo cercare sezione contraria - continue; - const TBill c(r, 3, 0x0); - if (conto == c) - return i; - } - return -1; -} - - -// Controlla se un conto e' usato nelle righe IVA -int TPrimanota_application::bill_used(const TBill& conto) const -{ - int users = 0; - - const TArray& rows = ivas().rows_array(); - for (int i = 0; i < rows.items(); i++) - { - TToken_string& row = (TToken_string&)rows[i]; - if (!row.empty_items()) - { - const TBill c(row, 6, 0x0); - if (conto == c) users++; - } - } - - return users; -} - -/* - // Controlla se e' stato usata l'IVA detraibile o indetraibile nelle righe IVA - // Certified 90% - int TPrimanota_application::det_used(char det) const - { - int users = 0; - - const bool detraib = det == 'D'; - TString_array& arr = ivas().rows_array(); - for (int i = 0; i < arr.items(); i++) - { - TToken_string& row = arr.row(i); - if (!row.empty_items()) - { - const bool d = detraibile(row); - if (detraib == d) users++; - } - } - - return users; - } - */ - -/////////////////////////////////////////////////////////// -// Gestione sheet CG -/////////////////////////////////////////////////////////// - -TSheet_field& TPrimanota_application::cgs() const -{ - TSheet_field& s = (TSheet_field&)curr_mask().field(F_SHEETCG); - return s; -} - - -// Certified 100% -// Scrive l'importo imp nella opportuna colonna della riga n -void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp) -{ - TSheet_field& s = cgs(); - imp.add_to(s.row(n), 0); - s.force_update(n); -} - -// Legge l'importo della riga n e lo ritorna col segno dovuto -// Certified 100% -TImporto TPrimanota_application::get_cgs_imp(int n) -{ - TImporto importo; - importo = cgs().row(n); - return importo; -} - -// Certified 90% -bool TPrimanota_application::add_cgs_imp(int n, const TImporto& imp) -{ - TImporto tot; - tot = cgs().row(n); - tot += imp; - set_cgs_imp(n, tot); - return tot.is_zero();; -} - -// Certified 90% -bool TPrimanota_application::sub_cgs_imp(int n, const TImporto& imp) -{ - TImporto tot; - tot = cgs().row(n); - tot -= imp; - set_cgs_imp(n, tot); - return tot.is_zero(); -} - - -TImporto TPrimanota_application::real2imp(const real& r, char row_type) -{ - bool dare; - if (row_type == 'S') - { - dare = causale().sezione_ritsoc() == 'D'; - } - else - { - dare = causale().sezione_clifo() == 'D'; - if (row_type != 'T' && row_type != 'F') dare = !dare; - } - - TImporto importo(dare ? 'D' : 'A', r); - return importo; -} - -// Disabilita le celle della riga contabile n in base al suo tipo -void TPrimanota_application::disable_cgs_cells(int n, char tipo) -{ - int first = 0, last = 0; - switch(tipo) - { - case 'A': // Abbuoni attivi - case 'C': // Differenza cambio - case 'D': // IVA Detraibile - case 'F': // Ritenute Fiscali - case 'N': // IVA Non detraibile - case 'P': // Abbuoni passsivi - case 'R': // Ritenute professionali - case 'S': // Ritenute Sociali - case 'T': // Totale documento - last = 3; - break; - case 'K': // Riga cliente/fornitore per saldaconto - first = 2; - case 'I': - last = 7; // Imponibile - break; - default: - last = 0; // Solo contabile - break; - } - - if (last > 0) - { - TSheet_field& cg = cgs(); - for (int i = first; i < last; i++) - cg.disable_cell(n, i); - if (tipo == 'T' && !causale().corrispettivi()) - { - cg.disable_cell(n, 5); - cg.disable_cell(n, 6); - } - } -} - -void TPrimanota_application::reset_sheet_row(TSheet_field& s, int n) -{ - s.row(s.items()); // Append a new line - s.destroy(n); // Remove line n -} - -int TPrimanota_application::set_cgs_row(int n, const TImporto& imp, - TBill& conto, const char* desc, - char tipo) -{ - TSheet_field& cg = cgs(); - if (n < 0) n = cg.first_empty(); - TToken_string& row = cg.row(n); - row = ""; - imp.add_to(row, 0); - row.add(conto.string(0x3)); - row.add(""); // Codice decrizione - row.add(desc); // Descrizione aggiuntiva - - switch(tipo) // Calcolo contropartita - { - case 'T': - { - TToken_string& irow = ivas().row(0); - for (int i = 5; i < 10; i++) - row.add(irow.get(i == 5 ? 5 : -1)); - } - break; -default: -{ - const int pos = type2pos('T'); - if (pos >= 0) - { - TBill contro(cg.row(pos), 2, 0x3); - row.add(contro.string(0x3)); - } - else row.add(" | | | | "); -} -break; -} - -row << "| |" << tipo; - -disable_cgs_cells(n, tipo); -cg.force_update(n); - -return n; -} - - -HIDDEN int compare_rows(const TObject** o1, const TObject** o2) -{ - // Totale, Rit.Fisc., Rit.Soc., da riga IVA, riga contabile, IVA detr., IVA non detr. - const char* const sort_order = "TFSI DNGAPRLC"; - - const TToken_string* r1 = (const TToken_string*)*o1; - const TToken_string* r2 = (const TToken_string*)*o2; - const char c1 = row_type(*r1); - const char c2 = row_type(*r2); - return int(strchr(sort_order, c1) - strchr(sort_order, c2)); -} - -HIDDEN bool can_remove(TToken_string& s) -{ - const char* dare = s.get(0); - bool yes = dare == NULL ; - if (!yes) - { - if (*dare == '\0' || *dare == ' ' || strcmp(dare,"0") == 0) - { - const char* avere = s.get(); - yes = (avere == NULL || *avere == '\0' || *avere == ' ' || strcmp(avere,"0") == 0); - } - } - return yes; -} - - -void TPrimanota_application::cgs_pack() -{ - TString_array& rows = cgs().rows_array(); - const bool salda = is_saldaconto() && iva() == nessuna_iva; - - for (int i = rows.items()-1; i >= 0; i--) - { - TToken_string& r = rows.row(i); - if (can_remove(r)) - { - if (salda && row_type(r) == 'K') - cg_notify(cgs(), i, K_DEL); - rows.destroy(i, salda); - } - } - if (!salda) - rows.sort(compare_rows); // Pack and sort array -} - - -bool TPrimanota_application::ci_sono_importi() const -{ - TString_array& rows = cgs().rows_array(); - for (int i = 0; i < rows.items(); i++) - { - TToken_string& r = rows.row(i); - const real dare(r.get(0)); - if (dare != ZERO) return TRUE; - const real avere(r.get()); - if (avere != ZERO) return TRUE; - } - return FALSE; -} - -real TPrimanota_application::calcola_saldo() const -{ - TString_array& rows = cgs().rows_array(); - const int max = rows.items(); - - real tdare, tavere; - for (int i = 0; i < max; i++) - { - TToken_string& r = rows.row(i); - tdare += real(r.get(0)); - tavere += real(r.get()); - } - - real sbilancio = abs(tdare)-abs(tavere); - switch (sbilancio.sign()) - { - case +1: // Il dare supera l'avere in valore assoluto - curr_mask().set(F_DARE, (tdare-tavere).string()); - curr_mask().reset(F_AVERE); - break; - case -1: // L'avere supera il dare in valore assoluto - curr_mask().reset(F_DARE); - curr_mask().set(F_AVERE, (tavere-tdare).string()); - break; - default: // Sbilancio nullo - curr_mask().reset(F_DARE); - curr_mask().reset(F_AVERE); - break; - } - - return sbilancio; -} - - -// Handler dello sheet di contabilita' -// Certified 90% -bool TPrimanota_application::cg_handler(TMask_field& f, KEY k) -{ - if (k == K_ENTER) - { - const real saldo = app().calcola_saldo(); - - if (saldo != ZERO) - { - const char* ss = saldo.string("."); - return f.error_box("Il movimento e' sbilanciato di %s lire.", ss); - } - - TSheet_field& cg = app().cgs(); - bool empty = TRUE; - for (int i = 0; i < cg.items(); i++) - { - TToken_string& r = cg.row(i); - TImporto importo; importo = r; - - if (!importo.is_zero()) - { - const TBill c(r, 3, 0x0); - if (!c.ok()) - return f.error_box("Il conto della riga %d non e' completo", i+1); - const TBill co(r, 10, 0x0); - if (!co.empty() && !co.ok()) - return f.error_box("La contropartita della riga %d non e' completa", i+1); - empty = FALSE; - - const char tipo = row_type(r); - if (tipo == 'K' && app().iva() == nessuna_iva && app().is_saldaconto()) - { - const long numreg = f.mask().get_long(F_NUMREG); - const int currig = i+1; - const TImporto speso = app().partite().importo_speso(numreg, currig); - if (importo != speso) - { - bool ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" - "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); - if (ok) app().set_cgs_imp(i, speso); - else return FALSE; - } - } - } - } - - if (empty) - return error_box("Il movimento non ha nessuna riga contabile con un importo"); - } - return TRUE; -} - - -void TPrimanota_application::generazione_righe_cg(int r) -{ - begin_wait(); - - TSheet_field& cg = cgs(); - TToken_string& row = cg.row(r); - - if (can_remove(row)) // Ignora righe senza importo - return; - - TImporto importo; importo = row; - const bool causale_ok = causale().codice()[0] > ' '; - - if (r == 0 && cg.row(1).empty_items()) - { - TBill contro(row, 9, 0x3); // Contropartita della prima riga - if (causale_ok && !contro.ok()) - { - causale().bill(2, contro); // Prendi contropartita dalla causale - if (contro.ok()) - { - contro.add_to(row, 9, 0x3); - cg.force_update(r); - } - } - if (contro.ok()) - { - importo.swap_section(); - set_cgs_row(1, importo, contro, "", ' '); - TBill conto(row, 2, 0x3); - conto.add_to(cg.row(1), 9, 0x3); - cg.force_update(1); - } - } - - if (causale_ok) - { - int first_not_empty = 0; - for (int i = 0; i < r; i++) - { - TToken_string& row = cg.row(i); - if (!can_remove(row)) - { - first_not_empty = i; - break; - } - } - - TBill conto(row, 2, 0x3); - if (first_not_empty == r) // Sono la prima riga con importo ? - { - int last = -1; - for (i = r+1; i < cg.items(); i++) // Aggiorna tutte le altre contropartite - { - TToken_string& rowi = cg.row(i); - int gruppo = rowi.get_int(3); - if (gruppo != 0) // Considera righe con conto ... - { - gruppo = rowi.get_int(10); - if (gruppo == 0) // ... e senza contropartita - { - char sez = ' '; // Calcola sezione D/A della riga i - if (cg.cell_disabled(i,0)) sez = 'A'; else - if (cg.cell_disabled(i,1)) sez = 'D'; - - if (sez != ' ' && importo.sezione() != sez) // Considera solo le sezioni opposte - { - conto.add_to(rowi, 9, 0x3); - cg.force_update(i); - if (last < 0) last = i; - else last = 0; - } - } - } - } - if (last > r) - { - importo.swap_section(); - set_cgs_imp(last, importo); - - const int gruppo = row.get_int(10); - if (gruppo == 0) // Se non ho contropartita ... - { - TBill contro(cg.row(last), 2, 0x3); // ... copiala dalla riga corrispondente - contro.add_to(row, 9, 0x3); - cg.force_update(r); - } - } - } - else - { - TToken_string& first = cg.row(first_not_empty); - int gruppo = first.get_int(10); - if (gruppo == 0) // Se la prima riga non ha contropartita ... - { - conto.add_to(first, 9, 0x3); // ... copiaci la mia partita - cg.force_update(first_not_empty); - } - gruppo = row.get_int(10); - if (gruppo == 0) // Se non ho contropartita ... - { - TBill contro(first, 2, 0x3); // ... copiala dalla prima riga - contro.add_to(row, 9, 0x3); - cg.force_update(r); - } - } - } - - end_wait(); -} - - -bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k) -{ - const char tipo = row_type(cg.row(r)); // Tipo della riga in esame - - switch(k) - { - case K_TAB: - cg.sheet_mask().enable(DLG_DELREC, tipo <= ' ' || tipo == 'K'); - cg.sheet_mask().show(100, tipo == 'K'); - break; - case K_ENTER: - if (app().iva() == nessuna_iva) - app().generazione_righe_cg(r); - app().calcola_saldo(); - break; - case K_DEL: - if (tipo == 'K') - app().notify_cgline_deletion(r+1); - break; - case K_INS: - if (app().iva() == nessuna_iva && app().is_saldaconto()) - { - const char tipo = app().curr_mask().get(S_TIPORIGA)[0]; - if (tipo == 'K') - { - cg.row(r).add("K", 15); - for (int i = 0; i < r; i++) - { - const TToken_string& row = cg.row(i); - if (row_type(row) != 'K') - { - cg.swap_rows(r, i); - break; - } - } - } - } - break; - default: - break; - } - return TRUE; -} - -bool TPrimanota_application::descr_handler(TMask_field& f, KEY k) -{ - if (k == K_TAB && f.focusdirty()) - { - if (app().iva() != nessuna_iva) - { - const int first = type2pos('T'); - if (first >= 0) - { - TSheet_field& cg = app().cgs(); - cg.row(first).add(f.get(), 8); - cg.force_update(first); - } - } - } - if (k == K_ENTER && f.get().empty()) - { - if (f.mask().get(F_CODCAUS).empty()) - return f.error_box("La descrizione del documento e' necessaria in mancanza della causale"); - } - return TRUE; -} - - -// Handler per le colonne 'Dare' e 'Avere' dello sheet contabile. -// Scrivendo qualcosa in dare (101) cancella l'importo in avere (102) e viceversa -bool TPrimanota_application::dareavere_handler(TMask_field& f, KEY k) -{ - if (k == K_TAB && f.focusdirty() && f.get().not_empty()) - { - const int id = 203-f.dlg(); // Calcola id del campo da resettare - f.mask().reset(id); - } - return TRUE; -} - -// cazzorate - -TSheet_field& TPrimanota_application::pags() const -{ - TSheet_field& s = (TSheet_field&)_msk[2]->field(FS_RATESHEET); - return s; -} - -/////////////////////////////////////////////////////////// -// Gestione sheet IVA -/////////////////////////////////////////////////////////// - -TSheet_field& TPrimanota_application::ivas() const -{ - TSheet_field& s = (TSheet_field&)_msk[2]->field(F_SHEETIVA); - return s; -} - - -TBill& TPrimanota_application::ivas_bill(TBill& c) -{ - const int spric = c.tipo_cr(); - if (spric == 2 || spric == 3) - { - const TFixed_string td(causale().tipo_doc()); - if (td == "FV" || td == "NC") c.tipo_cr(4); - } - return c; -} - -bool TPrimanota_application::imponibile_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.dirty()) - { - TMask& m = f.mask(); - TString16 iva(m.get(102)); - if (iva.empty()) - { - iva = app().curr_mask().get(F_CODIVA); - m.set(102, iva); - } - if (iva.not_empty() && !app().causale().corrispettivi()) - { - const real& percent = cod2IVA(m); - const real imponibile(f.get()); - real imposta = abs(imponibile) * percent / 100.0; imposta.ceil(); - if (imponibile.sign() < 0) imposta = -imposta; - m.set(104, imposta.string()); - } - } - - return TRUE; -} - - -bool TPrimanota_application::codiva_handler(TMask_field& f, KEY key) -{ - if (!suspended_handler(f, key)) - return FALSE; - - if (key == K_TAB && f.dirty()) - { - TMask& m = f.mask(); - - if (m.get_int(107) == 0) - { - TCodiceIVA iva(f.get()); - TBill b; app().IVA2bill(iva, b); - - char cr[2] = { b.tipo_cr() + '0', '\0' }; - m.set(105, *cr > '0' ? cr : ""); - - const char tipo[2] = { b.tipo(), '\0' }; - m.set(106, tipo); - m.set(107, b.gruppo()); - m.set(108, b.conto()); - const short id = b.tipo() == 'C' ? 209 : (b.tipo() == 'F' ? 309 : 109); - m.set(id, b.sottoconto()); - m.set(id+1, b.descrizione()); - } - - TMask_field& im = m.field(101); - im.set_dirty(); - im.on_hit(); - } else - if (key == K_ENTER) - { - if (f.get().empty() && f.mask().get(101).not_empty()) - return f.error_box("Codice IVA obbligatorio"); - } - return TRUE; -} - -bool TPrimanota_application::detrazione_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.dirty() && app().iva() == iva_acquisti) - { - TMask_field& ci = f.mask().field(101); - ci.set_dirty(); - ci.on_hit(); - } - return TRUE; -} - -bool TPrimanota_application::imposta_handler(TMask_field& f, KEY key) -{ - if (key == K_ENTER || key == K_TAB) - { - const real imponibile(f.mask().get(101)); - const real& percent = app().causale().corrispettivi() ? ZERO : cod2IVA(f.mask()); - real imposta = abs(imponibile) * percent / 100.0; - imposta.ceil(); - if (imponibile.sign() < 0) imposta = -imposta; - - const real val(f.get()); - if (val != imposta) - { - f.warning_box("L'imposta dovrebbe essere %s", (const char*)imposta.string(".")); - } - } else - if (key == K_F8) - { - real imposta(f.get()); - if (imposta.is_zero()) - { - real imponibile(f.mask().get(101)); - const real& percent = cod2IVA(f.mask()); - imposta = scorpora(imponibile, percent); - f.mask().set(101, imponibile.string()); - f.set(imposta.string()); - } - else - f.warning_box("Cancellare l'imposta (tasto F2) prima di effettuare lo scorporo"); - } - - return TRUE; -} - - -// Calcola il totale degli imponibili e delle imposte e aggiorna -// i corrispondenti campi della maschera -// Certified 99% -real TPrimanota_application::calcola_imp() const -{ - TArray& rows = ivas().rows_array(); - const int max = rows.items(); - - real imponibili, imposte; - for (int r = 0; r < max; r++) - { - TToken_string& row = (TToken_string&)rows[r]; - imponibili += real(row.get(0)); - imposte += real(row.get(3)); - } - - curr_mask().set(F_IMPONIBILI, imponibili.string(), TRUE); - curr_mask().set(F_IMPOSTE, imposte.string(), TRUE); - - return imponibili+imposte; -} - -void TPrimanota_application::ivas_pack() -{ - TString_array& rows = ivas().rows_array(); - - const int max = rows.items(); - for (int i = 0; i < max; i++) - { - TToken_string& r = rows.row(i); - const real imponibile(r.get(0)); - if (imponibile != ZERO) continue; - const real imposta(r.get(3)); - if (imposta != ZERO) continue; - rows.destroy(i, FALSE); - } - - rows.pack(); // Pack array -} - -// Certified 50% -bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k) -{ - static int oldpos,oldposiva; - static real oldimp, oldiva; - - TToken_string& row = iva.row(r); - const TCausale& cau = app().causale(); - - if (k == K_SPACE) - { - oldimp = real(row.get(0)); // Imponibile - oldiva = real(row.get(3)); // Imposta - - if (oldiva.is_zero() && cau.corrispettivi()) - { // In caso di corrispettivi ... - const TCodiceIVA i(row.get(1)); - const real percent = i.percentuale(); - oldiva = scorpora(oldimp, percent); // ... scorpora imposta dall'imponibile - } - - const char tipod = detraibile(row) ? 'D' : 'N'; - oldposiva = type2pos(tipod); - - if (oldposiva < 0 && !oldiva.is_zero()) - { - const int ri = tipod == 'D' ? 3 : 4; // Calcola riga causale per l'IVA - TBill c; cau.bill(ri, c); - if (c.ok()) - { - const TString80 d(cau.desc_agg(ri)); - oldposiva = app().set_cgs_row(-1, app().real2imp(ZERO, 'I'), c, d, tipod); - } - else - if (ri == 4) // Se non esiste il conto IVA indetraibile ... - { // ... somma imponibile e imposta - oldimp += oldiva; - oldiva = 0.0; - } - } - - TBill oldconto(row, 6, 0x0); // g/c/s 6 7 8 - if (oldconto.ok()) - { - oldpos = bill2pos(oldconto, 'I'); - if (oldpos < 0) - { - const TString80 d(cau.desc_agg(2)); - oldpos = app().set_cgs_row(-1, app().real2imp(ZERO, 'I'), oldconto, d, 'I'); - } - } - else - oldpos = -1; // Se il conto e' incompleto ignoralo - } - if (k == K_DEL) // Cancellazione di una riga - { - row.add("0", 0); // Azzera imponibile - row.add("0", 3); // Azzera imposta - k = K_ENTER; // Elegante o Sporco trucco (dipende dai gusti!) - } - if (k == K_ENTER) - { - int delimp = -1, deliva = -1; // Eventuali righe contabili da cancellare - if (oldpos >= 0) // Se il conto esisteva anche prima ... - { // sottrai il vecchio imponibile - TImporto i(app().get_cgs_imp(oldpos)); - i.valore() -= oldimp; - app().set_cgs_imp(oldpos, i); - if (i.is_zero()) delimp = oldpos; - } - if (oldposiva >= 0) // Se conto IVA esisteva anche prima ... - { // sottrai la vecchia imposta - TImporto i(app().get_cgs_imp(oldposiva)); - i.valore() -= oldiva; - app().set_cgs_imp(oldposiva, i); - if (i.is_zero()) deliva = oldposiva; - } - - real imponibile(row.get(0)); // Nuovo imponibile - real imposta(row.get(3)); // Nuova imposta - - if (imposta.is_zero() && app().causale().corrispettivi()) - { // In caso di corrispettivi ... - const TCodiceIVA i(row.get(1)); - const real percent = i.percentuale(); - imposta = scorpora(imponibile, percent); // ... scorpora imposta dall'imponibile - } - - TBill conto(row, 5, 0x3); - int newpos = bill2pos(conto, 'I'); // Riga in cui andra' l'imponibile - - const bool detrarre = detraibile(row); // Determina se IVA detraibile - const int ri = detrarre ? 3 : 4; // Calcola riga causale col conto opportuno - TBill contoiva; app().causale().bill(ri, contoiva); - if (ri == 4 && !contoiva.ok()) // Se non c'e' il conto IVA indetraibile ... - { // ... somma imponibile e imposta - imponibile += imposta; - imposta = 0.0; - } - - // Aggiorna conto sulla riga contabile - if (newpos < 0) - { - if (delimp >= 0) - { - app().reset_cgs_row(delimp); // Cancella vecchia riga - if (deliva > delimp) deliva--; - } - - const TImporto val(app().real2imp(imponibile, 'I')); - if (conto.ok() && !val.is_zero()) // Se c'e' imponibile ... - { // crea una nuova riga contabile - const TString80 d(cau.desc_agg(2)); - app().set_cgs_row(-1, val, conto, d, 'I'); - } - } - else - { - TImporto val(app().real2imp(imponibile, 'I')); - const bool empty = app().add_cgs_imp(newpos, val); - if (empty) // Se la riga si e' azzerata ... - { // ... cancellala - app().reset_cgs_row(newpos); - newpos = -1; - } - } - oldimp = imponibile; - oldpos = newpos; - - // Aggiorna conto IVA sulla riga contabile - - const char tipod = detrarre ? 'D' : 'N'; - int newposiva = type2pos(tipod); - - if (deliva >= 0 && newposiva != deliva) // E' cambiato il tipo d'imposta - app().reset_cgs_row(deliva); // Azzera il vecchio tipo se necessario - - if (newposiva < 0) - { - if (!imposta.is_zero()) // Se c'e' imposta ... - { // ... crea nuova riga per l'IVA - const TImporto val(app().real2imp(imposta, 'I')); - const TString80 d(cau.desc_agg(ri)); - newposiva = app().set_cgs_row(-1, val, contoiva, d, tipod); - } - } -else -{ - const TImporto val(app().real2imp(imposta, 'I')); - const bool empty = app().add_cgs_imp(newposiva, val); - if (empty) // Se l'imposta si e' azzerata ... - { - app().reset_cgs_row(newposiva); // ... cancellala - newposiva = -1; - } - -} - -oldiva = imposta; -oldposiva = newposiva; - -if (r == 0) // Se cambio la prima riga ... - app().add_cgs_tot(app().curr_mask()); // ... ricalcola conti - - app().calcola_imp(); // Ricalcola totale IVA - app().calcola_saldo(); // Ricalcola sbilanci - - TMask& m = app().curr_mask(); - if (app().is_saldaconto() && m.page_enabled(2)) - app().set_scadenze(m); -} - -return TRUE; -} - - -// Handler dello sheet -// Certified 90% -bool TPrimanota_application::iva_handler(TMask_field& f, KEY k) -{ - if ((k == K_TAB && !f.mask().is_running()) || k == K_ENTER) - { - const real imp = app().calcola_imp(); - const real tot = app().totale_documento(); - if (k == K_ENTER) - { - if (imp != tot) - { - TString16 t(tot.string(".")); - TString16 i(imp.string(".")); - return error_box("La somma del totale documento e delle ritenute (%s) e' diverso dalla " - "somma degli imponibili e delle imposte (%s)", (const char*)t, (const char*)i); - } - - TSheet_field& iva = app().ivas(); - for (int i = 0; i < iva.items(); i++) - { - TToken_string& row = iva.row(i); - const real im(row.get(0)); - if (!im.is_zero()) - { - TBill c(row, 5, 0x1); - if (!c.ok() || !c.find()) - return error_box("Il conto della riga iva %d e' errato o incompleto", i+1); - } - } - } - } - return TRUE; -} - -bool TPrimanota_application::cg_conto_handler(TMask_field& f, KEY key) -{ - if (key == K_ENTER) - { - TMask& m = f.mask(); - if (m.get(115)[0] == 'T') // Se riga totale documento - { - const char cf = m.get(f.dlg()-2)[0]; - char tipo = app().clifo(); - if (app().causale().corrispettivi()) tipo = ' '; - if (cf != tipo) - { - const char* d = tipo == ' ' ? "normale" : (tipo == 'C' ? "clienti" : "fornitori"); - return f.error_box("E' richiesto un conto %s.", d); - } - } - } - return TRUE; -} - -// Gestore del sottoconto dello sheet IVA -bool TPrimanota_application::iva_sottoconto_handler(TMask_field& f, KEY key) -{ - if (!suspended_handler(f, key)) - return FALSE; - - if (key == K_TAB && f.dirty()) - { - const TLocalisamfile& piano = ((TEdit_field&)f).browse()->cursor()->file(); - int spric = piano.get_int("TIPOSPRIC"); - if ((spric == 2 || spric == 3) && !app().causale().corrispettivi()) - { - const TFixed_string td(app().causale().tipo_doc()); - if (td == "FV" || td == "NC") spric = 4; - } - f.mask().set(105, spric > 0 ? format("%d", spric) : "", TRUE); - } - return TRUE; -} - - -bool TPrimanota_application::sheet_clifo_handler(TMask_field& f, KEY k) -{ - if (!suspended_handler(f, k)) - return FALSE; - - if (k == K_TAB || k == K_ENTER) - { - TMask& m = f.mask(); - const short cid = 100 + (f.dlg() % 100) -1; - const int conto = m.get_int(cid); - if (conto == 0) - { - const long codice = atol(f.get()); - if (codice > 0L) - { - TBill c(0, 0, codice, f.dlg() > 300 ? 'F' : 'C'); - c.descrizione(); // Carica gruppo e conto - m.set(cid-1, c.gruppo()); - m.set(cid, c.conto()); - } - } - } - return TRUE; -} - -/////////////////////////////////////////////////////////// -// Handlers dei campi della testata -/////////////////////////////////////////////////////////// - -// Handler of the F_NUMREG field on the query mask -// Certified 99% -bool TPrimanota_application::num_handler(TMask_field& f, KEY key) -{ - TMask& m = f.mask(); - const long num = atol(f.get()); - if (key == K_TAB && m.is_running() && num > 0) - { - const long max = app()._lastreg+1; - - app()._skip_giornale_check = FALSE; - app()._skip_bollato_check = FALSE; - - if (num < max) - { - if (app().find(1)) - { - const TLocalisamfile& mov = app()._rel->lfile(); - bool ok = TRUE; - - if (mov.get_bool("STAMPATO")) - { - ok = yesno_box("Il movimento e' gia' stato stampato sul libro giornale:\n" - "si desidera continuare ugualmente"); - app()._skip_giornale_check = ok; - } - - if (ok && mov.get_bool("REGST")) - { - ok = yesno_box("Il movimento e' gia' stato stampato sul bollato:\n" - "si desidera continuare ugualmente"); - app()._skip_bollato_check = ok; - } - - if (ok && mov.get_bool("INVIATO")) - { - ok = yesno_box("Il movimento e' stato inviato ad un'altra contabilita':\n" - "si desidera continuare ugualmente"); - } - - if (ok) // Riempie a mano i campi necessari nel caso non sia stato usata la ricerca F9 - { - m.set(F_DATAREG, mov.get("DATAREG"), TRUE); - m.set(F_DATACOMP, mov.get("DATACOMP"), TRUE); - m.set(F_CODCAUS, mov.get("CODCAUS")); - m.stop_run(K_AUTO_ENTER); - } - } - } - else if (num > max) - { - f.set(format("%ld", max)); - return f.error_box("Non e' possibile inserire movimenti superiori al %ld", max); - } - } - return TRUE; -} - - -// Handler of the F_CODCAUS field on the query mask -// Certified 99% -bool TPrimanota_application::caus_query_handler(TMask_field& f, KEY key) -{ - if (!f.mask().is_running()) return TRUE; - - if (f.to_check(key)) - { - const int ann = f.mask().get_int(F_ANNOIVA); - const char* cau = f.get(); - - const TipoIVA i = cau2IVA(cau, ann); // Cerca causale e suo tipo - if (i != iva_errata) - { - const bool ok = suspended_handler(f, key); // Controlla sospensione - if (ok && key == K_TAB) - f.mask().stop_run(K_INS); // Entra in modo inserimento - } - else - return FALSE; - } - - return TRUE; -} - -// Handler of the F_CODCAUS field on the modify mask -// Certified 99% -bool TPrimanota_application::caus_modify_handler(TMask_field& f, KEY key) -{ - if (f.to_check(key)) - { - bool ok = suspended_handler(f, key); - if (!ok) return FALSE; - - const int ann = f.mask().get_int(F_ANNOIVA); - const TString16 cau(f.get()); - const TCausale c(cau, ann); - if (!c.ok()) return FALSE; - - ok = app().causale().similar(c); - if (!ok) return FALSE; - if (key == K_TAB) - { - app().read_caus(cau, ann); - app().cgs().force_update(); - } - } - - return TRUE; -} - - -// Handler of the F_DATAREG field -// Certified 70% -bool TPrimanota_application::datareg_handler(TMask_field& f, KEY key) -{ - bool ok = TRUE; - TMask& m = f.mask(); - - if ((key == K_TAB && m.is_running()) || key == K_ENTER) - { - const TDate dr(f.get()); // Data dell'operazione - if (dr > TDate(TODAY)) - return f.error_box("La data dell'operazione e' superiore quella di sistema"); - - const int ae = date2esc(dr); // Anno esercizio - if (ae == 0) - return f.error_box("La data dell'operazione non appartiene a nessun esercizio"); - - if (m.query_mode() || app().giornale().year() != ae) - ok = app().giornale().read(ae); - else - ok = TRUE; - - if (!ok) - return f.error_box("Non esiste il libro giornale dell'esercizio %d", ae); - - if (key == K_ENTER || f.focusdirty()) - { - const long numreg = m.get_long(F_NUMREG); - const bool error = numreg == 0 || numreg > app()._lastreg; - - if (key != K_ENTER && !app()._skip_giornale_check) - { - const TLibro_giornale& gio = app().giornale(); - if (dr < gio.last_print()) - { - f.error_box("La data dell'operazione e' antecedente al %s,\n" - "ultima stampa del libro giornale dell'esercizio %d", - gio.last_print().string(), ae); - if (error) return FALSE; - } - if (key == K_TAB && dr < gio.last_reg()) - f.warning_box("La data dell'operazione e' antecedente al %s,\n" - "ultima registrazione sul libro giornale dell'esercizio %d", - gio.last_reg().string(), ae); - } - - if (m.query_mode()) - app().causale().read(m.get(F_CODCAUS), dr.year()); - - TRegistro& reg = app().causale().reg(); - const TString16 codreg(reg.name()); - if (codreg.not_empty()) - { - if (reg.year() != dr.year()) - { - const bool ok = reg.read(codreg, dr.year()); - if (!ok) return FALSE; - app().read_caus(NULL, 0); - if (app().iva() != nessuna_iva) - m.field(F_CODREG).on_hit(); - } - - if (!app()._skip_bollato_check) - { - if (dr < reg.last_print()) - { - f.error_box("La data dell'operazione e' antecedente al %s,\n" - "ultima stampa del registro '%s' dell'anno %d", - reg.last_print().string(), (const char*)codreg, dr.year()); - if (error) return FALSE; - } - if (key == K_TAB && dr < reg.last_reg()) - f.warning_box("La data dell'operazione e' antecedente al %s,\n" - "ultima registrazione sul registro '%s' dell'anno %d", - reg.last_reg().string(), (const char*)codreg, dr.year()); - } - - if (reg.iva() != nessuna_iva && app()._rel->controlla_liquidazione(dr) == TRUE) - { - const char* m = itom(dr.month()); - f.warning_box("La liquidazione IVA relativa al mese di %s e' gia' stata calcolata", m); - } - } - } - } - return ok; -} - -// Handler of the F_DATACOMP field on the modify mask -// Certified 90% -bool TPrimanota_application::datacomp_handler(TMask_field& f, KEY key) -{ - TMask& m = f.mask(); - - if (key == K_TAB || key == K_ENTER) - { - const TDate dr(m.get(F_DATAREG)); // Data operazione - - TString16 datacomp = f.get(); - if (datacomp.empty()) - { - datacomp = dr.string(); - f.set(datacomp); - } - const TDate dc(datacomp); // Data di competenza - const int ae = date2esc(dc); // Esercizio corrispondente - - const char* data = "del 74/ter"; - if (f.dlg() == F_DATACOMP) - { - m.set(F_ANNOES, ae); - data = "di competenza"; - } - - if (ae) - { - int pr; // Esercizio precedente - const int ar = date2esc(dr, &pr); // Esercizio in corso - if (ae != ar && ae != pr) - { - TString80 e; - e << "La data " << data << " deve appartenere all'esercizio " << ar; - if (pr > 0) e << " o al " << pr; - return f.error_box(e); - } - } - else - { - if (m.is_running()) - return f.error_box("La data %s non appartiene a nessun esercizio", data); - } - } - - return TRUE; -} - -// Handler of the F_DATA74TER field on the modify mask -// Certified 90% -bool TPrimanota_application::data74ter_handler(TMask_field& f, KEY key) -{ - if (!f.to_check(key)) return TRUE; - bool ok = datacomp_handler(f, key); - if (ok) - { - const TDate d74(f.get()); - const TLibro_giornale& g = app().giornale(); - if (d74 < g.last_print()) - { - ok = f.error_box("La data per il 74/ter e' antecedente alla data di stampa " - "del libro giornale dell'esercizio %d", g.year()); - } - } - return ok; -} - -bool TPrimanota_application::doc_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB) - { - TMask& m = f.mask(); - const TString& val = f.get(); - - if (!val.empty() && m.field(F_ANNORIF).active()) - { // Se c'e' gestione saldaconto - if (f.dlg() == F_DATADOC) - { - const TDate dd(val); - m.set(F_ANNORIF, dd.year()); // copia data documento - } - else - { - m.set(F_NUMRIF, val); // copia numero documento - } - } - } - - return TRUE; -} - -bool TPrimanota_application::occas_code_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB) - { - const char* code = f.get(); - if (*code) - { - TRelation occas(LF_OCCAS); - occas.lfile().put("CFPI", code); - if (occas.read(_isequal) == NOERR) - { - f.mask().autoload(&occas); - f.mask().send_key(K_TAB, O_COMUNE); // Forza decodifica comuni - f.mask().send_key(K_TAB, O_COMUNENAS); - } - } - } - return TRUE; -} - -bool TPrimanota_application::occas_handler(TMask_field& f, KEY key) -{ - if (key == K_SPACE && f.mask().is_running()) - { - TMask& om = app().occas_mask(); - om.run(); - f.set_focus(); - } - return TRUE; -} - -// Crea o aggiorna la riga contabile col totale documento -// Certified 99% -void TPrimanota_application::add_cgs_tot(TMask& m) -{ - // Lettura del conto dalla maschera - char tipo = app().clifo(); - long codice = m.get_long(tipo == 'C' ? F_CLIENTE : F_FORNITORE); - TBill bill(0, 0, codice, tipo); - - if (!causale().corrispettivi()) - bill.find(); - - if (bill.conto() == 0) - { - // Se l'utente non ha ancora specificato un conto lo prendo dalla prima riga della causale - causale().bill(1, bill); - if (causale().corrispettivi()) - { - tipo = ' '; - codice = bill.sottoconto(); - } - } - - TBill nuovo(bill.gruppo(), bill.conto(), codice, tipo); - - real tot(m.get(F_TOTALE)); - - const int pos = type2pos('T'); - if (pos >= 0) - { - TSheet_field& ss = cgs(); - TToken_string& row = ss.row(pos); - const TBill vecchio(row, 2, 0x1); - if (!vecchio.empty() && nuovo != vecchio) // Se cambio cliente/fornitore - { - for (int i = 0; i < ss.items(); i++) if (i != pos) - { - TToken_string& r = ss.row(i); - const TBill tacchia(r, 9, 0x1); - if (tacchia == vecchio) - { - nuovo.add_to(r, 9, 0x3); // Aggiorna contropartite - ss.force_update(i); - } - } - } - } - - // Creazione/Aggiornamento riga totale - set_cgs_row(pos, real2imp(tot, 'T'), nuovo, m.get(F_DESCR), 'T'); - calcola_saldo(); -} - -// Handler of the F_CLIENTE & F_FORNITORE field on the modify mask -// Certified 99% -bool TPrimanota_application::clifo_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.active()) - { - TMask& m = f.mask(); - - const char cf = app().clifo(); - TLocalisamfile& clifo = ((TEdit_field&)f).browse()->cursor()->file(); - - if (clifo.get_char(CLI_TIPOCF) != cf || clifo.get(CLI_CODCF) != f.get()) - { - clifo.setkey(1); - clifo.put(CLI_TIPOCF, cf); - clifo.put(CLI_CODCF, f.get()); - clifo.read(); - CHECK(clifo.good(), "Impossibile ritrovare il clifo"); - } - if (!suspended_handler(f, key)) - return FALSE; - - if (!m.is_running() || f.dirty()) - { - app()._conto_ricavo.set(clifo.get_int(CLI_GRUPPORIC), - clifo.get_int(CLI_CONTORIC), - clifo.get_long(CLI_SOTTOCRIC)); - - const int alleg = clifo.get_int(CLI_ALLEG); - TEdit_field& upi = m.efield(F_RIEPILOGO); - upi.check_type(alleg == 3 ? CHECK_REQUIRED : CHECK_NORMAL); - - const TString& s = clifo.get(CLI_CODPAG); - if (s.not_empty()) m.set(F_CODPAG, s, TRUE); - } - - const bool occas = clifo.get_bool(CLI_OCCAS); - m.show(F_OCCASEDIT, occas); // Bottone Dati anagrafici - m.show(F_STATOPAIV, !occas); // Stato partita IVA - m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE, !occas); // Partita IVA - m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE, !occas); // Codice Fiscale - - if (f.focusdirty()) - { - app().add_cgs_tot(m); - - if (m.field(S_VALUTA).active()) - { - const TString16 valuta(clifo.get("CODVAL")); - if (valuta.not_empty() && valuta != m.get(S_VALUTA)) - { - TTable val("%val"); - val.put("CODTAB", valuta); - if (val.read() == NOERR) - { - m.set(S_VALUTA, valuta); - m.set(S_CAMBIO, val.get("R10"), TRUE); - } - } - } - if (occas && app().occas_mask().get(O_CODICE).empty()) - m.send_key(K_SPACE, F_OCCASEDIT); // Lancia maschera occasionali - } - } - return TRUE; -} - - -bool TPrimanota_application::IVA2bill(const TCodiceIVA& iva, TBill& bill) -{ - const TCausale& cau = causale(); - const TString& tipo = iva.tipo(); - - if (tipo.not_empty()) - { - if (tipo == "ES") cau.bill(5, bill); else - if (tipo == "NI") cau.bill(6, bill); else - if (tipo == "NS") cau.bill(7, bill); - } - if (!bill.ok() && !cau.corrispettivi()) - bill = _conto_ricavo; - - if (!bill.ok()) - cau.bill(2, bill); - - ivas_bill(bill); - - return bill.ok(); -} - - -// Handler of the F_CODIVA -// Certified 99% -bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.get().not_empty()) - { - if (!suspended_handler(f, key)) - return FALSE; - - const real imp(app().ivas().row(1).get(0)); // Se il totale non e' stato spezzato - if (imp.is_zero()) - { - TToken_string& row = app().ivas().row(0); - - TMask& m = f.mask(); - iva_notify(app().ivas(), 0, K_SPACE); - - const TCodiceIVA iva(f.get()); - const bool corr = app().causale().corrispettivi(); - const bool acq3 = (app().iva() == iva_acquisti) && (row.get_int(2) == 3); - - real tot = app().totale_documento(); // Calcola totale documento - real imposta; // Calcola imposta - if (!corr && !acq3) - imposta = app().scorpora(tot, iva.percentuale()); - - row.add(tot.string(), 0); // imponibile - row.add(imposta.string(), 3); // imposta - - if (iva.codice() != row.get(1)) - { - row.add(iva.codice(), 1); // Aggiorna codice IVA - TBill bill; // Aggiorna conto della prima riga IVA - app().IVA2bill(iva, bill); - bill.add_to(row, 4, 0x7); - } - app().ivas().force_update(0); - - iva_notify(app().ivas(), 0, K_ENTER); - } - } - return TRUE; -} - -// Handler of the F_TOTALE -// Certified 99% -bool TPrimanota_application::totale_handler(TMask_field& f, KEY key) -{ - bool ok = TRUE; - TMask& m = f.mask(); - - if (key == K_TAB && f.focusdirty()) - { - app().add_cgs_tot(m); - m.field(F_CODIVA).on_hit(); - } - - if (key == K_ENTER && f.get().empty()) - ok = f.yesno_box("Totale documento nullo: continuare ugualmente?"); - return ok; -} - -bool TPrimanota_application::totdoc_handler(TMask_field& f, KEY key) -{ - bool ok = TRUE; - if (key == K_ENTER && f.get().empty()) - ok = f.yesno_box("Totale documento nullo: continuare ugualmente?"); - return ok; -} - - -void TPrimanota_application::add_cgs_rit(bool fiscali) -{ - const real imp(curr_mask().get(fiscali ? F_RITFIS : F_RITSOC)); - - const char tipo = fiscali ? 'F' : 'S'; - const int pos = type2pos(tipo); - if (pos < 0) - { - const int riga = fiscali ? 8 : 9; - TBill conto; causale().bill(riga, conto); - const TString80 desc(causale().desc_agg(riga)); - set_cgs_row(-1, real2imp(imp, tipo), conto, desc, tipo); - } - else - { - if (imp.is_zero()) - reset_cgs_row(pos); - else - set_cgs_imp(pos, real2imp(imp, tipo)); - } -} - -// Handler of the F_PROTIVA -bool TPrimanota_application::protiva_handler(TMask_field& f, KEY key) -{ - bool ok = TRUE; - if (key == K_ENTER && f.dirty() && f.mask().mode() == MODE_INS) - { - const long protiva = atol(f.get()); - const long protocol = app().causale().reg().protocol() + 1; - if (protiva != protocol) - ok = f.yesno_box("Accettare il protocollo IVA fuori sequenza: %ld invece di %ld", - protiva, protocol); - } - return ok; -} - - -// Handler of the F_RITFIS -// Certified 99% -bool TPrimanota_application::ritfis_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.focusdirty()) - app().add_cgs_rit(TRUE); - return TRUE; -} - - -// Handler of F_RITSOC -// Certified 99% -bool TPrimanota_application::ritsoc_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.focusdirty()) - app().add_cgs_rit(FALSE); - return TRUE; -} - -// Handler of F_CORRLIRE -// Certified 99% -bool TPrimanota_application::corrlire_handler(TMask_field& f, KEY key) -{ - TMask& m = f.mask(); - - if (key == K_ENTER && f.get().empty()) - { - if (m.get(F_CORRVALUTA).not_empty()) - { - TMask_field& cv = m.field(F_CORRVALUTA); - cv.set_focusdirty(); - cv.on_hit(); - } - else - key = K_F8; - } - - if (key == K_F8) - { - f.set(m.get(F_IMPONIBILI)); - f.set_dirty(); - m.reset(F_CORRVALUTA); - key = K_TAB; - } - if (key == K_TAB && f.focusdirty()) - { - if (m.get(F_CORRVALUTA).empty()) - { - const real cambio = m.get(F_CAMBIOINTRA); - if (cambio != ZERO && m.get(F_CORRVALUTA).empty()) - { - real c(f.get()); - c /= cambio; - m.set(F_CORRVALUTA, c.string()); - } - } - } - - if (key == K_ENTER) - { - const TString16 im(m.get(F_IMPONIBILI)); - const char* cl = f.get(); - if (im != cl) - warning_box("Il corrispettivo in lire e' diverso dal totale degli imponibili"); - } - - return TRUE; -} - -// Handler of F_CORRVALUTA -// Certified 99% -bool TPrimanota_application::corrvaluta_handler(TMask_field& f, KEY key) -{ - if (key == K_TAB && f.focusdirty()) - { - TMask& m = f.mask(); - if (m.get(F_CORRLIRE).empty()) - { - const real cambio = m.get(F_CAMBIOINTRA); - if (cambio != ZERO) - { - real c = f.get(); - c *= cambio; - m.set(F_CORRLIRE, c.string()); - } - } - } else - if (key == K_ENTER && f.get().empty()) - { - TMask_field& cl = f.mask().field(F_CORRLIRE); - cl.set_dirty(); - cl.on_hit(); - } - - return TRUE; -} - - -bool TPrimanota_application::solaiva_handler(TMask_field& f, KEY key) -{ - if (key == K_SPACE) - { - TMask& m = f.mask(); - const bool anchecg = !m.get_bool(F_SOLAIVA); - - m.show(F_SHEETCG, anchecg); - m.show(F_DARE, anchecg); - m.show(F_AVERE, anchecg); - - if (m.is_running() && anchecg) - { - TSheet_field& iva = app().ivas(); - const int righe = iva.items(); - TProgind pi(righe, "Generazione righe contabilita'", FALSE, TRUE, 16); - - app().cgs().reset(); - app().add_cgs_tot(m); - if (m.get(F_RITFIS).not_empty()) app().add_cgs_rit(TRUE); - if (m.get(F_RITSOC).not_empty()) app().add_cgs_rit(FALSE); - - TToken_string oldrow(128); - for (int i = 0; i < righe; i++) - { - TToken_string& r = iva.row(i); - if (!r.empty_items()) - { - oldrow = r; - r = ""; - iva_notify(iva, i, K_SPACE); - r = oldrow; - iva_notify(iva, i, K_ENTER); - } - pi.setstatus(i+1); - } - app().fill_sheet(m); - app().cgs().force_update(); - m.set_focus(); - } - } - return TRUE; -} - - +#include +#include +#include +#include + +#include "cg2100.h" +#include "cg2102.h" +#include "cg21sld.h" + +#include +#include + +/////////////////////////////////////////////////////////// +// Funzioni di decodifica/calcolo +/////////////////////////////////////////////////////////// + +HIDDEN char row_type(const TToken_string& s) +{ + const int l = s.len()-1; + return l > 0 ? s[l] : ' '; +} + +// Determina il tipo IVA da causale+anno +// Certified 100% +TipoIVA TPrimanota_application::cau2IVA(const char* causale, int annoiva) +{ + TipoIVA i = nessuna_iva; + + if (*causale > ' ') + { + TCausale& c = app().causale(); + if (c.read(causale, annoiva)) + i = c.iva(); + else + { + error_box("Causale errata: '%s'", causale); + i = iva_errata; + } + } + + return i; +} + +// Calcolo della percentuale di un dato codice IVA +// Certified 99% +const real& TPrimanota_application::cod2IVA(const TMask& m) +{ + static TString16 _codiva; + static real _percent; + + if (app().iva() == iva_acquisti && m.get_int(103) == 3) + return ZERO; + + const TString& codiva = m.get(102); + if (_codiva != codiva) + { + _codiva = codiva; + TCodiceIVA c(_codiva); + _percent = c.percentuale(); + } + + return _percent; +} + + +// Scorpora dall'imponibile la percentuale d'imposta(0.0%-100.0%) e ritorna l'imposta stessa +// Certified 99% Non sono sicurissimo degli imponibili negativi +real TPrimanota_application::scorpora(real& imponibile, const real& percent) +{ + real imposta = abs(imponibile) * percent / (percent + 100.0); imposta.ceil(); + if (imponibile.sign() < 0) imposta = -imposta; + imponibile -= imposta; + return imposta; +} + + +// Calcola il totale del documento tenenod conto del segno della prima riga e di quella delle +// ritenute sociali sulla causale +real TPrimanota_application::totale_documento() +{ + const TMask& m = curr_mask(); + + const bool swapt = test_swap(FALSE); // Totale invertito ? + const bool swaps = test_swap(TRUE); // Ritenute sociali invertite ? + + real tot(m.get(F_TOTALE)); // Legge totale + const real ritfis(m.get(F_RITFIS)); + tot += ritfis; // Somma ritenute fiscali + + real ritsoc(m.get(F_RITSOC)); + if (swapt ^ swaps) + ritsoc = -ritsoc; + tot += ritsoc; // Somma ritenute sociali con segno + + return tot; +} + + +bool TPrimanota_application::showpartite_handler(TMask_field& f, KEY k) +{ + bool ok = TRUE; + TMask& m = f.mask(); + + if (m.get(116) == "K") + { + TSheet_field& s = *m.get_sheet(); + const int riga = s.selected(); + if (k == K_SPACE) + { + const bool dirty = app().edit_partite(riga); + if (dirty) + { + if (m.field(103).enabled()) + app().disable_cgs_cells(riga, 'K'); + k = K_ENTER; + } + } + + if (k == K_ENTER) + { + const int currig = riga+1; + const long curreg = app().curr_mask().get_long(F_NUMREG); + TImporto importo; + const TString& imp = m.get(101); + if (imp.not_empty()) + importo.set('D', real(imp)); + else + importo.set('A', real(m.get(102))); + + const TImporto speso(app()._partite.importo_speso(curreg, currig)); + + if (importo != speso) + { + ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" + "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); + if (ok) + { + const bool dare = speso.sezione() == 'D'; + m.set(101, dare ? speso.valore().string() : ""); + m.set(102, dare ? "" : speso.valore().string()); + } + } + } + } + return ok; +} + + +// Determina se un codice sospeso o no +// Certified 99% +bool TPrimanota_application::suspended_handler(TMask_field& f, KEY k) +{ + if (f.to_check(k)) + { + CHECKD(f.is_edit(), "Can't check suspension of a non edit-field ", f.dlg()); + const TEdit_field& c = (const TEdit_field&)f; + const TBrowse* b = c.browse(); + CHECKD(b, "Can't check suspension of a edit-field without a USE ", f.dlg()); + const TLocalisamfile& i = b->cursor()->file(); + // Tabella File + const char* sf = i.tab() ? "B2" : "SOSPESO"; + const bool suspended = i.get_bool(sf); + if (suspended) + { + sf = f.get(); + return f.error_box("Il codice '%s' e' sospeso e non puo' essere utilizzato", sf); + } + } + return TRUE; +} + + +// Determina se un codice detrazione e' di tipo detraibile o no +// Certified 70% +bool TPrimanota_application::detraibile(TToken_string& row) +{ + if (app().iva() == iva_vendite) // Vendite sempre detraibili + return TRUE; + + const int tipo_det = row.get_int(2); // Leggi tipo detraibilita + if (tipo_det != 0) + return FALSE; + + const real& prorata = app().causale().reg().prorata(); + return prorata < 100.0; // Se prorata = 100% e' indetraibile +} + +/////////////////////////////////////////////////////////// +// Funzioni di ricerca +/////////////////////////////////////////////////////////// + +int TPrimanota_application::type2pos(char tipo) +{ + TString_array& cg = app().cgs().rows_array(); + for (int i = 0; i < cg.items(); i++) + { + const TToken_string& s = cg.row(i); + const char t = row_type(s); + if (t == tipo) + return i; + } + return -1; +} + + +// Trova nelle righe contabili un conto nelle righe di tipo prescelto +int TPrimanota_application::bill2pos(const TBill& conto, char tipo) +{ + TString_array& cg = app().cgs().rows_array(); + for (int i = 0; i < cg.items(); i++) + { + TToken_string& s = cg.row(i); + const char t = row_type(s); + if (t == tipo) + { + const TBill c(s, 3, 0x0); + if (c == conto) + return i; + } + } + return -1; +} + + +// Trova nelle righe contabili un conto di contropartita per il conto dato +int TPrimanota_application::bill2contr(const TBill& conto, char sezione) const +{ + TString_array& rows = cgs().rows_array(); + for (int i = 0; i < rows.items(); i++) + { + TToken_string& r = rows.row(i); + const real dare(r.get(0)); + const char sez = dare.is_zero() ? 'A' : 'D'; + if (sez == sezione) // Devo cercare sezione contraria + continue; + const TBill c(r, 3, 0x0); + if (conto == c) + return i; + } + return -1; +} + + +// Controlla se un conto e' usato nelle righe IVA +int TPrimanota_application::bill_used(const TBill& conto) const +{ + int users = 0; + + const TArray& rows = ivas().rows_array(); + for (int i = 0; i < rows.items(); i++) + { + TToken_string& row = (TToken_string&)rows[i]; + if (!row.empty_items()) + { + const TBill c(row, 6, 0x0); + if (conto == c) users++; + } + } + + return users; +} + +/* + // Controlla se e' stato usata l'IVA detraibile o indetraibile nelle righe IVA + // Certified 90% + int TPrimanota_application::det_used(char det) const + { + int users = 0; + + const bool detraib = det == 'D'; + TString_array& arr = ivas().rows_array(); + for (int i = 0; i < arr.items(); i++) + { + TToken_string& row = arr.row(i); + if (!row.empty_items()) + { + const bool d = detraibile(row); + if (detraib == d) users++; + } + } + + return users; + } + */ + +/////////////////////////////////////////////////////////// +// Gestione sheet CG +/////////////////////////////////////////////////////////// + +TSheet_field& TPrimanota_application::cgs() const +{ + TSheet_field& s = (TSheet_field&)curr_mask().field(F_SHEETCG); + return s; +} + + +// Certified 100% +// Scrive l'importo imp nella opportuna colonna della riga n +void TPrimanota_application::set_cgs_imp(int n, const TImporto& imp) +{ + TSheet_field& s = cgs(); + imp.add_to(s.row(n), 0); + s.force_update(n); +} + +// Legge l'importo della riga n e lo ritorna col segno dovuto +// Certified 100% +TImporto TPrimanota_application::get_cgs_imp(int n) +{ + TImporto importo; + importo = cgs().row(n); + return importo; +} + +// Certified 90% +bool TPrimanota_application::add_cgs_imp(int n, const TImporto& imp) +{ + TImporto tot; + tot = cgs().row(n); + tot += imp; + set_cgs_imp(n, tot); + return tot.is_zero();; +} + +// Certified 90% +bool TPrimanota_application::sub_cgs_imp(int n, const TImporto& imp) +{ + TImporto tot; + tot = cgs().row(n); + tot -= imp; + set_cgs_imp(n, tot); + return tot.is_zero(); +} + + +TImporto TPrimanota_application::real2imp(const real& r, char row_type) +{ + bool dare; + if (row_type == 'S') + { + dare = causale().sezione_ritsoc() == 'D'; + } + else + { + dare = causale().sezione_clifo() == 'D'; + if (row_type != 'T' && row_type != 'F') dare = !dare; + } + + TImporto importo(dare ? 'D' : 'A', r); + return importo; +} + +// Disabilita le celle della riga contabile n in base al suo tipo +void TPrimanota_application::disable_cgs_cells(int n, char tipo) +{ + int first = 0, last = 0; + switch(tipo) + { + case 'A': // Abbuoni attivi + case 'C': // Differenza cambio + case 'D': // IVA Detraibile + case 'F': // Ritenute Fiscali + case 'N': // IVA Non detraibile + case 'P': // Abbuoni passsivi + case 'R': // Ritenute professionali + case 'S': // Ritenute Sociali + case 'T': // Totale documento + last = 3; + break; + case 'K': // Riga cliente/fornitore per saldaconto + first = 2; + case 'I': + last = 7; // Imponibile + break; + default: + last = 0; // Solo contabile + break; + } + + if (last > 0) + { + TSheet_field& cg = cgs(); + for (int i = first; i < last; i++) + cg.disable_cell(n, i); + if (tipo == 'T' && !causale().corrispettivi()) + { + cg.disable_cell(n, 5); + cg.disable_cell(n, 6); + } + } +} + +void TPrimanota_application::reset_sheet_row(TSheet_field& s, int n) +{ + s.row(s.items()); // Append a new line + s.destroy(n); // Remove line n +} + +int TPrimanota_application::set_cgs_row(int n, const TImporto& imp, + TBill& conto, const char* desc, + char tipo) +{ + TSheet_field& cg = cgs(); + if (n < 0) n = cg.first_empty(); + TToken_string& row = cg.row(n); + row = ""; + imp.add_to(row, 0); + row.add(conto.string(0x3)); + row.add(""); // Codice decrizione + row.add(desc); // Descrizione aggiuntiva + + switch(tipo) // Calcolo contropartita + { + case 'T': + { + TToken_string& irow = ivas().row(0); + for (int i = 5; i < 10; i++) + row.add(irow.get(i == 5 ? 5 : -1)); + } + break; +default: +{ + const int pos = type2pos('T'); + if (pos >= 0) + { + TBill contro(cg.row(pos), 2, 0x3); + row.add(contro.string(0x3)); + } + else row.add(" | | | | "); +} +break; +} + +row << "| |" << tipo; + +disable_cgs_cells(n, tipo); +cg.force_update(n); + +return n; +} + + +HIDDEN int compare_rows(const TObject** o1, const TObject** o2) +{ + // Totale, Rit.Fisc., Rit.Soc., da riga IVA, riga contabile, IVA detr., IVA non detr. + const char* const sort_order = "TFSI DNGAPRLC"; + + const TToken_string* r1 = (const TToken_string*)*o1; + const TToken_string* r2 = (const TToken_string*)*o2; + const char c1 = row_type(*r1); + const char c2 = row_type(*r2); + return int(strchr(sort_order, c1) - strchr(sort_order, c2)); +} + +HIDDEN bool can_remove(TToken_string& s) +{ + const char* dare = s.get(0); + bool yes = dare == NULL ; + if (!yes) + { + if (*dare == '\0' || *dare == ' ' || strcmp(dare,"0") == 0) + { + const char* avere = s.get(); + yes = (avere == NULL || *avere == '\0' || *avere == ' ' || strcmp(avere,"0") == 0); + } + } + return yes; +} + + +void TPrimanota_application::cgs_pack() +{ + TString_array& rows = cgs().rows_array(); + const bool salda = is_saldaconto() && iva() == nessuna_iva; + + for (int i = rows.items()-1; i >= 0; i--) + { + TToken_string& r = rows.row(i); + if (can_remove(r)) + { + if (salda && row_type(r) == 'K') + cg_notify(cgs(), i, K_DEL); + rows.destroy(i, salda); + } + } + if (!salda) + rows.sort(compare_rows); // Pack and sort array +} + + +bool TPrimanota_application::ci_sono_importi() const +{ + TString_array& rows = cgs().rows_array(); + for (int i = 0; i < rows.items(); i++) + { + TToken_string& r = rows.row(i); + const real dare(r.get(0)); + if (dare != ZERO) return TRUE; + const real avere(r.get()); + if (avere != ZERO) return TRUE; + } + return FALSE; +} + +real TPrimanota_application::calcola_saldo() const +{ + TString_array& rows = cgs().rows_array(); + const int max = rows.items(); + + real tdare, tavere; + for (int i = 0; i < max; i++) + { + TToken_string& r = rows.row(i); + tdare += real(r.get(0)); + tavere += real(r.get()); + } + + real sbilancio = abs(tdare)-abs(tavere); + switch (sbilancio.sign()) + { + case +1: // Il dare supera l'avere in valore assoluto + curr_mask().set(F_DARE, (tdare-tavere).string()); + curr_mask().reset(F_AVERE); + break; + case -1: // L'avere supera il dare in valore assoluto + curr_mask().reset(F_DARE); + curr_mask().set(F_AVERE, (tavere-tdare).string()); + break; + default: // Sbilancio nullo + curr_mask().reset(F_DARE); + curr_mask().reset(F_AVERE); + break; + } + + return sbilancio; +} + + +// Handler dello sheet di contabilita' +// Certified 90% +bool TPrimanota_application::cg_handler(TMask_field& f, KEY k) +{ + if (k == K_ENTER) + { + const real saldo = app().calcola_saldo(); + + if (saldo != ZERO) + { + const char* ss = saldo.string("."); + return f.error_box("Il movimento e' sbilanciato di %s lire.", ss); + } + + TSheet_field& cg = app().cgs(); + bool empty = TRUE; + for (int i = 0; i < cg.items(); i++) + { + TToken_string& r = cg.row(i); + TImporto importo; importo = r; + + if (!importo.is_zero()) + { + const TBill c(r, 3, 0x0); + if (!c.ok()) + return f.error_box("Il conto della riga %d non e' completo", i+1); + const TBill co(r, 10, 0x0); + if (!co.empty() && !co.ok()) + return f.error_box("La contropartita della riga %d non e' completa", i+1); + empty = FALSE; + + const char tipo = row_type(r); + if (tipo == 'K' && app().iva() == nessuna_iva && app().is_saldaconto()) + { + const long numreg = f.mask().get_long(F_NUMREG); + const int currig = i+1; + const TImporto speso = app().partite().importo_speso(numreg, currig); + if (importo != speso) + { + bool ok = yesno_box("L'importo dei pagamenti %c %s\ne' diverso dall'importo sulla riga %d.\n" + "Si desidera correggerlo?", speso.sezione(), speso.valore().string("."), currig); + if (ok) app().set_cgs_imp(i, speso); + else return FALSE; + } + } + } + } + + if (empty) + return error_box("Il movimento non ha nessuna riga contabile con un importo"); + } + return TRUE; +} + + +void TPrimanota_application::generazione_righe_cg(int r) +{ + begin_wait(); + + TSheet_field& cg = cgs(); + TToken_string& row = cg.row(r); + + if (can_remove(row)) // Ignora righe senza importo + return; + + TImporto importo; importo = row; + const bool causale_ok = causale().codice()[0] > ' '; + + if (r == 0 && cg.row(1).empty_items()) + { + TBill contro(row, 9, 0x3); // Contropartita della prima riga + if (causale_ok && !contro.ok()) + { + causale().bill(2, contro); // Prendi contropartita dalla causale + if (contro.ok()) + { + contro.add_to(row, 9, 0x3); + cg.force_update(r); + } + } + if (contro.ok()) + { + importo.swap_section(); + set_cgs_row(1, importo, contro, "", ' '); + TBill conto(row, 2, 0x3); + conto.add_to(cg.row(1), 9, 0x3); + cg.force_update(1); + } + } + + if (causale_ok) + { + int first_not_empty = 0; + for (int i = 0; i < r; i++) + { + TToken_string& row = cg.row(i); + if (!can_remove(row)) + { + first_not_empty = i; + break; + } + } + + TBill conto(row, 2, 0x3); + if (first_not_empty == r) // Sono la prima riga con importo ? + { + int last = -1; + for (i = r+1; i < cg.items(); i++) // Aggiorna tutte le altre contropartite + { + TToken_string& rowi = cg.row(i); + int gruppo = rowi.get_int(3); + if (gruppo != 0) // Considera righe con conto ... + { + gruppo = rowi.get_int(10); + if (gruppo == 0) // ... e senza contropartita + { + char sez = ' '; // Calcola sezione D/A della riga i + if (cg.cell_disabled(i,0)) sez = 'A'; else + if (cg.cell_disabled(i,1)) sez = 'D'; + + if (sez != ' ' && importo.sezione() != sez) // Considera solo le sezioni opposte + { + conto.add_to(rowi, 9, 0x3); + cg.force_update(i); + if (last < 0) last = i; + else last = 0; + } + } + } + } + if (last > r) + { + importo.swap_section(); + set_cgs_imp(last, importo); + + const int gruppo = row.get_int(10); + if (gruppo == 0) // Se non ho contropartita ... + { + TBill contro(cg.row(last), 2, 0x3); // ... copiala dalla riga corrispondente + contro.add_to(row, 9, 0x3); + cg.force_update(r); + } + } + } + else + { + TToken_string& first = cg.row(first_not_empty); + int gruppo = first.get_int(10); + if (gruppo == 0) // Se la prima riga non ha contropartita ... + { + conto.add_to(first, 9, 0x3); // ... copiaci la mia partita + cg.force_update(first_not_empty); + } + gruppo = row.get_int(10); + if (gruppo == 0) // Se non ho contropartita ... + { + TBill contro(first, 2, 0x3); // ... copiala dalla prima riga + contro.add_to(row, 9, 0x3); + cg.force_update(r); + } + } + } + + end_wait(); +} + + +bool TPrimanota_application::cg_notify(TSheet_field& cg, int r, KEY k) +{ + const char tipo = row_type(cg.row(r)); // Tipo della riga in esame + + switch(k) + { + case K_TAB: + cg.sheet_mask().enable(DLG_DELREC, tipo <= ' ' || tipo == 'K'); + cg.sheet_mask().show(100, tipo == 'K'); + break; + case K_ENTER: + if (app().iva() == nessuna_iva) + app().generazione_righe_cg(r); + app().calcola_saldo(); + break; + case K_DEL: + if (tipo == 'K') + app().notify_cgline_deletion(r+1); + break; + case K_INS: + if (app().iva() == nessuna_iva && app().is_saldaconto()) + { + const char tipo = app().curr_mask().get(S_TIPORIGA)[0]; + if (tipo == 'K') + { + cg.row(r).add("K", 15); + for (int i = 0; i < r; i++) + { + const TToken_string& row = cg.row(i); + if (row_type(row) != 'K') + { + cg.swap_rows(r, i); + break; + } + } + } + } + break; + default: + break; + } + return TRUE; +} + +bool TPrimanota_application::descr_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.focusdirty()) + { + if (app().iva() != nessuna_iva) + { + const int first = type2pos('T'); + if (first >= 0) + { + TSheet_field& cg = app().cgs(); + cg.row(first).add(f.get(), 8); + cg.force_update(first); + } + } + } + if (k == K_ENTER && f.get().empty()) + { + if (f.mask().get(F_CODCAUS).empty()) + return f.error_box("La descrizione del documento e' necessaria in mancanza della causale"); + } + return TRUE; +} + + +// Handler per le colonne 'Dare' e 'Avere' dello sheet contabile. +// Scrivendo qualcosa in dare (101) cancella l'importo in avere (102) e viceversa +bool TPrimanota_application::dareavere_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.focusdirty() && f.get().not_empty()) + { + const int id = 203-f.dlg(); // Calcola id del campo da resettare + f.mask().reset(id); + } + return TRUE; +} + +// cazzorate + +TSheet_field& TPrimanota_application::pags() const +{ + TSheet_field& s = (TSheet_field&)_msk[2]->field(FS_RATESHEET); + return s; +} + +/////////////////////////////////////////////////////////// +// Gestione sheet IVA +/////////////////////////////////////////////////////////// + +TSheet_field& TPrimanota_application::ivas() const +{ + TSheet_field& s = (TSheet_field&)_msk[2]->field(F_SHEETIVA); + return s; +} + + +TBill& TPrimanota_application::ivas_bill(TBill& c) +{ + const int spric = c.tipo_cr(); + if (spric == 2 || spric == 3) + { + const TFixed_string td(causale().tipo_doc()); + if (td == "FV" || td == "NC") c.tipo_cr(4); + } + return c; +} + +bool TPrimanota_application::imponibile_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.dirty()) + { + TMask& m = f.mask(); + TString16 iva(m.get(102)); + if (iva.empty()) + { + iva = app().curr_mask().get(F_CODIVA); + m.set(102, iva); + } + if (iva.not_empty() && !app().causale().corrispettivi()) + { + const real& percent = cod2IVA(m); + const real imponibile(f.get()); + real imposta = abs(imponibile) * percent / 100.0; imposta.ceil(); + if (imponibile.sign() < 0) imposta = -imposta; + m.set(104, imposta.string()); + } + } + + return TRUE; +} + + +bool TPrimanota_application::codiva_handler(TMask_field& f, KEY key) +{ + if (!suspended_handler(f, key)) + return FALSE; + + if (key == K_TAB && f.dirty()) + { + TMask& m = f.mask(); + + if (m.get_int(107) == 0) + { + TCodiceIVA iva(f.get()); + TBill b; app().IVA2bill(iva, b); + + char cr[2] = { b.tipo_cr() + '0', '\0' }; + m.set(105, *cr > '0' ? cr : ""); + + const char tipo[2] = { b.tipo(), '\0' }; + m.set(106, tipo); + m.set(107, b.gruppo()); + m.set(108, b.conto()); + const short id = b.tipo() == 'C' ? 209 : (b.tipo() == 'F' ? 309 : 109); + m.set(id, b.sottoconto()); + m.set(id+1, b.descrizione()); + } + + TMask_field& im = m.field(101); + im.set_dirty(); + im.on_hit(); + } else + if (key == K_ENTER) + { + if (f.get().empty() && f.mask().get(101).not_empty()) + return f.error_box("Codice IVA obbligatorio"); + } + return TRUE; +} + +bool TPrimanota_application::detrazione_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.dirty() && app().iva() == iva_acquisti) + { + TMask_field& ci = f.mask().field(101); + ci.set_dirty(); + ci.on_hit(); + } + return TRUE; +} + +bool TPrimanota_application::imposta_handler(TMask_field& f, KEY key) +{ + if (key == K_ENTER || key == K_TAB) + { + const real imponibile(f.mask().get(101)); + const real& percent = app().causale().corrispettivi() ? ZERO : cod2IVA(f.mask()); + real imposta = abs(imponibile) * percent / 100.0; + imposta.ceil(); + if (imponibile.sign() < 0) imposta = -imposta; + + const real val(f.get()); + if (val != imposta) + { + f.warning_box("L'imposta dovrebbe essere %s", (const char*)imposta.string(".")); + } + } else + if (key == K_F8) + { + real imposta(f.get()); + if (imposta.is_zero()) + { + real imponibile(f.mask().get(101)); + const real& percent = cod2IVA(f.mask()); + imposta = scorpora(imponibile, percent); + f.mask().set(101, imponibile.string()); + f.set(imposta.string()); + } + else + f.warning_box("Cancellare l'imposta (tasto F2) prima di effettuare lo scorporo"); + } + + return TRUE; +} + + +// Calcola il totale degli imponibili e delle imposte e aggiorna +// i corrispondenti campi della maschera +// Certified 99% +real TPrimanota_application::calcola_imp() const +{ + TArray& rows = ivas().rows_array(); + const int max = rows.items(); + + real imponibili, imposte; + for (int r = 0; r < max; r++) + { + TToken_string& row = (TToken_string&)rows[r]; + imponibili += real(row.get(0)); + imposte += real(row.get(3)); + } + + curr_mask().set(F_IMPONIBILI, imponibili.string(), TRUE); + curr_mask().set(F_IMPOSTE, imposte.string(), TRUE); + + return imponibili+imposte; +} + +void TPrimanota_application::ivas_pack() +{ + TString_array& rows = ivas().rows_array(); + + const int max = rows.items(); + for (int i = 0; i < max; i++) + { + TToken_string& r = rows.row(i); + const real imponibile(r.get(0)); + if (imponibile != ZERO) continue; + const real imposta(r.get(3)); + if (imposta != ZERO) continue; + rows.destroy(i, FALSE); + } + + rows.pack(); // Pack array +} + +// Certified 50% +bool TPrimanota_application::iva_notify(TSheet_field& iva, int r, KEY k) +{ + static int oldpos,oldposiva; + static real oldimp, oldiva; + + TToken_string& row = iva.row(r); + const TCausale& cau = app().causale(); + + if (k == K_SPACE) + { + oldimp = real(row.get(0)); // Imponibile + oldiva = real(row.get(3)); // Imposta + + if (oldiva.is_zero() && cau.corrispettivi()) + { // In caso di corrispettivi ... + const TCodiceIVA i(row.get(1)); + const real percent = i.percentuale(); + oldiva = scorpora(oldimp, percent); // ... scorpora imposta dall'imponibile + } + + const char tipod = detraibile(row) ? 'D' : 'N'; + oldposiva = type2pos(tipod); + + if (oldposiva < 0 && !oldiva.is_zero()) + { + const int ri = tipod == 'D' ? 3 : 4; // Calcola riga causale per l'IVA + TBill c; cau.bill(ri, c); + if (c.ok()) + { + const TString80 d(cau.desc_agg(ri)); + oldposiva = app().set_cgs_row(-1, app().real2imp(ZERO, 'I'), c, d, tipod); + } + else + if (ri == 4) // Se non esiste il conto IVA indetraibile ... + { // ... somma imponibile e imposta + oldimp += oldiva; + oldiva = 0.0; + } + } + + TBill oldconto(row, 6, 0x0); // g/c/s 6 7 8 + if (oldconto.ok()) + { + oldpos = bill2pos(oldconto, 'I'); + if (oldpos < 0) + { + const TString80 d(cau.desc_agg(2)); + oldpos = app().set_cgs_row(-1, app().real2imp(ZERO, 'I'), oldconto, d, 'I'); + } + } + else + oldpos = -1; // Se il conto e' incompleto ignoralo + } + if (k == K_DEL) // Cancellazione di una riga + { + row.add("0", 0); // Azzera imponibile + row.add("0", 3); // Azzera imposta + k = K_ENTER; // Elegante o Sporco trucco (dipende dai gusti!) + } + if (k == K_ENTER) + { + int delimp = -1, deliva = -1; // Eventuali righe contabili da cancellare + if (oldpos >= 0) // Se il conto esisteva anche prima ... + { // sottrai il vecchio imponibile + TImporto i(app().get_cgs_imp(oldpos)); + i.valore() -= oldimp; + app().set_cgs_imp(oldpos, i); + if (i.is_zero()) delimp = oldpos; + } + if (oldposiva >= 0) // Se conto IVA esisteva anche prima ... + { // sottrai la vecchia imposta + TImporto i(app().get_cgs_imp(oldposiva)); + i.valore() -= oldiva; + app().set_cgs_imp(oldposiva, i); + if (i.is_zero()) deliva = oldposiva; + } + + real imponibile(row.get(0)); // Nuovo imponibile + real imposta(row.get(3)); // Nuova imposta + + if (imposta.is_zero() && app().causale().corrispettivi()) + { // In caso di corrispettivi ... + const TCodiceIVA i(row.get(1)); + const real percent = i.percentuale(); + imposta = scorpora(imponibile, percent); // ... scorpora imposta dall'imponibile + } + + TBill conto(row, 5, 0x3); + int newpos = bill2pos(conto, 'I'); // Riga in cui andra' l'imponibile + + const bool detrarre = detraibile(row); // Determina se IVA detraibile + const int ri = detrarre ? 3 : 4; // Calcola riga causale col conto opportuno + TBill contoiva; app().causale().bill(ri, contoiva); + if (ri == 4 && !contoiva.ok()) // Se non c'e' il conto IVA indetraibile ... + { // ... somma imponibile e imposta + imponibile += imposta; + imposta = 0.0; + } + + // Aggiorna conto sulla riga contabile + if (newpos < 0) + { + if (delimp >= 0) + { + app().reset_cgs_row(delimp); // Cancella vecchia riga + if (deliva > delimp) deliva--; + } + + const TImporto val(app().real2imp(imponibile, 'I')); + if (conto.ok() && !val.is_zero()) // Se c'e' imponibile ... + { // crea una nuova riga contabile + const TString80 d(cau.desc_agg(2)); + app().set_cgs_row(-1, val, conto, d, 'I'); + } + } + else + { + TImporto val(app().real2imp(imponibile, 'I')); + const bool empty = app().add_cgs_imp(newpos, val); + if (empty) // Se la riga si e' azzerata ... + { // ... cancellala + app().reset_cgs_row(newpos); + newpos = -1; + } + } + oldimp = imponibile; + oldpos = newpos; + + // Aggiorna conto IVA sulla riga contabile + + const char tipod = detrarre ? 'D' : 'N'; + int newposiva = type2pos(tipod); + + if (deliva >= 0 && newposiva != deliva) // E' cambiato il tipo d'imposta + app().reset_cgs_row(deliva); // Azzera il vecchio tipo se necessario + + if (newposiva < 0) + { + if (!imposta.is_zero()) // Se c'e' imposta ... + { // ... crea nuova riga per l'IVA + const TImporto val(app().real2imp(imposta, 'I')); + const TString80 d(cau.desc_agg(ri)); + newposiva = app().set_cgs_row(-1, val, contoiva, d, tipod); + } + } +else +{ + const TImporto val(app().real2imp(imposta, 'I')); + const bool empty = app().add_cgs_imp(newposiva, val); + if (empty) // Se l'imposta si e' azzerata ... + { + app().reset_cgs_row(newposiva); // ... cancellala + newposiva = -1; + } + +} + +oldiva = imposta; +oldposiva = newposiva; + +if (r == 0) // Se cambio la prima riga ... + app().add_cgs_tot(app().curr_mask()); // ... ricalcola conti + + app().calcola_imp(); // Ricalcola totale IVA + app().calcola_saldo(); // Ricalcola sbilanci + + TMask& m = app().curr_mask(); + if (app().is_saldaconto() && m.page_enabled(2)) + app().set_scadenze(m); +} + +return TRUE; +} + + +// Handler dello sheet +// Certified 90% +bool TPrimanota_application::iva_handler(TMask_field& f, KEY k) +{ + if ((k == K_TAB && !f.mask().is_running()) || k == K_ENTER) + { + const real imp = app().calcola_imp(); + const real tot = app().totale_documento(); + if (k == K_ENTER) + { + if (imp != tot) + { + TString16 t(tot.string(".")); + TString16 i(imp.string(".")); + return error_box("La somma del totale documento e delle ritenute (%s) e' diverso dalla " + "somma degli imponibili e delle imposte (%s)", (const char*)t, (const char*)i); + } + + TSheet_field& iva = app().ivas(); + for (int i = 0; i < iva.items(); i++) + { + TToken_string& row = iva.row(i); + const real im(row.get(0)); + if (!im.is_zero()) + { + TBill c(row, 5, 0x1); + if (!c.ok() || !c.find()) + return error_box("Il conto della riga iva %d e' errato o incompleto", i+1); + } + } + } + } + return TRUE; +} + +bool TPrimanota_application::cg_conto_handler(TMask_field& f, KEY key) +{ + if (key == K_ENTER) + { + TMask& m = f.mask(); + if (m.get(115)[0] == 'T') // Se riga totale documento + { + const char cf = m.get(f.dlg()-2)[0]; + char tipo = app().clifo(); + if (app().causale().corrispettivi()) tipo = ' '; + if (cf != tipo) + { + const char* d = tipo == ' ' ? "normale" : (tipo == 'C' ? "clienti" : "fornitori"); + return f.error_box("E' richiesto un conto %s.", d); + } + } + } + return TRUE; +} + +// Gestore del sottoconto dello sheet IVA +bool TPrimanota_application::iva_sottoconto_handler(TMask_field& f, KEY key) +{ + if (!suspended_handler(f, key)) + return FALSE; + + if (key == K_TAB && f.dirty()) + { + const TLocalisamfile& piano = ((TEdit_field&)f).browse()->cursor()->file(); + int spric = piano.get_int("TIPOSPRIC"); + if ((spric == 2 || spric == 3) && !app().causale().corrispettivi()) + { + const TFixed_string td(app().causale().tipo_doc()); + if (td == "FV" || td == "NC") spric = 4; + } + f.mask().set(105, spric > 0 ? format("%d", spric) : "", TRUE); + } + return TRUE; +} + + +bool TPrimanota_application::sheet_clifo_handler(TMask_field& f, KEY k) +{ + if (!suspended_handler(f, k)) + return FALSE; + + if (k == K_TAB || k == K_ENTER) + { + TMask& m = f.mask(); + const short cid = 100 + (f.dlg() % 100) -1; + const int conto = m.get_int(cid); + if (conto == 0) + { + const long codice = atol(f.get()); + if (codice > 0L) + { + TBill c(0, 0, codice, f.dlg() > 300 ? 'F' : 'C'); + c.descrizione(); // Carica gruppo e conto + m.set(cid-1, c.gruppo()); + m.set(cid, c.conto()); + } + } + } + return TRUE; +} + +/////////////////////////////////////////////////////////// +// Handlers dei campi della testata +/////////////////////////////////////////////////////////// + +// Handler of the F_NUMREG field on the query mask +// Certified 99% +bool TPrimanota_application::num_handler(TMask_field& f, KEY key) +{ + TMask& m = f.mask(); + const long num = atol(f.get()); + if (key == K_TAB && m.is_running() && num > 0) + { + const long max = app()._lastreg+1; + + app()._skip_giornale_check = FALSE; + app()._skip_bollato_check = FALSE; + + if (num < max) + { + if (app().find(1)) + { + const TLocalisamfile& mov = app()._rel->lfile(); + bool ok = TRUE; + + if (mov.get_bool("STAMPATO")) + { + ok = yesno_box("Il movimento e' gia' stato stampato sul libro giornale:\n" + "si desidera continuare ugualmente"); + app()._skip_giornale_check = ok; + } + + if (ok && mov.get_bool("REGST")) + { + ok = yesno_box("Il movimento e' gia' stato stampato sul bollato:\n" + "si desidera continuare ugualmente"); + app()._skip_bollato_check = ok; + } + + if (ok && mov.get_bool("INVIATO")) + { + ok = yesno_box("Il movimento e' stato inviato ad un'altra contabilita':\n" + "si desidera continuare ugualmente"); + } + + if (ok) // Riempie a mano i campi necessari nel caso non sia stato usata la ricerca F9 + { + m.set(F_DATAREG, mov.get("DATAREG"), TRUE); + m.set(F_DATACOMP, mov.get("DATACOMP"), TRUE); + m.set(F_CODCAUS, mov.get("CODCAUS")); + m.stop_run(K_AUTO_ENTER); + } + } + } + else if (num > max) + { + f.set(format("%ld", max)); + return f.error_box("Non e' possibile inserire movimenti superiori al %ld", max); + } + } + return TRUE; +} + + +// Handler of the F_CODCAUS field on the query mask +// Certified 99% +bool TPrimanota_application::caus_query_handler(TMask_field& f, KEY key) +{ + if (!f.mask().is_running()) return TRUE; + + if (f.to_check(key)) + { + const int ann = f.mask().get_int(F_ANNOIVA); + const char* cau = f.get(); + + const TipoIVA i = cau2IVA(cau, ann); // Cerca causale e suo tipo + if (i != iva_errata) + { + const bool ok = suspended_handler(f, key); // Controlla sospensione + if (ok && key == K_TAB) + f.mask().stop_run(K_INS); // Entra in modo inserimento + } + else + return FALSE; + } + + return TRUE; +} + +// Handler of the F_CODCAUS field on the modify mask +// Certified 99% +bool TPrimanota_application::caus_modify_handler(TMask_field& f, KEY key) +{ + if (f.to_check(key)) + { + bool ok = suspended_handler(f, key); + if (!ok) return FALSE; + + const int ann = f.mask().get_int(F_ANNOIVA); + const TString16 cau(f.get()); + const TCausale c(cau, ann); + if (!c.ok()) return FALSE; + + ok = app().causale().similar(c); + if (!ok) return FALSE; + if (key == K_TAB) + { + app().read_caus(cau, ann); + app().cgs().force_update(); + } + } + + return TRUE; +} + + +// Handler of the F_DATAREG field +// Certified 70% +bool TPrimanota_application::datareg_handler(TMask_field& f, KEY key) +{ + bool ok = TRUE; + TMask& m = f.mask(); + + if ((key == K_TAB && m.is_running()) || key == K_ENTER) + { + const TDate dr(f.get()); // Data dell'operazione + if (dr > TDate(TODAY)) + return f.error_box("La data dell'operazione e' superiore quella di sistema"); + + const int ae = date2esc(dr); // Anno esercizio + if (ae == 0) + return f.error_box("La data dell'operazione non appartiene a nessun esercizio"); + + if (m.query_mode() || app().giornale().year() != ae) + ok = app().giornale().read(ae); + else + ok = TRUE; + + if (!ok) + return f.error_box("Non esiste il libro giornale dell'esercizio %d", ae); + + if (key == K_ENTER || f.focusdirty()) + { + const long numreg = m.get_long(F_NUMREG); + const bool error = numreg == 0 || numreg > app()._lastreg; + + if (key != K_ENTER && !app()._skip_giornale_check) + { + const TLibro_giornale& gio = app().giornale(); + if (dr < gio.last_print()) + { + f.error_box("La data dell'operazione e' antecedente al %s,\n" + "ultima stampa del libro giornale dell'esercizio %d", + gio.last_print().string(), ae); + if (error) return FALSE; + } + if (key == K_TAB && dr < gio.last_reg()) + f.warning_box("La data dell'operazione e' antecedente al %s,\n" + "ultima registrazione sul libro giornale dell'esercizio %d", + gio.last_reg().string(), ae); + } + + if (m.query_mode()) + app().causale().read(m.get(F_CODCAUS), dr.year()); + + TRegistro& reg = app().causale().reg(); + const TString16 codreg(reg.name()); + if (codreg.not_empty()) + { + if (reg.year() != dr.year()) + { + const bool ok = reg.read(codreg, dr.year()); + if (!ok) return FALSE; + app().read_caus(NULL, 0); + if (app().iva() != nessuna_iva) + m.field(F_CODREG).on_hit(); + } + + if (!app()._skip_bollato_check) + { + if (dr < reg.last_print()) + { + f.error_box("La data dell'operazione e' antecedente al %s,\n" + "ultima stampa del registro '%s' dell'anno %d", + reg.last_print().string(), (const char*)codreg, dr.year()); + if (error) return FALSE; + } + if (key == K_TAB && dr < reg.last_reg()) + f.warning_box("La data dell'operazione e' antecedente al %s,\n" + "ultima registrazione sul registro '%s' dell'anno %d", + reg.last_reg().string(), (const char*)codreg, dr.year()); + } + + if (reg.iva() != nessuna_iva && app()._rel->controlla_liquidazione(dr) == TRUE) + { + const char* m = itom(dr.month()); + f.warning_box("La liquidazione IVA relativa al mese di %s e' gia' stata calcolata", m); + } + } + } + } + return ok; +} + +// Handler of the F_DATACOMP field on the modify mask +// Certified 90% +bool TPrimanota_application::datacomp_handler(TMask_field& f, KEY key) +{ + TMask& m = f.mask(); + + if (key == K_TAB || key == K_ENTER) + { + const TDate dr(m.get(F_DATAREG)); // Data operazione + + TString16 datacomp = f.get(); + if (datacomp.empty()) + { + datacomp = dr.string(); + f.set(datacomp); + } + const TDate dc(datacomp); // Data di competenza + const int ae = date2esc(dc); // Esercizio corrispondente + + const char* data = "del 74/ter"; + if (f.dlg() == F_DATACOMP) + { + m.set(F_ANNOES, ae); + data = "di competenza"; + } + + if (ae) + { + int pr; // Esercizio precedente + const int ar = date2esc(dr, &pr); // Esercizio in corso + if (ae != ar && ae != pr) + { + TString80 e; + e << "La data " << data << " deve appartenere all'esercizio " << ar; + if (pr > 0) e << " o al " << pr; + return f.error_box(e); + } + } + else + { + if (m.is_running()) + return f.error_box("La data %s non appartiene a nessun esercizio", data); + } + } + + return TRUE; +} + +// Handler of the F_DATA74TER field on the modify mask +// Certified 90% +bool TPrimanota_application::data74ter_handler(TMask_field& f, KEY key) +{ + if (!f.to_check(key)) return TRUE; + bool ok = datacomp_handler(f, key); + if (ok) + { + const TDate d74(f.get()); + const TLibro_giornale& g = app().giornale(); + if (d74 < g.last_print()) + { + ok = f.error_box("La data per il 74/ter e' antecedente alla data di stampa " + "del libro giornale dell'esercizio %d", g.year()); + } + } + return ok; +} + +bool TPrimanota_application::doc_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB) + { + TMask& m = f.mask(); + const TString& val = f.get(); + + if (!val.empty() && m.field(F_ANNORIF).active()) + { // Se c'e' gestione saldaconto + if (f.dlg() == F_DATADOC) + { + const TDate dd(val); + m.set(F_ANNORIF, dd.year()); // copia data documento + } + else + { + m.set(F_NUMRIF, val); // copia numero documento + } + } + } + + return TRUE; +} + +bool TPrimanota_application::occas_code_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB) + { + const char* code = f.get(); + if (*code) + { + TRelation occas(LF_OCCAS); + occas.lfile().put("CFPI", code); + if (occas.read(_isequal) == NOERR) + { + f.mask().autoload(&occas); + f.mask().send_key(K_TAB, O_COMUNE); // Forza decodifica comuni + f.mask().send_key(K_TAB, O_COMUNENAS); + } + } + } + return TRUE; +} + +bool TPrimanota_application::occas_handler(TMask_field& f, KEY key) +{ + if (key == K_SPACE && f.mask().is_running()) + { + TMask& om = app().occas_mask(); + om.run(); + f.set_focus(); + } + return TRUE; +} + +// Crea o aggiorna la riga contabile col totale documento +// Certified 99% +void TPrimanota_application::add_cgs_tot(TMask& m) +{ + // Lettura del conto dalla maschera + char tipo = app().clifo(); + long codice = m.get_long(tipo == 'C' ? F_CLIENTE : F_FORNITORE); + TBill bill(0, 0, codice, tipo); + + if (!causale().corrispettivi()) + bill.find(); + + if (bill.conto() == 0) + { + // Se l'utente non ha ancora specificato un conto lo prendo dalla prima riga della causale + causale().bill(1, bill); + if (causale().corrispettivi()) + { + tipo = ' '; + codice = bill.sottoconto(); + } + } + + TBill nuovo(bill.gruppo(), bill.conto(), codice, tipo); + + real tot(m.get(F_TOTALE)); + + const int pos = type2pos('T'); + if (pos >= 0) + { + TSheet_field& ss = cgs(); + TToken_string& row = ss.row(pos); + const TBill vecchio(row, 2, 0x1); + if (!vecchio.empty() && nuovo != vecchio) // Se cambio cliente/fornitore + { + for (int i = 0; i < ss.items(); i++) if (i != pos) + { + TToken_string& r = ss.row(i); + const TBill tacchia(r, 9, 0x1); + if (tacchia == vecchio) + { + nuovo.add_to(r, 9, 0x3); // Aggiorna contropartite + ss.force_update(i); + } + } + } + } + + // Creazione/Aggiornamento riga totale + set_cgs_row(pos, real2imp(tot, 'T'), nuovo, m.get(F_DESCR), 'T'); + calcola_saldo(); +} + +// Handler of the F_CLIENTE & F_FORNITORE field on the modify mask +// Certified 99% +bool TPrimanota_application::clifo_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.active()) + { + TMask& m = f.mask(); + + const char cf = app().clifo(); + TLocalisamfile& clifo = ((TEdit_field&)f).browse()->cursor()->file(); + + if (clifo.get_char(CLI_TIPOCF) != cf || clifo.get(CLI_CODCF) != f.get()) + { + clifo.setkey(1); + clifo.put(CLI_TIPOCF, cf); + clifo.put(CLI_CODCF, f.get()); + clifo.read(); + CHECK(clifo.good(), "Impossibile ritrovare il clifo"); + } + if (!suspended_handler(f, key)) + return FALSE; + + if (!m.is_running() || f.dirty()) + { + app()._conto_ricavo.set(clifo.get_int(CLI_GRUPPORIC), + clifo.get_int(CLI_CONTORIC), + clifo.get_long(CLI_SOTTOCRIC)); + + const int alleg = clifo.get_int(CLI_ALLEG); + TEdit_field& upi = m.efield(F_RIEPILOGO); + upi.check_type(alleg == 3 ? CHECK_REQUIRED : CHECK_NORMAL); + + const TString& s = clifo.get(CLI_CODPAG); + if (s.not_empty()) m.set(F_CODPAG, s, TRUE); + } + + const bool occas = clifo.get_bool(CLI_OCCAS); + m.show(F_OCCASEDIT, occas); // Bottone Dati anagrafici + m.show(F_STATOPAIV, !occas); // Stato partita IVA + m.show(cf == 'C' ? F_PIVACLIENTE : F_PIVAFORNITORE, !occas); // Partita IVA + m.show(cf == 'C' ? F_COFICLIENTE : F_COFIFORNITORE, !occas); // Codice Fiscale + + if (f.focusdirty()) + { + app().add_cgs_tot(m); + + if (m.field(S_VALUTA).active()) + { + const TString16 valuta(clifo.get("CODVAL")); + if (valuta.not_empty() && valuta != m.get(S_VALUTA)) + { + TTable val("%val"); + val.put("CODTAB", valuta); + if (val.read() == NOERR) + { + m.set(S_VALUTA, valuta); + m.set(S_CAMBIO, val.get("R10"), TRUE); + } + } + } + if (occas && app().occas_mask().get(O_CODICE).empty()) + m.send_key(K_SPACE, F_OCCASEDIT); // Lancia maschera occasionali + } + } + return TRUE; +} + + +bool TPrimanota_application::IVA2bill(const TCodiceIVA& iva, TBill& bill) +{ + const TCausale& cau = causale(); + const TString& tipo = iva.tipo(); + + if (tipo.not_empty()) + { + if (tipo == "ES") cau.bill(5, bill); else + if (tipo == "NI") cau.bill(6, bill); else + if (tipo == "NS") cau.bill(7, bill); + } + if (!bill.ok() && !cau.corrispettivi()) + bill = _conto_ricavo; + + if (!bill.ok()) + cau.bill(2, bill); + + ivas_bill(bill); + + return bill.ok(); +} + + +// Handler of the F_CODIVA +// Certified 99% +bool TPrimanota_application::main_codiva_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.get().not_empty()) + { + if (!suspended_handler(f, key)) + return FALSE; + + const real imp(app().ivas().row(1).get(0)); // Se il totale non e' stato spezzato + if (imp.is_zero()) + { + TToken_string& row = app().ivas().row(0); + + TMask& m = f.mask(); + iva_notify(app().ivas(), 0, K_SPACE); + + const TCodiceIVA iva(f.get()); + const bool corr = app().causale().corrispettivi(); + const bool acq3 = (app().iva() == iva_acquisti) && (row.get_int(2) == 3); + + real tot = app().totale_documento(); // Calcola totale documento + real imposta; // Calcola imposta + if (!corr && !acq3) + imposta = app().scorpora(tot, iva.percentuale()); + + row.add(tot.string(), 0); // imponibile + row.add(imposta.string(), 3); // imposta + + if (iva.codice() != row.get(1)) + { + row.add(iva.codice(), 1); // Aggiorna codice IVA + TBill bill; // Aggiorna conto della prima riga IVA + app().IVA2bill(iva, bill); + bill.add_to(row, 4, 0x7); + } + app().ivas().force_update(0); + + iva_notify(app().ivas(), 0, K_ENTER); + } + } + return TRUE; +} + +// Handler of the F_TOTALE +// Certified 99% +bool TPrimanota_application::totale_handler(TMask_field& f, KEY key) +{ + bool ok = TRUE; + TMask& m = f.mask(); + + if (key == K_TAB && f.focusdirty()) + { + app().add_cgs_tot(m); + m.field(F_CODIVA).on_hit(); + } + + if (key == K_ENTER && f.get().empty()) + ok = f.yesno_box("Totale documento nullo: continuare ugualmente?"); + return ok; +} + +bool TPrimanota_application::totdoc_handler(TMask_field& f, KEY key) +{ + bool ok = TRUE; + if (key == K_ENTER && f.get().empty()) + ok = f.yesno_box("Totale documento nullo: continuare ugualmente?"); + return ok; +} + + +void TPrimanota_application::add_cgs_rit(bool fiscali) +{ + const real imp(curr_mask().get(fiscali ? F_RITFIS : F_RITSOC)); + + const char tipo = fiscali ? 'F' : 'S'; + const int pos = type2pos(tipo); + if (pos < 0) + { + const int riga = fiscali ? 8 : 9; + TBill conto; causale().bill(riga, conto); + const TString80 desc(causale().desc_agg(riga)); + set_cgs_row(-1, real2imp(imp, tipo), conto, desc, tipo); + } + else + { + if (imp.is_zero()) + reset_cgs_row(pos); + else + set_cgs_imp(pos, real2imp(imp, tipo)); + } +} + +// Handler of the F_PROTIVA +bool TPrimanota_application::protiva_handler(TMask_field& f, KEY key) +{ + bool ok = TRUE; + if (key == K_ENTER && f.dirty() && f.mask().mode() == MODE_INS) + { + const long protiva = atol(f.get()); + const long protocol = app().causale().reg().protocol() + 1; + if (protiva != protocol) + ok = f.yesno_box("Accettare il protocollo IVA fuori sequenza: %ld invece di %ld", + protiva, protocol); + } + return ok; +} + + +// Handler of the F_RITFIS +// Certified 99% +bool TPrimanota_application::ritfis_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.focusdirty()) + app().add_cgs_rit(TRUE); + return TRUE; +} + + +// Handler of F_RITSOC +// Certified 99% +bool TPrimanota_application::ritsoc_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.focusdirty()) + app().add_cgs_rit(FALSE); + return TRUE; +} + +// Handler of F_CORRLIRE +// Certified 99% +bool TPrimanota_application::corrlire_handler(TMask_field& f, KEY key) +{ + TMask& m = f.mask(); + + if (key == K_ENTER && f.get().empty()) + { + if (m.get(F_CORRVALUTA).not_empty()) + { + TMask_field& cv = m.field(F_CORRVALUTA); + cv.set_focusdirty(); + cv.on_hit(); + } + else + key = K_F8; + } + + if (key == K_F8) + { + f.set(m.get(F_IMPONIBILI)); + f.set_dirty(); + m.reset(F_CORRVALUTA); + key = K_TAB; + } + if (key == K_TAB && f.focusdirty()) + { + if (m.get(F_CORRVALUTA).empty()) + { + const real cambio = m.get(F_CAMBIOINTRA); + if (cambio != ZERO && m.get(F_CORRVALUTA).empty()) + { + real c(f.get()); + c /= cambio; + m.set(F_CORRVALUTA, c.string()); + } + } + } + + if (key == K_ENTER) + { + const TString16 im(m.get(F_IMPONIBILI)); + const char* cl = f.get(); + if (im != cl) + warning_box("Il corrispettivo in lire e' diverso dal totale degli imponibili"); + } + + return TRUE; +} + +// Handler of F_CORRVALUTA +// Certified 99% +bool TPrimanota_application::corrvaluta_handler(TMask_field& f, KEY key) +{ + if (key == K_TAB && f.focusdirty()) + { + TMask& m = f.mask(); + if (m.get(F_CORRLIRE).empty()) + { + const real cambio = m.get(F_CAMBIOINTRA); + if (cambio != ZERO) + { + real c = f.get(); + c *= cambio; + m.set(F_CORRLIRE, c.string()); + } + } + } else + if (key == K_ENTER && f.get().empty()) + { + TMask_field& cl = f.mask().field(F_CORRLIRE); + cl.set_dirty(); + cl.on_hit(); + } + + return TRUE; +} + + +bool TPrimanota_application::solaiva_handler(TMask_field& f, KEY key) +{ + if (key == K_SPACE) + { + TMask& m = f.mask(); + const bool anchecg = !m.get_bool(F_SOLAIVA); + + m.show(F_SHEETCG, anchecg); + m.show(F_DARE, anchecg); + m.show(F_AVERE, anchecg); + + if (m.is_running() && anchecg) + { + TSheet_field& iva = app().ivas(); + const int righe = iva.items(); + TProgind pi(righe, "Generazione righe contabilita'", FALSE, TRUE, 16); + + app().cgs().reset(); + app().add_cgs_tot(m); + if (m.get(F_RITFIS).not_empty()) app().add_cgs_rit(TRUE); + if (m.get(F_RITSOC).not_empty()) app().add_cgs_rit(FALSE); + + TToken_string oldrow(128); + for (int i = 0; i < righe; i++) + { + TToken_string& r = iva.row(i); + if (!r.empty_items()) + { + oldrow = r; + r = ""; + iva_notify(iva, i, K_SPACE); + r = oldrow; + iva_notify(iva, i, K_ENTER); + } + pi.setstatus(i+1); + } + app().fill_sheet(m); + app().cgs().force_update(); + m.set_focus(); + } + } + return TRUE; +} + + diff --git a/cg/cg2102.h b/cg/cg2102.h index c80e00bdd..8402566b2 100755 --- a/cg/cg2102.h +++ b/cg/cg2102.h @@ -1,232 +1,232 @@ -#ifndef __CG2102_H -#define __CG2102_H - -#ifndef __RELAPP_H -#include -#endif - -#ifndef __PAGAMENT_H -#include "pagament.h" -#endif - -#ifndef __CGLIB_H -#include "cglib.h" -#endif - -#ifndef __CG2101_H -#include "cg2101.h" -#endif - -#ifndef __CG2103_H -#include "cg2103.h" -#endif - -class TPrimanota_application : public TRelation_application -{ - TMovimentoPN* _rel; - TLocalisamfile* _tabcom; - TLocalisamfile* _tab; - TLocalisamfile* _caus; - TLocalisamfile* _rcaus; - TLocalisamfile* _clifo; - TLocalisamfile* _pcon; - TLocalisamfile* _attiv; - TLocalisamfile* _saldo; - TLocalisamfile* _comuni; - TLocalisamfile* _occas; - TLocalisamfile* _nditte; - TLocalisamfile* _scadenze; - TLocalisamfile* _pagamenti; - - TPagamento* _pag; - - TCausale* _causale; // Causale corrente - TLibro_giornale* _giornale; // Libro giornale corrente - TipoIVA _iva; // Tipo di IVA corrente - bool _ges_val, _ges_sal; // Gestione valuta e saldaconto - bool _num_cli, _num_for; // Riferimento partita allineato a destra - - bool _skip_giornale_check; // Ignora controllo data stampa libro giornale - bool _skip_bollato_check; // Ignora controllo data stampa bollato - - bool _savenew; // Registra e nuovo - short _firstfocus; // Primo campo della maschera a prendere il focus - - bool _iva_showed; // Lo sheet IVA e' gia' stato visualizzato una volta? - - bool _is_saldaconto; // saldaconto si/no (vede parametri e causale) - - TSaldo_agg _saldi; // Saldi da aggiornare - TPartite_array _partite; // Partite coinvolte - - TMask* _msk[4]; // Maschere di query, cg, iva - long _lastreg; // Numero ultima registrazione - int _mode; // Modo maschera corrente - - TBill _conto_ricavo; // Conto di ricavo del clifo - TString_array _pag_rows; - - static bool showpartite_handler(TMask_field& f, KEY k); - static bool speserimb_handler(TMask_field& f, KEY k); - static bool altrespese_handler(TMask_field& f, KEY k); - static bool abbatt_handler(TMask_field& f, KEY k); - static bool abbpass_handler(TMask_field& f, KEY k); - static bool ritprof_handler(TMask_field& f, KEY k); - static bool diffcamb_handler(TMask_field& f, KEY k); - static bool suspended_handler(TMask_field& f, KEY k); - static bool num_handler(TMask_field& f, KEY key); - static bool caus_query_handler(TMask_field& f, KEY key); - static bool caus_modify_handler(TMask_field& f, KEY key); - static bool datareg_handler(TMask_field& f, KEY key); - static bool datacomp_handler(TMask_field& f, KEY key); - static bool data74ter_handler(TMask_field& f, KEY key); - static bool doc_handler(TMask_field& f, KEY key); - static bool protiva_handler(TMask_field& f, KEY key); - static bool clifo_handler(TMask_field& f, KEY key); - static bool totale_handler(TMask_field& f, KEY key); - static bool totdoc_handler(TMask_field& f, KEY key); - static bool ritfis_handler(TMask_field& f, KEY key); - static bool ritsoc_handler(TMask_field& f, KEY key); - static bool main_codiva_handler(TMask_field& f, KEY key); - static bool corrlire_handler(TMask_field& f, KEY key); - static bool corrvaluta_handler(TMask_field& f, KEY key); - static bool occas_code_handler(TMask_field& f, KEY key); - static bool occas_handler(TMask_field& f, KEY key); - static bool solaiva_handler(TMask_field& f, KEY key); - static bool descr_handler(TMask_field& f, KEY k); - - static bool sheet_clifo_handler(TMask_field& f, KEY k); - static bool iva_sottoconto_handler(TMask_field& f, KEY k); - static bool imponibile_handler(TMask_field& f, KEY key); - static bool detrazione_handler(TMask_field& f, KEY key); - static bool codiva_handler(TMask_field& f, KEY key); - static bool imposta_handler(TMask_field& f, KEY key); - static bool dareavere_handler(TMask_field& f, KEY k); - static bool cg_conto_handler(TMask_field& f, KEY key); - static bool codpag_handler(TMask_field& f, KEY key); - - static bool iva_notify(TSheet_field& s, int r, KEY key); - static bool iva_handler(TMask_field& f, KEY key); - static bool cg_notify(TSheet_field& s, int r, KEY key); - static bool cg_handler(TMask_field& f, KEY key); - static bool pag_notify(TSheet_field& s, int r, KEY key); - - void reset_sheet_row(TSheet_field& s, int n); - -protected: // TApplication - virtual void on_firm_change(); - virtual void on_config_change(); - virtual void print(); - -protected: // TRelation_application - virtual bool user_create(); - virtual bool user_destroy(); - virtual bool changing_mask(int mode); - virtual TMask* get_mask(int mode); - virtual TRelation* get_relation() const { return _rel; } - virtual void init_query_mode(TMask& m); - virtual void init_insert_mode(TMask& m); - virtual void init_modify_mode(TMask& m); - virtual bool save_and_new() const; - virtual const char* get_next_key(); - virtual int read(TMask& m); - virtual int write(const TMask& m); - virtual int rewrite(const TMask& m); - virtual bool remove(); - virtual void write_enable(bool) {} - -protected: - void check_saldi(); - void genera_incasso(const char* causimm); - - TMask* load_mask(int n); - TMask& occas_mask() { return *load_mask(3); } - - void mask2rel(const TMask& m); - - TipoIVA iva() const { return _iva; } - char clifo() const { return iva() == iva_vendite ? 'C' : 'F'; } - bool gestione_valuta() const { return _ges_val; } - bool gestione_saldaconto() const { return _ges_sal; } - bool is_saldaconto() const { return _is_saldaconto; } - void set_saldaconto(bool b) { _is_saldaconto = b; } - - void fill_sheet(TMask& m) const; - void init_mask(TMask& m); - - static TipoIVA reg2IVA(const char* registro, int anno); - static TipoIVA cau2IVA(const char* causale, int anno); - static int type2pos(char tipo); - static const real& cod2IVA(const TMask& m); - static real scorpora(real& imponibile, const real& percentuale); - static bool detraibile(TToken_string& row); - static int bill2pos(const TBill& conto, char tipo); - - bool IVA2bill(const TCodiceIVA& iva, TBill& bill); - int bill2contr(const TBill& c, char sezione) const; - int bill_used(const TBill& conto) const; - int det_used(char detraib) const; - TBill& ivas_bill(TBill& tc); - - bool read_caus(const char* cod, int year); - TCausale& causale() { return *_causale; } - TLibro_giornale& giornale() { return *_giornale; } - - bool test_swap(bool ritsoc); - TImporto real2imp(const real& r, char tipo); - real totale_documento(); - - void ivas_pack(); - void cgs_pack(); - bool ci_sono_importi() const; - real calcola_saldo() const; - real calcola_imp() const; - - void add_cgs_tot(TMask& m); - int set_cgs_row(int n, const TImporto& importo, TBill& conto, const char* desc, char tipo); - void set_cgs_imp(int n, const TImporto& importo); - TImporto get_cgs_imp(int n); - bool add_cgs_imp(int n, const TImporto& importo); - bool sub_cgs_imp(int n, const TImporto& importo); - void disable_cgs_cells(int n, char tipo); - - void add_cgs_rit(bool fisc); - void generazione_righe_cg(int r); - - void reset_cgs_row(int n) { reset_sheet_row(cgs(), n); } - void reset_ivas_row(int n) { reset_sheet_row(ivas(), n); } - - TPagamento& pagamento() { CHECK(_pag, "Pagamento nullo"); return *_pag; } - void set_pagamento(const char* c, const char* d); - void reset_pagamento(); - void set_scadenze(TMask& m); - bool read_scadenze(TMask& m); - void write_scadenze(const TMask& m); - - bool edit_partite(int riga); - - bool notify_cgline_deletion(TPartita& partita, long nreg, int numrig); - bool notify_cgline_deletion(int numrig); - - bool notify_edit_pagamento(TPartita& partita, TRectype& new_pag); - - long calcola_m770(int tipo_coll, real& spese, real& compenso, real& iva, real& ritfis); - bool link_m770(); - -public: - TPartite_array& partite() { return _partite; } // Partite editate - int nuovo_pagamento(TPartita& p, int nriga, int rata, int rmov); - bool edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp); - - TSheet_field& cgs() const; - TSheet_field& ivas() const; - TSheet_field& pags() const; - TString_array& pag_rows() { return _pag_rows; } - - TPrimanota_application(); -}; - -inline TPrimanota_application& app() -{ return (TPrimanota_application&)main_app(); } - -#endif +#ifndef __CG2102_H +#define __CG2102_H + +#ifndef __RELAPP_H +#include +#endif + +#ifndef __PAGAMENT_H +#include "pagament.h" +#endif + +#ifndef __CGLIB_H +#include "cglib.h" +#endif + +#ifndef __CG2101_H +#include "cg2101.h" +#endif + +#ifndef __CG2103_H +#include "cg2103.h" +#endif + +class TPrimanota_application : public TRelation_application +{ + TMovimentoPN* _rel; + TLocalisamfile* _tabcom; + TLocalisamfile* _tab; + TLocalisamfile* _caus; + TLocalisamfile* _rcaus; + TLocalisamfile* _clifo; + TLocalisamfile* _pcon; + TLocalisamfile* _attiv; + TLocalisamfile* _saldo; + TLocalisamfile* _comuni; + TLocalisamfile* _occas; + TLocalisamfile* _nditte; + TLocalisamfile* _scadenze; + TLocalisamfile* _pagamenti; + + TPagamento* _pag; + + TCausale* _causale; // Causale corrente + TLibro_giornale* _giornale; // Libro giornale corrente + TipoIVA _iva; // Tipo di IVA corrente + bool _ges_val, _ges_sal; // Gestione valuta e saldaconto + bool _num_cli, _num_for; // Riferimento partita allineato a destra + + bool _skip_giornale_check; // Ignora controllo data stampa libro giornale + bool _skip_bollato_check; // Ignora controllo data stampa bollato + + bool _savenew; // Registra e nuovo + short _firstfocus; // Primo campo della maschera a prendere il focus + + bool _iva_showed; // Lo sheet IVA e' gia' stato visualizzato una volta? + + bool _is_saldaconto; // saldaconto si/no (vede parametri e causale) + + TSaldo_agg _saldi; // Saldi da aggiornare + TPartite_array _partite; // Partite coinvolte + + TMask* _msk[4]; // Maschere di query, cg, iva + long _lastreg; // Numero ultima registrazione + int _mode; // Modo maschera corrente + + TBill _conto_ricavo; // Conto di ricavo del clifo + TString_array _pag_rows; + + static bool showpartite_handler(TMask_field& f, KEY k); + static bool speserimb_handler(TMask_field& f, KEY k); + static bool altrespese_handler(TMask_field& f, KEY k); + static bool abbatt_handler(TMask_field& f, KEY k); + static bool abbpass_handler(TMask_field& f, KEY k); + static bool ritprof_handler(TMask_field& f, KEY k); + static bool diffcamb_handler(TMask_field& f, KEY k); + static bool suspended_handler(TMask_field& f, KEY k); + static bool num_handler(TMask_field& f, KEY key); + static bool caus_query_handler(TMask_field& f, KEY key); + static bool caus_modify_handler(TMask_field& f, KEY key); + static bool datareg_handler(TMask_field& f, KEY key); + static bool datacomp_handler(TMask_field& f, KEY key); + static bool data74ter_handler(TMask_field& f, KEY key); + static bool doc_handler(TMask_field& f, KEY key); + static bool protiva_handler(TMask_field& f, KEY key); + static bool clifo_handler(TMask_field& f, KEY key); + static bool totale_handler(TMask_field& f, KEY key); + static bool totdoc_handler(TMask_field& f, KEY key); + static bool ritfis_handler(TMask_field& f, KEY key); + static bool ritsoc_handler(TMask_field& f, KEY key); + static bool main_codiva_handler(TMask_field& f, KEY key); + static bool corrlire_handler(TMask_field& f, KEY key); + static bool corrvaluta_handler(TMask_field& f, KEY key); + static bool occas_code_handler(TMask_field& f, KEY key); + static bool occas_handler(TMask_field& f, KEY key); + static bool solaiva_handler(TMask_field& f, KEY key); + static bool descr_handler(TMask_field& f, KEY k); + + static bool sheet_clifo_handler(TMask_field& f, KEY k); + static bool iva_sottoconto_handler(TMask_field& f, KEY k); + static bool imponibile_handler(TMask_field& f, KEY key); + static bool detrazione_handler(TMask_field& f, KEY key); + static bool codiva_handler(TMask_field& f, KEY key); + static bool imposta_handler(TMask_field& f, KEY key); + static bool dareavere_handler(TMask_field& f, KEY k); + static bool cg_conto_handler(TMask_field& f, KEY key); + static bool codpag_handler(TMask_field& f, KEY key); + + static bool iva_notify(TSheet_field& s, int r, KEY key); + static bool iva_handler(TMask_field& f, KEY key); + static bool cg_notify(TSheet_field& s, int r, KEY key); + static bool cg_handler(TMask_field& f, KEY key); + static bool pag_notify(TSheet_field& s, int r, KEY key); + + void reset_sheet_row(TSheet_field& s, int n); + +protected: // TApplication + virtual void on_firm_change(); + virtual void on_config_change(); + virtual void print(); + +protected: // TRelation_application + virtual bool user_create(); + virtual bool user_destroy(); + virtual bool changing_mask(int mode); + virtual TMask* get_mask(int mode); + virtual TRelation* get_relation() const { return _rel; } + virtual void init_query_mode(TMask& m); + virtual void init_insert_mode(TMask& m); + virtual void init_modify_mode(TMask& m); + virtual bool save_and_new() const; + virtual const char* get_next_key(); + virtual int read(TMask& m); + virtual int write(const TMask& m); + virtual int rewrite(const TMask& m); + virtual bool remove(); + virtual void write_enable(bool) {} + +protected: + void check_saldi(); + void genera_incasso(const char* causimm); + + TMask* load_mask(int n); + TMask& occas_mask() { return *load_mask(3); } + + void mask2rel(const TMask& m); + + TipoIVA iva() const { return _iva; } + char clifo() const { return iva() == iva_vendite ? 'C' : 'F'; } + bool gestione_valuta() const { return _ges_val; } + bool gestione_saldaconto() const { return _ges_sal; } + bool is_saldaconto() const { return _is_saldaconto; } + void set_saldaconto(bool b) { _is_saldaconto = b; } + + void fill_sheet(TMask& m) const; + void init_mask(TMask& m); + + static TipoIVA reg2IVA(const char* registro, int anno); + static TipoIVA cau2IVA(const char* causale, int anno); + static int type2pos(char tipo); + static const real& cod2IVA(const TMask& m); + static real scorpora(real& imponibile, const real& percentuale); + static bool detraibile(TToken_string& row); + static int bill2pos(const TBill& conto, char tipo); + + bool IVA2bill(const TCodiceIVA& iva, TBill& bill); + int bill2contr(const TBill& c, char sezione) const; + int bill_used(const TBill& conto) const; + int det_used(char detraib) const; + TBill& ivas_bill(TBill& tc); + + bool read_caus(const char* cod, int year); + TCausale& causale() { return *_causale; } + TLibro_giornale& giornale() { return *_giornale; } + + bool test_swap(bool ritsoc); + TImporto real2imp(const real& r, char tipo); + real totale_documento(); + + void ivas_pack(); + void cgs_pack(); + bool ci_sono_importi() const; + real calcola_saldo() const; + real calcola_imp() const; + + void add_cgs_tot(TMask& m); + int set_cgs_row(int n, const TImporto& importo, TBill& conto, const char* desc, char tipo); + void set_cgs_imp(int n, const TImporto& importo); + TImporto get_cgs_imp(int n); + bool add_cgs_imp(int n, const TImporto& importo); + bool sub_cgs_imp(int n, const TImporto& importo); + void disable_cgs_cells(int n, char tipo); + + void add_cgs_rit(bool fisc); + void generazione_righe_cg(int r); + + void reset_cgs_row(int n) { reset_sheet_row(cgs(), n); } + void reset_ivas_row(int n) { reset_sheet_row(ivas(), n); } + + TPagamento& pagamento() { CHECK(_pag, "Pagamento nullo"); return *_pag; } + void set_pagamento(const char* c, const char* d); + void reset_pagamento(); + void set_scadenze(TMask& m); + bool read_scadenze(TMask& m); + void write_scadenze(const TMask& m); + + bool edit_partite(int riga); + + bool notify_cgline_deletion(TPartita& partita, long nreg, int numrig); + bool notify_cgline_deletion(int numrig); + + bool notify_edit_pagamento(TPartita& partita, TRectype& new_pag); + + long calcola_m770(int tipo_coll, real& spese, real& compenso, real& iva, real& ritfis); + bool link_m770(); + +public: + TPartite_array& partite() { return _partite; } // Partite editate + int nuovo_pagamento(TPartita& p, int nriga, int rata, int rmov); + bool edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp); + + TSheet_field& cgs() const; + TSheet_field& ivas() const; + TSheet_field& pags() const; + TString_array& pag_rows() { return _pag_rows; } + + TPrimanota_application(); +}; + +inline TPrimanota_application& app() +{ return (TPrimanota_application&)main_app(); } + +#endif diff --git a/cg/cg2105.cpp b/cg/cg2105.cpp index dbeeb6a04..f2bf00e5b 100755 --- a/cg/cg2105.cpp +++ b/cg/cg2105.cpp @@ -1,677 +1,691 @@ -#include "cg2102.h" // Applicazione di prima nota - -#include "cg2100.h" // Campi maschere prima nota -#include "cg2100p.h" // Campi maschere partite e pagamenti - -#include // Archivio clienti/fornitori -#include // Archivio partite -#include // Archivio scadenze -#include // Archivio pagamenti - -/////////////////////////////////////////////////////////// -// Maschera partite -/////////////////////////////////////////////////////////// - -class TGame_mask : public TMask -{ - const TBill _conto; // Conto fisso - int _riga_partite; - -protected: - static bool annopart_handler(TMask_field& f, KEY k); - static bool numpart_handler(TMask_field& f, KEY k); - static bool partite_notify(TSheet_field& partite, int r, KEY k); - static bool show_all_handler(TMask_field& f, KEY k); - static bool scambio_handler(TMask_field& f, KEY k); - static bool edit_scadenza_handler(TMask_field& f, KEY k); - - void add_importo(TToken_string& s, const TImporto& i) const; - void fill_partite(bool all) const; - -public: - TSheet_field& partite() const { return (TSheet_field&)field(P_PARTITE); } - TSheet_field& scadenze() const { return (TSheet_field&)field(P_SCADENZE); } - const TBill& conto() const { return _conto; } - - TGame_mask(const TBill& bill); - virtual ~TGame_mask() {} -}; - -TGame_mask::TGame_mask(const TBill& bill) - : TMask("cg2100p"), _conto(bill) -{ - const char tipocf[2] = { bill.tipo(), '\0' }; - set(P_TIPOC, tipocf); - set(P_GRUPPO, bill.gruppo()); - set(P_CONTO, bill.conto()); - set(P_SOTTOCONTO, bill.sottoconto()); - set(P_DESCR, ((TBill&)bill).descrizione()); - - set_handler(P_ANNO, annopart_handler); - set_handler(P_NUMERO, numpart_handler); - set_handler(P_SHOWALL, show_all_handler); - set_handler(P_SCAMBIO, scambio_handler); - - partite().set_notify(partite_notify); - scadenze().sheet_mask().set_handler(100, edit_scadenza_handler); -} - -bool TGame_mask::annopart_handler(TMask_field& f, KEY k) -{ - if (k == K_TAB && f.dirty() && f.get().not_empty()) - { - TMask_field& n = f.mask().field(P_NUMERO); - n.set_dirty(); - numpart_handler(n, k); - } - return TRUE; -} - -bool TGame_mask::numpart_handler(TMask_field& f, KEY k) -{ - if (k == K_TAB && f.dirty()) - { - const TGame_mask& m = (const TGame_mask&)f.mask(); - - const int anno = m.get_int(P_ANNO); - const TString16 num = f.get(); - if (anno > 0 && num.not_empty()) - { - TSheet_field& sheet = m.partite(); - for (int i = 0; i < sheet.items(); i++) - { - TToken_string& row = sheet.row(i); - if (anno == row.get_int(0)) // Se corrisponde l'anno e ... - if (num == row.get()) // corrisponde il numero partita ... - { - sheet.select(i); // ... seleziona la partita - partite_notify(sheet, i, K_TAB); // ed esplodi le sue righe - break; - } - } - if (i >= sheet.items()) - f.warning_box("Partita inesistente"); - } - } - return TRUE; -} - -bool TGame_mask::show_all_handler(TMask_field& f, KEY k) -{ - if (k == K_SPACE) - { - const TGame_mask& gm = (const TGame_mask&)f.mask(); - const bool all = f.get().not_empty(); - gm.fill_partite(all); - } - return TRUE; -} - -bool TGame_mask::scambio_handler(TMask_field& f, KEY k) -{ - if (k == K_SPACE) - { - const TGame_mask& gm = (const TGame_mask&)f.mask(); - const TSheet_field& sheet = gm.scadenze(); - sheet.swap_columns(103, 109); - sheet.swap_columns(104, 110); - } - return TRUE; -} - -bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k) -{ - if (k == K_TAB) - { - TGame_mask& gm = (TGame_mask&)partite.mask(); - gm._riga_partite = r; - - TSheet_field& scadenze = gm.scadenze(); - scadenze.destroy(); - - const TBill& zio = gm.conto(); // Conto cliente/fornitore - TToken_string& row = partite.row(r); - const int anno = row.get_int(0); // Anno partita - const TString16 num = row.get(); // Numero partita - gm.set(P_ANNO, anno); // Aggiorna campi di ricerca - gm.set(P_NUMERO, num); - - TPartita* game = app().partite().exist(zio, anno, num); // Cerca la partita tra quelle editate - const bool should_delete_game = (game == NULL); // Ricorda di fare delete - if (should_delete_game) // Se non c'era ... - game = new TPartita(zio, anno, num); // ... creane una temporanea - - const int lastrow = game->last(); - for (int ri = game->first(); ri <= lastrow; ri = game->succ(ri)) - { - const TRiga_partite& riga = game->riga(ri); - for (int ra = 1; ra <= riga.rate(); ra++) - { - const TRiga_scadenze& scad = riga.rata(ra); - TToken_string& row = scadenze.row(-1); - row.add(ri); - row.add(ra); - row.add(riga.get(PART_DATADOC)); - row.add(riga.get(PART_NREG)); - row.add(riga.get(PART_DATAREG)); - row.add(scad.get(SCAD_DATASCAD)); - row.add(scad.get(SCAD_IMPORTO)); - row.add(scad.get_real(SCAD_IMPORTOVAL).string(0, 2)); - row.add(riga.get(PART_DESCR)); - row.add(riga.get(PART_NUMDOC)); - row.add(riga.get(PART_PROTIVA)); - - const TRecord_array& ap = scad.rows_array(); - const int lastp = ap.last_row(); - for (int pa = ap.first_row(); pa <= lastp; pa = ap.succ_row(pa)) - { - const TRiga_partite& rigp = game->riga(pa); - const TRectype& pag = ap.row(pa); - - TToken_string& row = scadenze.row(-1); - row.add(ri); - row.add(ra); - row.add(rigp.get(PART_DATADOC)); - row.add(rigp.get(PART_NREG)); - row.add(rigp.get(PART_DATAREG)); - row.add(scad.get(SCAD_DATASCAD)); - row.add(pag.get_real(SCAD_IMPORTO).string()); - row.add(pag.get_real(SCAD_IMPORTOVAL).string(0, 2)); - row.add(rigp.get(PART_DESCR)); - row.add(rigp.get(PART_NUMDOC)); - row.add(""); - row.add(pa); - } - } - } - scadenze.force_update(); - if (should_delete_game) - delete game; - } - - return TRUE; -} - -bool TGame_mask::edit_scadenza_handler(TMask_field& f, KEY k) -{ - if (k == K_SPACE) - { - TMask& m = f.mask(); - TGame_mask& gm = (TGame_mask&)(m.get_sheet()->mask()); - - const TBill& bill = gm.conto(); - const int anno = gm.get_int(P_ANNO); - const TString16 numero = gm.get(P_NUMERO); - const int nriga = m.get_int(101); - const int nrata = m.get_int(102); - const int rmov = app().cgs().selected()+1; - - CHECK(nriga && nrata, "La riga della scadenza sembra vuota, ma tutti sanno che e' una balla!"); - - int nrigp = m.get_int(112); - if (nrigp == 0) - { - TPartita& game = app().partite().partita(bill, anno, numero); - nrigp = app().nuovo_pagamento(game, nriga, nrata, rmov); - if (nrigp < 1) - return f.error_box("La rata %d e' gia' stata pagata", nrata); - } - else - { - const TMask& cm = app().curr_mask(); - const long cur_reg = cm.get_long(F_NUMREG); - const long nreg = m.get_long(104); - if (cur_reg != nreg) - return f.error_box("Non si possono modificare pagamenti di movimenti diversi dal %ld", - cur_reg); - } - - TPartita& game = app().partite().partita(bill, anno, numero); - const bool dirty = app().edit_pagamento(game, nriga, nrata, nrigp); - - if (dirty) - partite_notify(gm.partite(), gm._riga_partite, K_TAB); - } - return TRUE; -} - - -void TGame_mask::add_importo(TToken_string& s, const TImporto& i) const -{ - if (i.is_zero()) - s.add(""); - else - { - s.add(i.valore().string()); - s << ' ' << i.sezione(); - } -} - -void TGame_mask::fill_partite(bool all) const -{ - TString_array& a = partite().rows_array(); - a.destroy(); - - app().begin_wait(); - - TLocalisamfile partita(LF_PARTITE); - partita.zero(); - if (conto().tipo() > ' ') // Ignora gruppo e conto dei clifo - { - partita.put(PART_TIPOCF, conto().tipo()); - partita.put(PART_SOTTOCONTO, conto().sottoconto()); - } - else conto().put(partita.curr()); // Scrive completamente i conti normali - - const TRectype filter(partita.curr()); // Record campione - - for (int err = partita.read(_isgteq); - err == NOERR && partita.curr() == filter; - err = partita.read(_isgreat)) - { - const int anno = partita.get_int(PART_ANNO); - const TString16 num(partita.get(PART_NUMPART)); - - TPartita* game = NULL; - bool should_delete_game = FALSE; - if (app().partite().exist(conto(), anno, num)) - game = &app().partite().partita(conto(), anno, num); - else - { - game = new TPartita(conto(), anno, num); - should_delete_game = TRUE; - } - - TImporto saldo, doc, pag, imp; - game->calcola_saldo(saldo, doc, pag, imp); - - if (all || !saldo.is_zero()) - { - int riga_fatt = game->prima_fattura(); - if (riga_fatt < 1) riga_fatt = game->first(); // E' un anticipo - - const TRiga_partite& riga = game->riga(riga_fatt); - const TString16 data_doc = riga.get(PART_DATADOC); - const TString16 num_doc = riga.get(PART_NUMDOC); - const char*descr = riga.get(PART_DESCR); - - TToken_string &r = partite().row(-1); // Stringa di lavoro per lo sheet - r.add(anno); - r.add(num); - r.add(data_doc); - r.add(num_doc); - add_importo(r, saldo); - add_importo(r, doc); - add_importo(r, pag); - add_importo(r, imp); - r.add(descr); - } - - if (should_delete_game) - delete game; - - partita.put(PART_NRIGA, 9999); // Forza lettura partita successiva nella prossima read - } - - partite().force_update(); - if (a.items() > 0) - partite_notify(partite(), 0, K_TAB); - else - { - scadenze().destroy(); - scadenze().force_update(); - } - app().end_wait(); -} - -/////////////////////////////////////////////////////////// -// Metodi di prima nota -/////////////////////////////////////////////////////////// - -bool TPrimanota_application::edit_partite(int riga) -{ - TToken_string& cgr = cgs().row(riga); - const TBill b(cgr, 2, 0x3); // Legge il conto della riga selezionata - if (!b.ok()) return FALSE; - - TGame_mask mask(b); // Inizializzazione maschera di selezione partite - mask.run(); - - return TRUE; -} - - -int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int rata, int rmov) -{ - const TRiga_partite& riga_part = partita.riga(nriga); - CHECKD(rata >= 1 && rata <= riga_part.rate(), "Rata errata ", rata); - - TRiga_scadenze& riga_scad = riga_part.rata(rata); - if (riga_scad.pagata()) - return -1; - - TBill conto; partita.conto(conto); // Legge conto principale - - const long numreg = curr_mask().get_long(F_NUMREG); - int nrigp = partita.mov2rig(numreg, rmov); // Cerca riga partita relativa alla riga rmov - - if (nrigp < 1) // Devo creare una nuova riga di partita - { - TRiga_partite& part = partita.nuova_riga(); // Creazione nuova riga vuota - nrigp = part.get_int(PART_NRIGA); - - // Copia dati movimento corrente - part.put(PART_NREG, numreg); // Numero operazione - part.put(PART_NUMRIG, rmov); // Riga su cui ho cliccato - part.put(PART_DATAREG, curr_mask().get(F_DATAREG)); - part.put(PART_DATADOC, curr_mask().get(F_DATADOC)); - part.put(PART_NUMDOC, curr_mask().get(F_NUMDOC)); - part.put(PART_DESCR, curr_mask().get(F_DESCR)); - part.put(PART_CAMBIO, curr_mask().get(S_CAMBIO)); - part.put(PART_DATACAM, curr_mask().get(S_DATACAMBIO)); - - // Copia dati causale corrente - const int tipomov = causale().tipomov(); - part.put(PART_TIPOMOV, tipomov); - part.put(PART_CODCAUS, causale().codice()); - const TRegistro& reg = causale().reg(); - part.put(PART_REG, reg.name()); - part.put(PART_PROTIVA, reg.protocol()); - - // Complesso algoritmo per calcolare la sezione di una nuova riga partita - char sezione = ' '; // Sezione nulla - TBill bill; causale().bill(1, bill); // Legge primo conto causale - if (bill.tipo() == conto.tipo()) // Se il tipo coincide ... - sezione = causale().sezione(1); // ... usa la sezione della causale - - if (sezione <= ' ') // Se non c'e' la sezione bell'e' ch'e' pronta - { - if (tipomov == 1 || tipomov == 5) // calcola in base al tipo movimento e - sezione = (conto.tipo() == 'C') ? 'D' : 'A'; // al tipo cliente/fornitore - else - sezione = (conto.tipo() == 'C') ? 'A' : 'D'; - - if (bill.tipo() != conto.tipo()) // Compensazioni - sezione = (sezione == 'D') ? 'A' : 'D'; // scambia segno - } - part.put(PART_SEZ, sezione); // Memorizza solo la sezione (importi nulli) - } - - TRectype& pagamento = riga_scad.row(nrigp, TRUE); // Crea nuovo pagamento - - int caus = 2; // Calcola riga causale per la contropartita in base al tipo pagamento - switch (riga_scad.get_int(SCAD_TIPOPAG)) - { - case 2: // Tratta - case 7: // Tratta accettata - caus = 3; break; - case 3: // Ricevuta bancaria - caus = 4; break; - case 4: // Cessione - caus = 5; break; - case 5: // Paghero' - caus = 6; break; - case 6: // Fattura di credito - caus = 7; break; - case 1: // Rimessa - case 8: // Rapporti interbancari diretti - case 9: // Bonifico - default: - caus = 2; break; - } - - TBill contro; causale().bill(caus, contro); // Legge conto contropartita - if (contro.empty()) // Se non specificato ... - causale().bill(caus = 1, contro); // ... prende il primo - contro.put(pagamento, TRUE); // Scrive conto contropartita - - if (conto.tipo() > ' ') // Se cliente o fornitore cerca sua banca - { - TRelation cliforel(LF_CLIFO); - cliforel.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF"); - TRectype& clifo = cliforel.lfile().curr(); - - clifo.put(CLI_TIPOCF, conto.tipo()); - clifo.put(CLI_CODCF, conto.codclifo()); - const int err = cliforel.read(); - CHECK(err == NOERR, "Chiss'e' fregato il clifo"); - - pagamento.put(PAGSCA_CODABI, clifo.get(CLI_CODABI)); - pagamento.put(PAGSCA_CODCAB, clifo.get(CLI_CODCAB)); - pagamento.put(PAGSCA_CODAG, cliforel.lfile(LF_CFVEN).get(CLI_CODAG)); - } - pagamento.put(PAGSCA_CODABIPR, riga_scad.get(SCAD_CODABIPR)); - pagamento.put(PAGSCA_CODCABPR, riga_scad.get(SCAD_CODCABPR)); - - return nrigp; -} - -HIDDEN bool importo_handler(TMask_field& f, KEY k) -{ - TMask& m = f.mask(); - - if (k == K_F8) - { - f.set(m.get(S_RESIDUO)); - k = K_TAB; - } - - if (f.to_check(k)) - { - const real i(f.get()); - const real tot(m.get(S_RESIDUO)); - if (i >= tot) - m.set(S_SALDOACC, "S"); - } - - return TRUE; -} - - -bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pag) -{ - const int nriga = new_pag.get_int(PAGSCA_NRIGA); // Riga fattura - const TRiga_partite& parbas = p.riga(nriga); - - const int nrata = new_pag.get_int(PAGSCA_NRATA); // Numero rata - TRiga_scadenze& scaden = parbas.rata(nrata); - - const int nrigp = new_pag.get_int(PAGSCA_NRIGP); // Riga pagamento - const TRectype& old_pag = scaden.row(nrigp); - const TRiga_partite& somma = p.riga(nrigp); - - const char sez = somma.sezione(); // Sezione importo e ritenute - const char controsez = sez == 'A' ? 'D' : 'A'; // Sezione contropartita - - // Aggiornamento contopartita - const TImporto old_importo(controsez, old_pag.get_real(PAGSCA_IMPORTO)); - TBill old_conto; old_conto.get(old_pag, TRUE); - - const TImporto new_importo(controsez, new_pag.get_real(PAGSCA_IMPORTO)); - TBill new_conto; new_conto.get(new_pag, TRUE); - - if (old_importo != new_importo || old_conto != new_conto) - { - const int old_riga = bill2pos(old_conto, 'I'); - if (old_riga >= 0) - sub_cgs_imp(old_riga, old_importo); - - // Importo della contropartita - if (!new_importo.is_zero()) - { - const int new_riga = bill2pos(new_conto, 'I'); - if (new_riga < 0) - set_cgs_row(new_riga, new_importo, new_conto, "", 'I'); - else - add_cgs_imp(new_riga, new_importo); - } - } - - // Aggiornamento ritenute - const real old_ritenute(old_pag.get(PAGSCA_RITENUTE)); - const real new_ritenute(new_pag.get(PAGSCA_RITENUTE)); - const TImporto grow_ritenute(controsez, new_ritenute-old_ritenute); - if (!grow_ritenute.is_zero()) - { - const riga = type2pos('F'); - if (riga < 0) - { - TBill conto_rit; causale().bill(11, conto_rit); - set_cgs_row(riga, grow_ritenute, conto_rit, "", 'F'); - } - else - add_cgs_imp(riga, grow_ritenute); - } - - char old_ap, new_ap; - TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam; - const bool empty = p.modifica_pagamento(new_pag, - old_ap, old_abbuono, new_abbuono, - new_ap, new_abbuono, new_diffcam); - - // Se c'e' differenza negli abbuoni - if (old_abbuono != new_abbuono || old_ap != new_ap) - { - const int riga_contabile = app().cgs().selected(); - if (old_ap != ' ') // Se c'era un abbuono ... - { - const int riga_abb = type2pos(old_ap); - CHECK(riga_abb >= 0, "Chiss'e' fregato gli abbuoni?"); - sub_cgs_imp(riga_abb, old_abbuono); - - // Sottrae l'abbuono con la sezione invertita dalla riga contabile - add_cgs_imp(riga_contabile, old_abbuono); - } - if (new_ap != ' ') // Se ci sono abbuoni - { - const riga_abb = type2pos(new_ap); - if (riga_abb < 0) - { - TBill conto_abb; causale().bill(new_ap == 'A' ? 9 : 8, conto_abb); - app().set_cgs_row(riga_abb, new_abbuono, conto_abb, "", new_ap); - } - else - add_cgs_imp(riga_abb, new_abbuono); - sub_cgs_imp(riga_contabile, new_abbuono); // Aggiunge l'abbuono con la sezione invertita - } - } - - // Se c'e' variazione nella differenza cambi - if (old_diffcam != new_diffcam) - { - const int riga_diffcam = type2pos('C'); - if (!old_diffcam.is_zero()) // Se c'era una differenza cambi - { - CHECK(riga_diffcam >= 0, "Chiss'e' fregato la differenza cambi?"); - sub_cgs_imp(riga_diffcam, old_diffcam); - } - if (!new_diffcam.is_zero()) - { - if (riga_diffcam < 0) - { - TBill conto_diffcam; causale().bill(12, conto_diffcam); - set_cgs_row(riga_diffcam, new_diffcam, conto_diffcam, "", 'C'); - } - else - add_cgs_imp(riga_diffcam, new_diffcam); - } - } - - return empty; -} - - -bool TPrimanota_application::edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) -{ - TMask m("cg2100s"); - m.set_handler(S_IMPORTO, importo_handler); - - const TRiga_partite& parbas = p.riga(nriga); - const TRiga_scadenze& scaden = parbas.rata(nrata); - const TRectype& oldpag = scaden.row(nrigp); - TRiga_partite& somma = p.riga(nrigp); - - const bool in_valuta = scaden.in_valuta(); - m.show(S_IMPORTOVAL_SCAD, in_valuta); - m.show(S_IMPORTOVAL, in_valuta); - - TRelation rel(LF_PAGSCA); // Working relation - rel.lfile().curr() = oldpag; - m.autoload(&rel); // Load current record on mask - - m.set(S_DESCAGG, somma.get(PART_DESCR)); - - // Dati del documento (fattura) che ha generato la scadenza - m.set(S_NUMDOC, parbas.get(PART_NUMDOC)); // Numero documento - m.set(S_DATADOC, parbas.get(PART_DATADOC)); // Data documento - m.set(S_NUMPROT, parbas.get(PART_PROTIVA)); // Protocollo IVA - m.set(S_DESCR, parbas.get(PART_DESCR)); // Descrizione documento - - // Dati della scadenza che ha generato la partita - TReal_field& residuo = (TReal_field&)m.field(S_RESIDUO); - residuo.set_decimals(in_valuta ? 2 : 0); - residuo.set(scaden.residuo().string()); // Residuo da pagare - m.set(S_DATASCAD, scaden.get(SCAD_DATASCAD)); // Data della scadenza - m.set(S_SEZIONE_SCAD, parbas.get(PART_SEZ)); // Sezione della rata - m.set(S_RATA, scaden.get(SCAD_NRATA)); - m.set(S_IMPORTO_SCAD, scaden.get(SCAD_IMPORTO)); // Importo della rata - m.set(S_IMPORTOVAL_SCAD, scaden.get(SCAD_IMPORTOVAL)); // Importo in valuta - - const KEY key = m.run(); - if (key == K_ENTER || key == K_DEL) - { - if (key == K_DEL) - { - m.reset(S_IMPORTO); - m.reset(S_IMPORTOVAL); - m.reset(S_RITENUTE); - } - else - { - somma.put(PART_DESCR, m.get(S_DESCAGG)); // Aggiorna descrizione (comune ai pagamenti) - } - - m.autosave(&rel); - TRectype& new_pag = rel.lfile().curr(); - notify_edit_pagamento(p, new_pag); - } - - return key != K_ESC; -} - -bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg, int numrig) -{ - bool found = FALSE; - - for (int r = partita.last(); r > 0; r = partita.pred(r)) - { - TRiga_partite& part = partita.riga(r); - const long reg = part.get_long(PART_NREG); - if (reg == nreg) // Se la registrazione corrisponde - { - const int num = part.get_int(PART_NUMRIG); - if (numrig > 0) - { - - } - else // numrig == 0 - { - found = TRUE; // usata solo da ::remove - } - } - } - - return found; -} - -bool TPrimanota_application::notify_cgline_deletion(int numrig) -{ - bool found = FALSE; - const long nreg = curr_mask().get_long(F_NUMREG); - _partite.add_reg_num(nreg, 0); - - for (TPartita* game = _partite.first(); game; game = _partite.next()) - found |= notify_cgline_deletion(*game, nreg, numrig); - - return found; -} \ No newline at end of file +#include "cg2102.h" // Applicazione di prima nota + +#include "cg2100.h" // Campi maschere prima nota +#include "cg2100p.h" // Campi maschere partite e pagamenti + +#include // Archivio clienti/fornitori +#include // Archivio partite +#include // Archivio scadenze +#include // Archivio pagamenti + +/////////////////////////////////////////////////////////// +// Maschera partite +/////////////////////////////////////////////////////////// + +class TGame_mask : public TMask +{ + const TBill _conto; // Conto fisso + int _riga_partite; + +protected: + static bool annopart_handler(TMask_field& f, KEY k); + static bool numpart_handler(TMask_field& f, KEY k); + static bool partite_notify(TSheet_field& partite, int r, KEY k); + static bool show_all_handler(TMask_field& f, KEY k); + static bool scambio_handler(TMask_field& f, KEY k); + static bool edit_scadenza_handler(TMask_field& f, KEY k); + + void add_importo(TToken_string& s, const TImporto& i) const; + void fill_partite(bool all) const; + +public: + TSheet_field& partite() const { return (TSheet_field&)field(P_PARTITE); } + TSheet_field& scadenze() const { return (TSheet_field&)field(P_SCADENZE); } + const TBill& conto() const { return _conto; } + + TGame_mask(const TBill& bill); + virtual ~TGame_mask() {} +}; + +TGame_mask::TGame_mask(const TBill& bill) +: TMask("cg2100p"), _conto(bill) +{ + const char tipocf[2] = { bill.tipo(), '\0' }; + set(P_TIPOC, tipocf); + set(P_GRUPPO, bill.gruppo()); + set(P_CONTO, bill.conto()); + set(P_SOTTOCONTO, bill.sottoconto()); + set(P_DESCR, ((TBill&)bill).descrizione()); + + set_handler(P_ANNO, annopart_handler); + set_handler(P_NUMERO, numpart_handler); + set_handler(P_SHOWALL, show_all_handler); + set_handler(P_SCAMBIO, scambio_handler); + + partite().set_notify(partite_notify); + scadenze().sheet_mask().set_handler(100, edit_scadenza_handler); +} + +bool TGame_mask::annopart_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.dirty() && f.get().not_empty()) + { + TMask_field& n = f.mask().field(P_NUMERO); + n.set_dirty(); + numpart_handler(n, k); + } + return TRUE; +} + +bool TGame_mask::numpart_handler(TMask_field& f, KEY k) +{ + if (k == K_TAB && f.dirty()) + { + const TGame_mask& m = (const TGame_mask&)f.mask(); + + const int anno = m.get_int(P_ANNO); + const TString16 num = f.get(); + if (anno > 0 && num.not_empty()) + { + TSheet_field& sheet = m.partite(); + for (int i = 0; i < sheet.items(); i++) + { + TToken_string& row = sheet.row(i); + if (anno == row.get_int(0)) // Se corrisponde l'anno e ... + if (num == row.get()) // corrisponde il numero partita ... + { + sheet.select(i); // ... seleziona la partita + partite_notify(sheet, i, K_TAB); // ed esplodi le sue righe + break; + } + } + if (i >= sheet.items()) + f.warning_box("Partita inesistente"); + } + } + return TRUE; +} + +bool TGame_mask::show_all_handler(TMask_field& f, KEY k) +{ + if (k == K_SPACE) + { + const TGame_mask& gm = (const TGame_mask&)f.mask(); + const bool all = f.get().not_empty(); + gm.fill_partite(all); + } + return TRUE; +} + +bool TGame_mask::scambio_handler(TMask_field& f, KEY k) +{ + if (k == K_SPACE) + { + const TGame_mask& gm = (const TGame_mask&)f.mask(); + const TSheet_field& sheet = gm.scadenze(); + sheet.swap_columns(103, 110); // Scambia colonne + sheet.swap_columns(104, 111); + } + return TRUE; +} + +bool TGame_mask::partite_notify(TSheet_field& partite, int r, KEY k) +{ + if (k == K_TAB) + { + TGame_mask& gm = (TGame_mask&)partite.mask(); + gm._riga_partite = r; + + TSheet_field& scadenze = gm.scadenze(); + scadenze.destroy(); + + const TBill& zio = gm.conto(); // Conto cliente/fornitore + TToken_string& row = partite.row(r); + const int anno = row.get_int(0); // Anno partita + const TString16 num = row.get(); // Numero partita + gm.set(P_ANNO, anno); // Aggiorna campi di ricerca + gm.set(P_NUMERO, num); + + TPartita* game = app().partite().exist(zio, anno, num); // Cerca la partita tra quelle editate + const bool should_delete_game = (game == NULL); // Ricorda di fare delete + if (should_delete_game) // Se non c'era ... + game = new TPartita(zio, anno, num); // ... creane una temporanea + + const int lastrow = game->last(); + for (int ri = game->first(); ri <= lastrow; ri = game->succ(ri)) + { + const TRiga_partite& riga = game->riga(ri); + for (int ra = 1; ra <= riga.rate(); ra++) + { + const TRiga_scadenze& scad = riga.rata(ra); + TToken_string& row = scadenze.row(-1); + row.add(ri); + row.add(ra); + row.add(riga.get(PART_DATADOC)); + row.add(riga.get(PART_NREG)); + row.add(riga.get(PART_DATAREG)); + row.add(scad.get(SCAD_DATASCAD)); + row.add(scad.get(SCAD_IMPORTO)); + row.add(scad.get_real(SCAD_IMPORTOVAL).string(0, 2)); + row.add(riga.get(PART_DESCR)); + row.add(riga.get(PART_NUMDOC)); + row.add(riga.get(PART_PROTIVA)); + + const TRecord_array& ap = scad.rows_array(); + const int lastp = ap.last_row(); + for (int pa = ap.first_row(); pa <= lastp; pa = ap.succ_row(pa)) + { + const TRiga_partite& rigp = game->riga(pa); + const TRectype& pag = ap.row(pa); + + TToken_string& row = scadenze.row(-1); + row.add(ri); + row.add(ra); + row.add(rigp.get(PART_DATADOC)); + row.add(rigp.get(PART_NREG)); + row.add(rigp.get(PART_DATAREG)); + row.add(scad.get(SCAD_DATASCAD)); + row.add(pag.get_real(SCAD_IMPORTO).string()); + row.add(pag.get_real(SCAD_IMPORTOVAL).string(0, 2)); + row.add(rigp.get(PART_DESCR)); + row.add(rigp.get(PART_NUMDOC)); + row.add(""); + row.add(pa); + } + } + } + scadenze.force_update(); + if (should_delete_game) + delete game; + } + + return TRUE; +} + +bool TGame_mask::edit_scadenza_handler(TMask_field& f, KEY k) +{ + if (k == K_SPACE) + { + TMask& m = f.mask(); + TGame_mask& gm = (TGame_mask&)(m.get_sheet()->mask()); + + const TBill& bill = gm.conto(); + const int anno = gm.get_int(P_ANNO); + const TString16 numero = gm.get(P_NUMERO); + const int nriga = m.get_int(101); + const int nrata = m.get_int(102); + const int rmov = app().cgs().selected()+1; + + CHECK(nriga && nrata, "La riga della scadenza sembra vuota, ma tutti sanno che e' una balla!"); + + int nrigp = m.get_int(112); + if (nrigp == 0) + { + TPartita& game = app().partite().partita(bill, anno, numero); + nrigp = app().nuovo_pagamento(game, nriga, nrata, rmov); + if (nrigp < 1) + return f.error_box("La rata %d e' gia' stata pagata", nrata); + } + else + { + const TMask& cm = app().curr_mask(); + const long cur_reg = cm.get_long(F_NUMREG); + const long nreg = m.get_long(104); + if (cur_reg != nreg) + return f.error_box("Non si possono modificare pagamenti di movimenti diversi dal %ld", + cur_reg); + } + + TPartita& game = app().partite().partita(bill, anno, numero); + const bool dirty = app().edit_pagamento(game, nriga, nrata, nrigp); + + if (dirty) + partite_notify(gm.partite(), gm._riga_partite, K_TAB); + } + return TRUE; +} + + +void TGame_mask::add_importo(TToken_string& s, const TImporto& i) const +{ + if (i.is_zero()) + s.add(""); + else + { + s.add(i.valore().string()); + s << ' ' << i.sezione(); + } +} + +void TGame_mask::fill_partite(bool all) const +{ + TString_array& a = partite().rows_array(); + a.destroy(); + + app().begin_wait(); + + TLocalisamfile partita(LF_PARTITE); + partita.zero(); + if (conto().tipo() > ' ') // Ignora gruppo e conto dei clifo + { + partita.put(PART_TIPOCF, conto().tipo()); + partita.put(PART_SOTTOCONTO, conto().sottoconto()); + } + else conto().put(partita.curr()); // Scrive completamente i conti normali + + const TRectype filter(partita.curr()); // Record campione + + for (int err = partita.read(_isgteq); + err == NOERR && partita.curr() == filter; + err = partita.read(_isgreat)) + { + const int anno = partita.get_int(PART_ANNO); + const TString16 num(partita.get(PART_NUMPART)); + + TPartita* game = NULL; + bool should_delete_game = FALSE; + if (app().partite().exist(conto(), anno, num)) + game = &app().partite().partita(conto(), anno, num); + else + { + game = new TPartita(conto(), anno, num); + should_delete_game = TRUE; + } + + TImporto saldo, doc, pag, imp; + game->calcola_saldo(saldo, doc, pag, imp); + + if (all || !saldo.is_zero()) + { + int riga_fatt = game->prima_fattura(); + if (riga_fatt < 1) riga_fatt = game->first(); // E' un anticipo + + const TRiga_partite& riga = game->riga(riga_fatt); + const TString16 data_doc = riga.get(PART_DATADOC); + const TString16 num_doc = riga.get(PART_NUMDOC); + const char*descr = riga.get(PART_DESCR); + + TToken_string &r = partite().row(-1); // Stringa di lavoro per lo sheet + r.add(anno); + r.add(num); + r.add(data_doc); + r.add(num_doc); + add_importo(r, saldo); + add_importo(r, doc); + add_importo(r, pag); + add_importo(r, imp); + r.add(descr); + } + + if (should_delete_game) + delete game; + + partita.put(PART_NRIGA, 9999); // Forza lettura partita successiva nella prossima read + } + + partite().force_update(); + if (a.items() > 0) + partite_notify(partite(), 0, K_TAB); + else + { + scadenze().destroy(); + scadenze().force_update(); + } + app().end_wait(); +} + +/////////////////////////////////////////////////////////// +// Metodi di prima nota +/////////////////////////////////////////////////////////// + +bool TPrimanota_application::edit_partite(int riga) +{ + TToken_string& cgr = cgs().row(riga); + const TBill b(cgr, 2, 0x3); // Legge il conto della riga selezionata + if (!b.ok()) return FALSE; + + TGame_mask mask(b); // Inizializzazione maschera di selezione partite + mask.run(); + + return TRUE; +} + + +int TPrimanota_application::nuovo_pagamento(TPartita& partita, int nriga, int rata, int rmov) +{ + const TRiga_partite& riga_part = partita.riga(nriga); + CHECKD(rata >= 1 && rata <= riga_part.rate(), "Rata errata ", rata); + + TRiga_scadenze& riga_scad = riga_part.rata(rata); + if (riga_scad.pagata()) + return -1; + + TBill conto; partita.conto(conto); // Legge conto principale + + const long numreg = curr_mask().get_long(F_NUMREG); + int nrigp = partita.mov2rig(numreg, rmov); // Cerca riga partita relativa alla riga rmov + + if (nrigp < 1) // Devo creare una nuova riga di partita + { + TRiga_partite& part = partita.nuova_riga(); // Creazione nuova riga vuota + nrigp = part.get_int(PART_NRIGA); + + // Copia dati movimento corrente + part.put(PART_NREG, numreg); // Numero operazione + part.put(PART_NUMRIG, rmov); // Riga su cui ho cliccato + part.put(PART_DATAREG, curr_mask().get(F_DATAREG)); + part.put(PART_DATADOC, curr_mask().get(F_DATADOC)); + part.put(PART_NUMDOC, curr_mask().get(F_NUMDOC)); + part.put(PART_DESCR, curr_mask().get(F_DESCR)); + part.put(PART_CAMBIO, curr_mask().get(S_CAMBIO)); + part.put(PART_DATACAM, curr_mask().get(S_DATACAMBIO)); + + // Copia dati causale corrente + const int tipomov = causale().tipomov(); + part.put(PART_TIPOMOV, tipomov); + part.put(PART_CODCAUS, causale().codice()); + const TRegistro& reg = causale().reg(); + part.put(PART_REG, reg.name()); + part.put(PART_PROTIVA, reg.protocol()); + + // Complesso algoritmo per calcolare la sezione di una nuova riga partita + char sezione = ' '; // Sezione nulla + TBill bill; causale().bill(1, bill); // Legge primo conto causale + if (bill.tipo() == conto.tipo()) // Se il tipo coincide ... + sezione = causale().sezione(1); // ... usa la sezione della causale + + if (sezione <= ' ') // Se non c'e' la sezione bell'e' ch'e' pronta + { + if (tipomov == 1 || tipomov == 5) // calcola in base al tipo movimento e + sezione = (conto.tipo() == 'C') ? 'D' : 'A'; // al tipo cliente/fornitore + else + sezione = (conto.tipo() == 'C') ? 'A' : 'D'; + + if (bill.tipo() != conto.tipo()) // Compensazioni + sezione = (sezione == 'D') ? 'A' : 'D'; // scambia segno + } + part.put(PART_SEZ, sezione); // Memorizza solo la sezione (importi nulli) + } + + TRectype& pagamento = riga_scad.row(nrigp, TRUE); // Crea nuovo pagamento + + int caus = 2; // Calcola riga causale per la contropartita in base al tipo pagamento + switch (riga_scad.get_int(SCAD_TIPOPAG)) + { + case 2: // Tratta + case 7: // Tratta accettata + caus = 3; break; + case 3: // Ricevuta bancaria + caus = 4; break; + case 4: // Cessione + caus = 5; break; + case 5: // Paghero' + caus = 6; break; + case 6: // Fattura di credito + caus = 7; break; + case 1: // Rimessa + case 8: // Rapporti interbancari diretti + case 9: // Bonifico + default: + caus = 2; break; + } + + TBill contro; causale().bill(caus, contro); // Legge conto contropartita + if (contro.empty()) // Se non specificato ... + causale().bill(caus = 1, contro); // ... prende il primo + contro.put(pagamento, TRUE); // Scrive conto contropartita + + if (conto.tipo() > ' ') // Se cliente o fornitore cerca sua banca + { + TRelation cliforel(LF_CLIFO); + cliforel.add(LF_CFVEN, "TIPOCF=TIPOCF|CODCF=CODCF"); + TRectype& clifo = cliforel.lfile().curr(); + + clifo.put(CLI_TIPOCF, conto.tipo()); + clifo.put(CLI_CODCF, conto.codclifo()); + const int err = cliforel.read(); + CHECK(err == NOERR, "Chiss'e' fregato il clifo"); + + pagamento.put(PAGSCA_CODABI, clifo.get(CLI_CODABI)); + pagamento.put(PAGSCA_CODCAB, clifo.get(CLI_CODCAB)); + pagamento.put(PAGSCA_CODAG, cliforel.lfile(LF_CFVEN).get(CLI_CODAG)); + } + pagamento.put(PAGSCA_CODABIPR, riga_scad.get(SCAD_CODABIPR)); + pagamento.put(PAGSCA_CODCABPR, riga_scad.get(SCAD_CODCABPR)); + + return nrigp; +} + +HIDDEN bool importo_handler(TMask_field& f, KEY k) +{ + TMask& m = f.mask(); + + if (k == K_F8) + { + f.set(m.get(S_RESIDUO)); + k = K_TAB; + } + + if (f.to_check(k)) + { + const real i(f.get()); + const real tot(m.get(S_RESIDUO)); + if (i >= tot) + m.set(S_SALDOACC, "S"); + } + + return TRUE; +} + + +bool TPrimanota_application::notify_edit_pagamento(TPartita& p, TRectype& new_pag) +{ + const int nriga = new_pag.get_int(PAGSCA_NRIGA); // Riga fattura + const TRiga_partite& parbas = p.riga(nriga); + + const int nrata = new_pag.get_int(PAGSCA_NRATA); // Numero rata + TRiga_scadenze& scaden = parbas.rata(nrata); + + const int nrigp = new_pag.get_int(PAGSCA_NRIGP); // Riga pagamento + const TRectype& old_pag = scaden.row(nrigp); + const TRiga_partite& somma = p.riga(nrigp); + + const char sez = somma.sezione(); // Sezione importo e ritenute + const char controsez = sez == 'A' ? 'D' : 'A'; // Sezione contropartita + + // Aggiornamento contopartita + const TImporto old_importo(controsez, old_pag.get_real(PAGSCA_IMPORTO)); + TBill old_conto; old_conto.get(old_pag, TRUE); + + const TImporto new_importo(controsez, new_pag.get_real(PAGSCA_IMPORTO)); + TBill new_conto; new_conto.get(new_pag, TRUE); + + if (old_importo != new_importo || old_conto != new_conto) + { + const int old_riga = bill2pos(old_conto, 'I'); + if (old_riga >= 0) + { + const bool empty = sub_cgs_imp(old_riga, old_importo); + if (empty && (new_importo.is_zero() || new_conto != old_conto)) + reset_cgs_row(old_riga); + } + + // Importo della contropartita + if (!new_importo.is_zero()) + { + const int new_riga = bill2pos(new_conto, 'I'); + if (new_riga < 0) + set_cgs_row(new_riga, new_importo, new_conto, "", 'I'); + else + add_cgs_imp(new_riga, new_importo); + } + } + + // Aggiornamento ritenute + const real old_ritenute(old_pag.get(PAGSCA_RITENUTE)); + const real new_ritenute(new_pag.get(PAGSCA_RITENUTE)); + if (old_ritenute != new_ritenute) + { + const TImporto grow_ritenute(controsez, new_ritenute-old_ritenute); + const riga = type2pos('F'); + if (riga < 0) + { + TBill conto_rit; causale().bill(11, conto_rit); + set_cgs_row(riga, grow_ritenute, conto_rit, "", 'F'); + } + else + { + const bool empty = add_cgs_imp(riga, grow_ritenute); + if (empty) reset_cgs_row(riga); + } + } + + char old_ap, new_ap; + TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam; + const bool empty = p.modifica_pagamento(new_pag, + old_ap, old_abbuono, new_abbuono, + new_ap, new_abbuono, new_diffcam); + + // Se c'e' differenza negli abbuoni + if (old_abbuono != new_abbuono || old_ap != new_ap) + { + const int riga_contabile = app().cgs().selected(); + if (old_ap != ' ') // Se c'era un abbuono ... + { + const int riga_abb = type2pos(old_ap); + CHECK(riga_abb >= 0, "Chiss'e' fregato gli abbuoni?"); + const bool empty = sub_cgs_imp(riga_abb, old_abbuono); + if (empty && new_ap != old_ap) + reset_cgs_row(riga_abb); + + // Sottrae l'abbuono con la sezione invertita dalla riga contabile + add_cgs_imp(riga_contabile, old_abbuono); + } + if (new_ap != ' ') // Se ci sono abbuoni + { + const riga_abb = type2pos(new_ap); + if (riga_abb < 0) + { + TBill conto_abb; causale().bill(new_ap == 'A' ? 9 : 8, conto_abb); + app().set_cgs_row(riga_abb, new_abbuono, conto_abb, "", new_ap); + } + else + add_cgs_imp(riga_abb, new_abbuono); + sub_cgs_imp(riga_contabile, new_abbuono); // Aggiunge l'abbuono con la sezione invertita + } + } + + // Se c'e' variazione nella differenza cambi + if (old_diffcam != new_diffcam) + { + const int riga_diffcam = type2pos('C'); + TImporto grow_diffcam(new_diffcam); grow_diffcam -= old_diffcam; + + if (riga_diffcam < 0) + { + TBill conto_diffcam; causale().bill(12, conto_diffcam); + set_cgs_row(riga_diffcam, grow_diffcam, conto_diffcam, "", 'C'); + } + else + { + const bool empty = add_cgs_imp(riga_diffcam, grow_diffcam); + if (empty) reset_cgs_row(riga_diffcam); + } + } + + return empty; +} + + +bool TPrimanota_application::edit_pagamento(TPartita& p, int nriga, int nrata, int nrigp) +{ + TMask m("cg2100s"); + m.set_handler(S_IMPORTO, importo_handler); + + const TRiga_partite& parbas = p.riga(nriga); + const TRiga_scadenze& scaden = parbas.rata(nrata); + const TRectype& oldpag = scaden.row(nrigp); + TRiga_partite& somma = p.riga(nrigp); + + const bool in_valuta = scaden.in_valuta(); + m.show(S_IMPORTOVAL_SCAD, in_valuta); + m.show(S_IMPORTOVAL, in_valuta); + + TRelation rel(LF_PAGSCA); // Working relation + rel.lfile().curr() = oldpag; + m.autoload(&rel); // Load current record on mask + + m.set(S_DESCAGG, somma.get(PART_DESCR)); + + // Dati del documento (fattura) che ha generato la scadenza + m.set(S_NUMDOC, parbas.get(PART_NUMDOC)); // Numero documento + m.set(S_DATADOC, parbas.get(PART_DATADOC)); // Data documento + m.set(S_NUMPROT, parbas.get(PART_PROTIVA)); // Protocollo IVA + m.set(S_DESCR, parbas.get(PART_DESCR)); // Descrizione documento + + // Dati della scadenza che ha generato la partita + TReal_field& residuo = (TReal_field&)m.field(S_RESIDUO); + residuo.set_decimals(in_valuta ? 2 : 0); + residuo.set(scaden.residuo().string()); // Residuo da pagare + m.set(S_DATASCAD, scaden.get(SCAD_DATASCAD)); // Data della scadenza + m.set(S_SEZIONE_SCAD, parbas.get(PART_SEZ)); // Sezione della rata + m.set(S_RATA, scaden.get(SCAD_NRATA)); + m.set(S_IMPORTO_SCAD, scaden.get(SCAD_IMPORTO)); // Importo della rata + m.set(S_IMPORTOVAL_SCAD, scaden.get(SCAD_IMPORTOVAL)); // Importo in valuta + + const KEY key = m.run(); + if (key == K_ENTER || key == K_DEL) + { + if (key == K_DEL) + { + m.reset(S_IMPORTO); + m.reset(S_IMPORTOVAL); + m.reset(S_RITENUTE); + } + else + { + somma.put(PART_DESCR, m.get(S_DESCAGG)); // Aggiorna descrizione (comune ai pagamenti) + } + + m.autosave(&rel); + TRectype& new_pag = rel.lfile().curr(); + notify_edit_pagamento(p, new_pag); + } + + return key != K_ESC; +} + +bool TPrimanota_application::notify_cgline_deletion(TPartita& partita, long nreg, int numrig) +{ + bool found = FALSE; + + for (int p = partita.last(); p > 0; p = partita.pred(p)) + { + const TRiga_partite& part = partita.riga(p); + if (part.get_int(PART_TIPOMOV) == 1) + { + for (int r = part.rate(); r > 0; r--) + { + const TRiga_scadenze& scad = part.rata(r); + for (int s = scad.last(); s > 0; s = scad.pred(s)) + { + const TRiga_partite& sum = partita.riga(s); + if (sum.get_long(PART_NREG) == nreg && + (numrig == 0 || sum.get_int(PART_NUMRIG) == numrig)) + { + TRectype pag(scad.row(s)); + pag.zero(PAGSCA_IMPORTO); + pag.zero(PAGSCA_IMPORTOVAL); + pag.zero(PAGSCA_RITENUTE); + notify_edit_pagamento(partita, pag); + found = TRUE; + } + } + } + } + } + + return found; +} + +bool TPrimanota_application::notify_cgline_deletion(int numrig) +{ + bool found = FALSE; + const long nreg = curr_mask().get_long(F_NUMREG); + _partite.add_reg_num(nreg, 0); + + for (TPartita* game = _partite.first(); game; game = _partite.next()) + found |= notify_cgline_deletion(*game, nreg, numrig); + + return found; +} diff --git a/cg/cg21cg.uml b/cg/cg21cg.uml index 571a8387f..f49140884 100755 --- a/cg/cg21cg.uml +++ b/cg/cg21cg.uml @@ -1,387 +1,387 @@ -PAGE "RIGA PRIMA NOTA" -1 -1 67 16 - -GROUPBOX DLG_NULL 66 3 -BEGIN - PROMPT 1 1 "Descrizione" -END - -STRING 108 5 -BEGIN - PROMPT 2 2 "" - HELP "Codice della descrizione aggiuntiva della riga" - FLAGS "UZ" - USE %DPN - INPUT CODTAB 108 - DISPLAY "Codice" CODTAB - DISPLAY "Descrizione@50" S0 - INPUT CODTAB 108 - OUTPUT 108 CODTAB - OUTPUT 109 S0 - CHECKTYPE NORMAL -END - -STRING 109 50 -BEGIN - PROMPT 12 2 "" - USE %DPN KEY 2 - INPUT S0 109 - DISPLAY "Descrizione@50" S0 - DISPLAY "Codice" CODTAB - COPY OUTPUT 108 - HELP "Descrizione aggiuntiva della riga" - FIELD DESCR -END - -GROUPBOX DLG_NULL 66 5 -BEGIN - PROMPT 1 4 "Conto principale" -END - -NUMBER 101 15 -BEGIN - PROMPT 2 5 "Dare " - HELP "Importo 'dare' del conto della riga" - FLAGS "RV" - PICTURE "." -END - -NUMBER 102 15 -BEGIN - PROMPT 42 5 "Avere " - HELP "Importo 'avere' del conto della riga" - FLAGS "RV" - PICTURE "." -END - -LIST 103 1 12 -BEGIN - PROMPT 2 6 "Tipo " - HELP "Tipo del conto principale della riga" - FLAGS "U" - ITEM " |Conto" MESSAGE SHOW,106|HIDE,206|HIDE,306|SHOW,107|HIDE,207|HIDE,307 - ITEM "C|Cliente" MESSAGE SHOW,206|HIDE,106|HIDE,306|SHOW,207|HIDE,107|HIDE,307 - ITEM "F|Fornitore" MESSAGE SHOW,306|HIDE,106|HIDE,206|SHOW,307|HIDE,107|HIDE,207 -END - -NUMBER 104 3 -BEGIN - PROMPT 20 6 "Gruppo " - HELP "Codice del conto delle riga" -END - -NUMBER 105 3 -BEGIN - PROMPT 32 6 "Conto " - HELP "Codice del conto delle riga" - FIELD LF_PCON->CONTO - USE LF_PCON SELECT (CONTO!="") && (SOTTOCONTO="") - INPUT GRUPPO 104 - INPUT CONTO 105 - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - DISPLAY "Descrizione@50" DESCR - DISPLAY "Tipo" TMCF - OUTPUT 103 TMCF - OUTPUT 104 GRUPPO - OUTPUT 105 CONTO - OUTPUT 107 DESCR - CHECKTYPE NORMAL - MESSAGE DIRTY,106|DIRTY,206|DIRTY,306 - WARNING "Conto inesistente o mancante sulla riga contabile" -END - -NUMBER 106 6 -BEGIN - PROMPT 45 6 "Sottoconto " - HELP "Codice del conto delle riga" - FIELD LF_PCON->SOTTOCONTO - USE LF_PCON SELECT SOTTOCONTO!="" - INPUT GRUPPO 104 - INPUT CONTO 105 - INPUT SOTTOCONTO 106 - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - DISPLAY "Sottoconto" SOTTOCONTO - DISPLAY "Descrizione@50" DESCR - OUTPUT 106 SOTTOCONTO - OUTPUT 104 GRUPPO - OUTPUT 105 CONTO - OUTPUT 107 DESCR - ADD RUN cg0 -0 - CHECKTYPE NORMAL - WARNING "Sottoconto inesistente sulla riga contabile" -END - -NUMBER 206 6 -BEGIN - PROMPT 45 6 "Cliente " - HELP "Codice del cliente delle riga" - FIELD LF_PCON->SOTTOCONTO - USE LF_CLIFO - INPUT TIPOCF "C" - INPUT CODCF 206 - DISPLAY "Codice" CODCF - DISPLAY "Ragione Sociale Cliente@50" RAGSOC - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - OUTPUT 206 CODCF - OUTPUT 207 RAGSOC - MESSAGE COPY,106 - ADD RUN cg0 -1 C - CHECKTYPE NORMAL - WARNING "Cliente inesistente sulla riga contabile" -END - -NUMBER 306 6 -BEGIN - PROMPT 45 6 "Fornitore " - HELP "Codice del fornitore delle riga" - FIELD LF_PCON->SOTTOCONTO - USE LF_CLIFO - INPUT TIPOCF "F" - INPUT CODCF 306 - DISPLAY "Codice" CODCF - DISPLAY "Ragione Sociale Fornitore@50" RAGSOC - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - OUTPUT 306 CODCF - OUTPUT 307 RAGSOC - MESSAGE COPY,106 - ADD RUN cg0 -1 F - MESSAGE COPY,106 - CHECKTYPE NORMAL - WARNING "Fornitore inesistente sulla riga contabile" -END - -STRING 107 50 -BEGIN - PROMPT 2 7 "Descriz. " - HELP "Descrizione del conto delle riga" - FIELD LF_PCON->DESCR - USE LF_PCON KEY 2 - INPUT DESCR 107 - DISPLAY "Descrizione@50" DESCR - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - DISPLAY "Sottoconto" SOTTOCONTO - COPY OUTPUT 106 - CHECKTYPE NORMAL - WARNING "Sottoconto inesistente o mancante sulla riga contabile" - ADD RUN cg0 -0 -END - -STRING 207 50 -BEGIN - PROMPT 2 7 "Cliente " - HELP "Ragione sociale del cliente delle riga" - FIELD LF_CLIFO->RAGSOC - USE LF_CLIFO KEY 2 - INPUT TIPOCF "C" - INPUT RAGSOC 207 - DISPLAY "Ragione Sociale Cliente@50" RAGSOC - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - DISPLAY "Codice" CODCF - COPY OUTPUT 206 - MESSAGE COPY,107 - ADD RUN cg0 -1 C - CHECKTYPE NORMAL - WARNING "Cliente inesistente sulla riga contabile" -END - -STRING 307 50 -BEGIN - PROMPT 2 7 "Fornitore " - HELP "Ragione sociale del fonitore delle riga" - FIELD LF_PCON->SOTTOCONTO - USE LF_CLIFO KEY 2 - INPUT TIPOCF "F" - INPUT RAGSOC 307 - DISPLAY "Ragione Sociale Fornitore@50" RAGSOC - DISPLAY "Gruppo" GRUPPO - DISPLAY "Conto" CONTO - DISPLAY "Codice" CODCF - COPY OUTPUT 306 - MESSAGE COPY,107 - ADD RUN cg0 -1 F - CHECKTYPE NORMAL - WARNING "Fornitore inesistente sulla riga contabile" -END - -GROUPBOX DLG_NULL 66 4 -BEGIN - PROMPT 1 9 "Contropartita" -END - -LIST 110 1 12 -BEGIN - PROMPT 2 10 "Tipo " - HELP "Tipo del conto di contropartita della riga" - FLAGS "U" - ITEM " |Conto" MESSAGE SHOW,113|HIDE,213|HIDE,313|SHOW,114|HIDE,214|HIDE,314 - ITEM "C|Cliente" MESSAGE SHOW,213|HIDE,113|HIDE,313|SHOW,214|HIDE,114|HIDE,314 - ITEM "F|Fornitore" MESSAGE SHOW,313|HIDE,113|HIDE,213|SHOW,314|HIDE,114|HIDE,214 -END - -NUMBER 111 3 -BEGIN - PROMPT 20 10 "Gruppo " - HELP "Codice del conto di contropartita delle riga" -END - -NUMBER 112 3 -BEGIN - PROMPT 32 10 "Conto " - HELP "Codice del conto di contropartita delle riga" - FIELD LF_PCON->CONTO - COPY USE 105 - INPUT GRUPPO 111 - INPUT CONTO 112 - COPY DISPLAY 105 - OUTPUT 110 TMCF - OUTPUT 111 GRUPPO - OUTPUT 112 CONTO - OUTPUT 114 DESCR - ADD RUN CG0 -0 - MESSAGE DIRTY,113|DIRTY,213|DIRTY,313 - CHECKTYPE NORMAL - VALIDATE REQIF_FUNC 3 113 213 313 -END - -NUMBER 113 6 -BEGIN - PROMPT 45 10 "Sottoconto " - HELP "Codice del conto di contropartita delle riga" - FIELD LF_PCON->SOTTOCONTO - COPY USE 106 - COPY INPUT 112 - INPUT SOTTOCONTO 113 - COPY DISPLAY 106 - OUTPUT 113 SOTTOCONTO - OUTPUT 111 GRUPPO - OUTPUT 112 CONTO - OUTPUT 114 DESCR - CHECKTYPE NORMAL -END - -NUMBER 213 6 -BEGIN - PROMPT 45 10 "Cliente " - HELP "Codice del cliente di contropartita delle riga" - FIELD LF_CLIFO->CODCF - COPY USE 206 - INPUT TIPOCF "C" - INPUT CODCF 213 - COPY DISPLAY 206 - OUTPUT 213 CODCF - OUTPUT 214 RAGSOC - MESSAGE COPY,113 - CHECKTYPE NORMAL -END - -NUMBER 313 6 -BEGIN - PROMPT 45 10 "Fornitore " - HELP "Codice del fornitore di contropartita delle riga" - FIELD LF_CLIFO->CODCF - COPY USE 306 - INPUT TIPOCF "F" - INPUT CODCF 313 - COPY DISPLAY 306 - OUTPUT 313 CODCF - OUTPUT 314 RAGSOC - MESSAGE COPY,113 - CHECKTYPE NORMAL -END - -STRING 114 50 -BEGIN - PROMPT 2 11 "Descriz. " - HELP "Descrizione del conto di contropartita delle riga" - FIELD LF_PCON->DESCR - COPY USE 107 - INPUT DESCR 114 - COPY DISPLAY 107 - COPY OUTPUT 113 - ADD RUN cg0 -0 - WARNING "Conto inesistente sulla riga contabile" -END - -STRING 214 50 -BEGIN - PROMPT 2 11 "Cliente " - HELP "Ragione sociale del cliente di contropartita delle riga" - FIELD LF_CLIFO->RAGSOC - COPY USE 207 - INPUT TIPOCF "C" - INPUT RAGSOC 214 - COPY DISPLAY 207 - COPY OUTPUT 213 - ADD RUN cg0 -1 C - CHECKTYPE NORMAL - WARNING "Cliente inesistente sulla riga contabile" -END - -STRING 314 50 -BEGIN - PROMPT 2 11 "Fornitore " - HELP "Ragione sociale del fornitore di contropartita delle riga" - FIELD LF_CLIFO->RAGSOC - COPY USE 307 - INPUT TIPOCF "F" - INPUT RAGSOC 314 - COPY DISPLAY 307 - COPY OUTPUT 313 - ADD RUN cg0 -1 F - CHECKTYPE NORMAL - WARNING "Fornitore inesistente sulla riga contabile" -END - -NUMBER 115 7 -BEGIN - PROMPT 2 13 "Riga giornale " - FLAGS "D" -END - -LIST 116 20 -BEGIN - PROMPT 30 13 "Tipo riga " - ITEM " |Sola contabilita'" - ITEM "C|Gestione saldaconto" - ITEM "D|IVA detraibile" - ITEM "F|Ritenute fiscali" - ITEM "I|Riga di IVA" - ITEM "K|Riga Cliente/Fornitore" - ITEM "N|IVA non detraibile" - ITEM "S|Ritenute sociali" - ITEM "T|Totale documento" - FLAGS "D" -END - - -BUTTON DLG_OK 9 2 -BEGIN - PROMPT -14 -1 "" -END - -BUTTON DLG_CANCEL 9 2 -BEGIN - PROMPT -24 -1 "" -END - -BUTTON DLG_DELREC 9 2 -BEGIN - PROMPT -34 -1 "Elimina" - MESSAGE EXIT,K_DEL -END - -BUTTON 100 9 2 -BEGIN - PROMPT -44 -1 "Partite" - MESSAGE EXIT,K_DEL -END - - -ENDPAGE - -ENDMASK +PAGE "RIGA PRIMA NOTA" -1 -1 67 16 + +GROUPBOX DLG_NULL 66 3 +BEGIN + PROMPT 1 1 "Descrizione" +END + +STRING 108 5 +BEGIN + PROMPT 2 2 "" + HELP "Codice della descrizione aggiuntiva della riga" + FLAGS "UZ" + USE %DPN + INPUT CODTAB 108 + DISPLAY "Codice" CODTAB + DISPLAY "Descrizione@50" S0 + INPUT CODTAB 108 + OUTPUT 108 CODTAB + OUTPUT 109 S0 + CHECKTYPE NORMAL +END + +STRING 109 50 +BEGIN + PROMPT 12 2 "" + USE %DPN KEY 2 + INPUT S0 109 + DISPLAY "Descrizione@50" S0 + DISPLAY "Codice" CODTAB + COPY OUTPUT 108 + HELP "Descrizione aggiuntiva della riga" + FIELD DESCR +END + +GROUPBOX DLG_NULL 66 5 +BEGIN + PROMPT 1 4 "Conto principale" +END + +NUMBER 101 15 +BEGIN + PROMPT 2 5 "Dare " + HELP "Importo 'dare' del conto della riga" + FLAGS "RV" + PICTURE "." +END + +NUMBER 102 15 +BEGIN + PROMPT 42 5 "Avere " + HELP "Importo 'avere' del conto della riga" + FLAGS "RV" + PICTURE "." +END + +LIST 103 1 12 +BEGIN + PROMPT 2 6 "Tipo " + HELP "Tipo del conto principale della riga" + FLAGS "U" + ITEM " |Conto" MESSAGE SHOW,106|HIDE,206|HIDE,306|SHOW,107|HIDE,207|HIDE,307 + ITEM "C|Cliente" MESSAGE SHOW,206|HIDE,106|HIDE,306|SHOW,207|HIDE,107|HIDE,307 + ITEM "F|Fornitore" MESSAGE SHOW,306|HIDE,106|HIDE,206|SHOW,307|HIDE,107|HIDE,207 +END + +NUMBER 104 3 +BEGIN + PROMPT 20 6 "Gruppo " + HELP "Codice del conto delle riga" +END + +NUMBER 105 3 +BEGIN + PROMPT 32 6 "Conto " + HELP "Codice del conto delle riga" + FIELD LF_PCON->CONTO + USE LF_PCON SELECT (CONTO!="") && (SOTTOCONTO="") + INPUT GRUPPO 104 + INPUT CONTO 105 + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Descrizione@50" DESCR + DISPLAY "Tipo" TMCF + OUTPUT 103 TMCF + OUTPUT 104 GRUPPO + OUTPUT 105 CONTO + OUTPUT 107 DESCR + CHECKTYPE NORMAL + MESSAGE DIRTY,106|DIRTY,206|DIRTY,306 + WARNING "Conto inesistente o mancante sulla riga contabile" +END + +NUMBER 106 6 +BEGIN + PROMPT 45 6 "Sottoconto " + HELP "Codice del conto delle riga" + FIELD LF_PCON->SOTTOCONTO + USE LF_PCON SELECT SOTTOCONTO!="" + INPUT GRUPPO 104 + INPUT CONTO 105 + INPUT SOTTOCONTO 106 + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Sottoconto" SOTTOCONTO + DISPLAY "Descrizione@50" DESCR + OUTPUT 106 SOTTOCONTO + OUTPUT 104 GRUPPO + OUTPUT 105 CONTO + OUTPUT 107 DESCR + ADD RUN cg0 -0 + CHECKTYPE NORMAL + WARNING "Sottoconto inesistente sulla riga contabile" +END + +NUMBER 206 6 +BEGIN + PROMPT 45 6 "Cliente " + HELP "Codice del cliente delle riga" + FIELD LF_PCON->SOTTOCONTO + USE LF_CLIFO + INPUT TIPOCF "C" + INPUT CODCF 206 + DISPLAY "Codice" CODCF + DISPLAY "Ragione Sociale Cliente@50" RAGSOC + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + OUTPUT 206 CODCF + OUTPUT 207 RAGSOC + MESSAGE COPY,106 + ADD RUN cg0 -1 C + CHECKTYPE NORMAL + WARNING "Cliente inesistente sulla riga contabile" +END + +NUMBER 306 6 +BEGIN + PROMPT 45 6 "Fornitore " + HELP "Codice del fornitore delle riga" + FIELD LF_PCON->SOTTOCONTO + USE LF_CLIFO + INPUT TIPOCF "F" + INPUT CODCF 306 + DISPLAY "Codice" CODCF + DISPLAY "Ragione Sociale Fornitore@50" RAGSOC + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + OUTPUT 306 CODCF + OUTPUT 307 RAGSOC + MESSAGE COPY,106 + ADD RUN cg0 -1 F + MESSAGE COPY,106 + CHECKTYPE NORMAL + WARNING "Fornitore inesistente sulla riga contabile" +END + +STRING 107 50 +BEGIN + PROMPT 2 7 "Descriz. " + HELP "Descrizione del conto delle riga" + FIELD LF_PCON->DESCR + USE LF_PCON KEY 2 + INPUT DESCR 107 + DISPLAY "Descrizione@50" DESCR + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Sottoconto" SOTTOCONTO + COPY OUTPUT 106 + CHECKTYPE NORMAL + WARNING "Sottoconto inesistente o mancante sulla riga contabile" + ADD RUN cg0 -0 +END + +STRING 207 50 +BEGIN + PROMPT 2 7 "Cliente " + HELP "Ragione sociale del cliente delle riga" + FIELD LF_CLIFO->RAGSOC + USE LF_CLIFO KEY 2 + INPUT TIPOCF "C" + INPUT RAGSOC 207 + DISPLAY "Ragione Sociale Cliente@50" RAGSOC + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Codice" CODCF + COPY OUTPUT 206 + MESSAGE COPY,107 + ADD RUN cg0 -1 C + CHECKTYPE NORMAL + WARNING "Cliente inesistente sulla riga contabile" +END + +STRING 307 50 +BEGIN + PROMPT 2 7 "Fornitore " + HELP "Ragione sociale del fonitore delle riga" + FIELD LF_PCON->SOTTOCONTO + USE LF_CLIFO KEY 2 + INPUT TIPOCF "F" + INPUT RAGSOC 307 + DISPLAY "Ragione Sociale Fornitore@50" RAGSOC + DISPLAY "Gruppo" GRUPPO + DISPLAY "Conto" CONTO + DISPLAY "Codice" CODCF + COPY OUTPUT 306 + MESSAGE COPY,107 + ADD RUN cg0 -1 F + CHECKTYPE NORMAL + WARNING "Fornitore inesistente sulla riga contabile" +END + +GROUPBOX DLG_NULL 66 4 +BEGIN + PROMPT 1 9 "Contropartita" +END + +LIST 110 1 12 +BEGIN + PROMPT 2 10 "Tipo " + HELP "Tipo del conto di contropartita della riga" + FLAGS "U" + ITEM " |Conto" MESSAGE SHOW,113|HIDE,213|HIDE,313|SHOW,114|HIDE,214|HIDE,314 + ITEM "C|Cliente" MESSAGE SHOW,213|HIDE,113|HIDE,313|SHOW,214|HIDE,114|HIDE,314 + ITEM "F|Fornitore" MESSAGE SHOW,313|HIDE,113|HIDE,213|SHOW,314|HIDE,114|HIDE,214 +END + +NUMBER 111 3 +BEGIN + PROMPT 20 10 "Gruppo " + HELP "Codice del conto di contropartita delle riga" +END + +NUMBER 112 3 +BEGIN + PROMPT 32 10 "Conto " + HELP "Codice del conto di contropartita delle riga" + FIELD LF_PCON->CONTO + COPY USE 105 + INPUT GRUPPO 111 + INPUT CONTO 112 + COPY DISPLAY 105 + OUTPUT 110 TMCF + OUTPUT 111 GRUPPO + OUTPUT 112 CONTO + OUTPUT 114 DESCR + ADD RUN CG0 -0 + MESSAGE DIRTY,113|DIRTY,213|DIRTY,313 + CHECKTYPE NORMAL + VALIDATE REQIF_FUNC 3 113 213 313 +END + +NUMBER 113 6 +BEGIN + PROMPT 45 10 "Sottoconto " + HELP "Codice del conto di contropartita delle riga" + FIELD LF_PCON->SOTTOCONTO + COPY USE 106 + COPY INPUT 112 + INPUT SOTTOCONTO 113 + COPY DISPLAY 106 + OUTPUT 113 SOTTOCONTO + OUTPUT 111 GRUPPO + OUTPUT 112 CONTO + OUTPUT 114 DESCR + CHECKTYPE NORMAL +END + +NUMBER 213 6 +BEGIN + PROMPT 45 10 "Cliente " + HELP "Codice del cliente di contropartita delle riga" + FIELD LF_CLIFO->CODCF + COPY USE 206 + INPUT TIPOCF "C" + INPUT CODCF 213 + COPY DISPLAY 206 + OUTPUT 213 CODCF + OUTPUT 214 RAGSOC + MESSAGE COPY,113 + CHECKTYPE NORMAL +END + +NUMBER 313 6 +BEGIN + PROMPT 45 10 "Fornitore " + HELP "Codice del fornitore di contropartita delle riga" + FIELD LF_CLIFO->CODCF + COPY USE 306 + INPUT TIPOCF "F" + INPUT CODCF 313 + COPY DISPLAY 306 + OUTPUT 313 CODCF + OUTPUT 314 RAGSOC + MESSAGE COPY,113 + CHECKTYPE NORMAL +END + +STRING 114 50 +BEGIN + PROMPT 2 11 "Descriz. " + HELP "Descrizione del conto di contropartita delle riga" + FIELD LF_PCON->DESCR + COPY USE 107 + INPUT DESCR 114 + COPY DISPLAY 107 + COPY OUTPUT 113 + ADD RUN cg0 -0 + WARNING "Conto inesistente sulla riga contabile" +END + +STRING 214 50 +BEGIN + PROMPT 2 11 "Cliente " + HELP "Ragione sociale del cliente di contropartita delle riga" + FIELD LF_CLIFO->RAGSOC + COPY USE 207 + INPUT TIPOCF "C" + INPUT RAGSOC 214 + COPY DISPLAY 207 + COPY OUTPUT 213 + ADD RUN cg0 -1 C + CHECKTYPE NORMAL + WARNING "Cliente inesistente sulla riga contabile" +END + +STRING 314 50 +BEGIN + PROMPT 2 11 "Fornitore " + HELP "Ragione sociale del fornitore di contropartita delle riga" + FIELD LF_CLIFO->RAGSOC + COPY USE 307 + INPUT TIPOCF "F" + INPUT RAGSOC 314 + COPY DISPLAY 307 + COPY OUTPUT 313 + ADD RUN cg0 -1 F + CHECKTYPE NORMAL + WARNING "Fornitore inesistente sulla riga contabile" +END + +NUMBER 115 7 +BEGIN + PROMPT 2 13 "Riga giornale " + FLAGS "D" +END + +LIST 116 20 +BEGIN + PROMPT 30 13 "Tipo riga " + ITEM " |Sola contabilita'" + ITEM "C|Gestione saldaconto" + ITEM "D|IVA detraibile" + ITEM "F|Ritenute fiscali" + ITEM "I|Riga di IVA" + ITEM "K|Riga Cliente/Fornitore" + ITEM "N|IVA non detraibile" + ITEM "S|Ritenute sociali" + ITEM "T|Totale documento" + FLAGS "D" +END + + +BUTTON DLG_OK 9 2 +BEGIN + PROMPT -14 -1 "" +END + +BUTTON DLG_CANCEL 9 2 +BEGIN + PROMPT -24 -1 "" +END + +BUTTON DLG_DELREC 9 2 +BEGIN + PROMPT -34 -1 "Elimina" + MESSAGE EXIT,K_DEL +END + +BUTTON 100 9 2 +BEGIN + PROMPT -44 -1 "Partite" + MESSAGE EXIT,K_DEL +END + + +ENDPAGE + +ENDMASK diff --git a/cg/pagament.cpp b/cg/pagament.cpp index cb2d569eb..df308d23d 100755 --- a/cg/pagament.cpp +++ b/cg/pagament.cpp @@ -1,1796 +1,1806 @@ -#include - -#include "pagament.h" - -#include -#include -#include -#include - -int TPagamento::_rata_ifield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.get_int(f); -} - -real TPagamento::_rata_rfield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return real(t.get(f)); -} - -TDate TPagamento::_rata_dfield(int n, int f) const -{ - TToken_string& t = (TToken_string&)_rate[n]; - return TDate(t.get(f)); -} - -const char* TPagamento::_rata_sfield(int n, int f) const -{ - static char kak[6]; - TToken_string& t = (TToken_string&)_rate[n]; - strcpy(kak,t.get(f)); - return kak; -} - - -bool TPagamento::ratapagata(int n) -{ - TToken_string& t = (TToken_string&)_rate[n]; - return t.items() > 6; -} - - - -void TPagamento::set_intervallo_rate(int in) -{ - _dirty = TRUE; - _int_rate = in; - if (_mcomm && (in % 30) != 0) - _mcomm = FALSE; - for (int i = 0; i < n_rate(); i++) - { - TToken_string& ts = rata(i); - ts.add(i == 0 ? (scad_rata(0) == 0 ? "0" : format("%d",in)) - : format("%d",in), 0); - } -} - -void TPagamento::set_mese_commerciale(bool v, int& sscad) -{ - _dirty = FALSE; - if (_mcomm == v) return; - if (sscad == -1) sscad = 30; - - if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1); - set_intervallo_rate(sscad); - - _mcomm = v; -} - -void TPagamento::set_rate_differenziate(int v) -{ - _dirty = FALSE; - if (!_rdiff && v == 2) return; - - if (v == 2 && (100 % n_rate()) == 0) - { - int p = 100 / n_rate(); - for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(p,1); - } - _rdiff = !(v == 2); - _dirty = TRUE; - } -} - -void TPagamento::set_tipo_prima_rata(int v, int sscad) -{ - _dirty = FALSE; - if (_tpr == v) return; - - if (v < 4 && _tpr > 3) - { - for (int i = n_rate() - 1; i > 0; i--) - { - TToken_string& tt = rata(i); - tt.add(scad_rata(i-1),0); - tt.add(tipo_rata(i-1),2); - tt.add(ulc_rata(i-1),5); - } - _rate.add(NULL,0); - _rate.pack(); - } - else if ( _tpr < 4 && v > 3) - { - TToken_string* ttn = new TToken_string(32); - ttn->add(0,0); - ttn->add(0,1); - ttn->add(1,2); - ttn->add("",3); - ttn->add("",4); - ttn->add("",5); - _rate.insert(ttn,0); - for (int i = 0; i < (n_rate()-1); i++) - { - TToken_string& tt = rata(i); - tt.add(scad_rata(i+1),0); - tt.add(tipo_rata(i+1),2); - tt.add(ulc_rata(i+1),5); - } - } - _tpr = v; - _dirty = TRUE; -} - -void TPagamento::set_numero_rate(int n, int sscad) -{ - _dirty = FALSE; - if (n == 0 || n == n_rate()) return; - - real p = real(100) / real(n); - p.round(2); - int nr = n_rate(); - int first = _tpr < 4 ? 0 : 1; - real sum = 0.0; - - for (int i = first; sum < real(100.0); i++) - { - if ((real(100.0) - sum) < p) - p = real(100.0) - sum; - - sum += p; - - // if necessary add remainder on first one - if ((real(100.0) - sum) /* still */ < p) - { - real prc = perc_rata(first); - prc += real(100.0) - sum; - TToken_string& rt = rata(first); - rt.add(prc.string(),1), - sum = 100; - } - - set_rata(i, real(p), - i == 0 ? (i < nr ? scad_rata(0) : 0): - (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), - (i < nr ? tipo_rata(i) : tipo_rata(nr-1))); - } - // erase remaining - for (; i < nr; i++) - _rate.add(NULL,i); - _rate.pack(); - - _dirty = TRUE; -} - - -void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata) -{ - if (mcomm) - { - int nm = scad / 30; - int ny = nm / 12; - nm %= 12; - - int newm = d.month() + nm; - if (newm > 12) { newm -= 12; ny++; } - - bool last = d.is_end_month() && inizio_scadenza() == 'M'; - - int dy = d.day(); - - // la palla del febbraio & c. - if (rata > 1) - { - TDate oldd(data_rata(rata-2)); - if (oldd.day() > dy) dy = oldd.day(); - } - - d.set_day(1); // il giorno 1 ce l'hanno tutti - d.set_month(newm); - d.set_year(d.year()+ny); - - d.set_end_month(); - if (!last && dy < d.day()) - d.set_day(dy); - } - else - { - d += scad; - } - - // riaggiusta la minchia se ci sono scadenze fissate - if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0) - { - for (int i = 0; i < 3; i++) - { - if (_fixd[i] > d.day()) - { - if (d.last_day(d.month(), d.year()) <= _fixd[i]) - d.set_day(_fixd[i]); - else d.set_end_month(); - break; - } - } - - if (i == 3) - { - if (_fixd[0] > 0 && _fixd[0] < d.day()) - { - d.set_day(_fixd[0]); - d.set_month(d.month() == 12 ? 1 : d.month() + 1); - } - } - - } -} - - -void TPagamento::set_default_type(int type, bool change_existing) -{ - _def_tpr = type; - if (change_existing) - { - for (int i = 0; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(type, 2); - } - _dirty = TRUE; - } -} - -void TPagamento::set_default_ulc(const char* ulc, bool change_existing) -{ - _def_ulc = ulc; - if (change_existing) - { - for (int i = 0; i < n_rate(); i++) - { - TToken_string& tt = rata(i); - tt.add(ulc, 5); - } - _dirty = TRUE; - } -} - -void TPagamento::remove_rata(int i) -{ - // non fa nessun ricalcolo, si limita ad impacchettare se - // necessario - _rate.add(NULL,i); - _rate.pack(); - _dirty = TRUE; -} - -TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc) -{ - TToken_string* tt = new TToken_string(16); - tt->add(day); // scadenza - tt->add(perc.string()); // percentuale - tt->add(type); // tipo - tt->add(""); - tt->add(""); - tt->add(ulc); - _rate.add(tt); - _dirty = TRUE; - return *tt; -} - -TToken_string& TPagamento::set_rata (int index, real perc, int day, int type, - const char* ulc, const char* imp, - const char* data) -{ - TToken_string* tt = (TToken_string*)_rate.objptr(index); - const bool nwr = (tt == NULL); - if (nwr) tt = new TToken_string(16); - - tt->add(day,0); // scadenza - tt->add(perc.string(),1); // percentuale - tt->add(type,2); // tipo - tt->add(data == NULL ? "" : data,3); - tt->add(imp == NULL ? "" : imp,4); - tt->add(ulc == NULL ? "" : ulc,5); - - if (!nwr) - { - if (index > _rate.items()) - { - error_box("Rate non contigue"); - delete tt; - } - } - else - { - _rate.add(tt,index); - _dirty = TRUE; - } - return *tt; -} - -void TPagamento::set_imprata(int i, real r) -{ - TToken_string& tt = (TToken_string&)_rate[i]; - TDate d = _inizio; - - for (int n = 0; n <= i; n++) - next_scad(d, scad_rata(n), _mcomm, n); - - tt.add((const char*)d, 3); - tt.add(r.string(), 4); -} - -TToken_string& TPagamento::set_rata(int index, const real& howmuch, - const TDate& date, int type,const char* ulc, bool pagato) -{ - // calcola percentuali e scadenze a partire dagli importi - TToken_string* tt = (TToken_string*)_rate.objptr(index); - - const bool nwr = (tt == NULL); // nuova rata - - if (nwr) tt = new TToken_string(16); - - TDate oldd = index > 0 ? data_rata(index -1) : _inizio; - int day = date - oldd; - real toshare(_tpr < 4 ? _firstr : _secndr); - real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; - perc *= real(100.0); - perc.round(2); - - tt->add(day,0); // scadenza - tt->add(perc.string(),1); // percentuale - tt->add(type,2); // tipo - tt->add(date.string(),3); - tt->add(howmuch.string(),4); - tt->add(ulc,5); - if (pagato) tt->add("X",6); - - if (!nwr) - { - if (index > _rate.items()) - { - error_box("Rate non contigue"); - delete tt; - } - } - else - { - _rate.add(tt, index); - _dirty = TRUE; - } - return *tt; -} - - - -word TPagamento::validate() const -{ - word res = 0x0000; - real r(0.0); - - int first = _tpr < 4 ? 0 : 1; - real toshare(_tpr < 4 ? _firstr : _secndr); - TDistrib ds(toshare,0); - - // check percentages & prepare slicer - for (int i = first; i < n_rate(); i++) - { - real p(perc_rata(i)); - ds.add(p); - r += p; - } - - if (r != real(100.0)) - res |= P_RSUM; - - - if (_inited) - { - ds.init(toshare); - // check importi rate consistenti con la percentuale - for (int i = first; i < n_rate(); i++) - { - real r1(tpay_rata(i)); - real r2(ds.get()); - if (r1 != r2) - { res |= P_IMPNC; break; } - } - - // check errori date scadenze (se istanziate) - TDate d(data_rata(0)); - if (d < _inizio) - res |= P_INIZIO; - for (i = 1; i < n_rate(); i++) - { - if (data_rata(i) <= d) - { res |= P_SCAD; break; } - d = data_rata(i); - } - } - return res; -} - - -void TPagamento::strerr(word err, TString& s) -{ - s = "Errore:"; - if (err & P_RSUM) - s << "\n Le percentuali non sommano a 100"; - if (err & P_IMPNC) - s << "\n Le percentuali sono inconsistenti con gli importi"; - if (err & P_SCAD) - s << "\n Le scadenze non sono consecutive"; - if (err & P_INIZIO) - s << "\n La prima rata e' antecedente alla data movimento"; -} - -const char* TPagamento::desc_tpr() const -{ - const char* o; - switch (_tpr) - { - case 0: o = "Totale su tutte le rate"; break; - case 1: o = "Tutte le imposte su 1a"; break; - case 2: o = "Tutte le spese su 1a"; break; - case 3: o = "Imposte + spese su 1a"; break; - case 4: o = "Spese + merce su 1a"; break; - case 5: o = "Merce + imposte su 1a"; break; - case 6: o = "Tutta la merce su 1a"; break; - default: o = ""; break; - } - return o; -} - -const char* TPagamento::desc_tipo(int i) const -{ - const char* o; - switch (i) - { - case 1: o = "Rimessa diretta o contanti"; break; - case 2: o = "Tratta"; break; - case 3: o = "Ricevuta bancaria"; break; - case 4: o = "Cessione"; break; - case 5: o = "Paghero'"; break; - case 6: o = "Lettera di credito"; break; - case 7: o = "Tratta accettata"; break; - case 8: o = "Rapporti interbancari diretti"; break; - case 9: o = "Bonifici"; break; - case 10: o = "Altro pagamento"; break; - } - return o; -} - -word TPagamento::recalc_rate(int row, bool is_perc_modified, - const char* new_value, const char* scad, - const char* typ, int rdiff, bool mcomm, - bool& need_recalc) - // ricalcola le rate sulla base di parametri modificati sulla riga row - // parametri: tutti i const char* possono essere NULL, il che vuol dire - // che i dati corrispondenti non sono stati modificati; - // se new_value non e' NULL puo' essere la percentuale (e - // allora is_perc_modified e' TRUE) o l'importo. Non e' - // possibile modificare entrambi; se succede viene data - // priorita' alla percentuale. -{ - CHECK(!(!is_perc_modified && new_value != NULL && !_inited), - "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!"); - - if (_rate.items() == 0) return P_OK; - - real rsum(0.0), newv(0.0), rmax(0.0); - int oldtype = tipo_rata(0); - int oldscad = scad_rata(0); - TDate lastdate = data_rata(0); - int first = _tpr < 4 ? 0 : 1; - TArray srate(_rate); // rate come erano - - - if (srate.items() > 1) - { - // calcola defaults per tipo pagamento e scadenza - // nel caso di rate nuove - oldscad = scad_rata(1); - } - - if (oldscad == 0) oldscad = 30; - if (oldtype == 0) oldtype = 1; - - if (new_value != NULL) - { - newv = new_value; - rmax = is_perc_modified? (real) 100.0 : (_tpr < 4 ? _firstr : _secndr); - if (newv > rmax) return P_RSUM; - } - - bool exhausted = FALSE; - - for (int i = first; i < srate.items(); i++) - { - if (i == row) - { - if (typ != NULL) - { - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - tt.add(typ,2); - ss.add(typ,2); - // no error is possible - } - - if (scad != NULL) - { - // if !_inited scad e' il n. giorni, se no e' la rata - if (_inited) - { - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - lastdate = scad; - // controlla errore sulla data scadenza - if (i > 0) - { - oldscad = (int)(lastdate - data_rata(i-1)); - if (oldscad <= 0l) return P_SCAD; - } - else if (lastdate < _inizio) return P_INIZIO; - tt.add(scad,3); - ss.add(scad,3); - // ricalcola rate successive: se si vuole modificarne solo una - // ci si fotte e si disabilita il ricalcolo - TDate ddd (lastdate); - for (int j = row+1; j < srate.items(); j++) - { - TToken_string& tt = rata(j); - TToken_string& ss = (TToken_string&)srate[j]; - next_scad(ddd,scad_rata(j),mcomm,j); - tt.add(ddd.string(),3); - ss.add(ddd.string(),3); - need_recalc = TRUE; - } - } - else - { - // nulla di speciale visto che si memorizza la derivata - int sc = atoi(scad); - for (int i = 0; i < row; i ++) - sc -= scad_rata(i); - if (sc < 0 || (row > 0 && sc == 0)) return P_SCAD; - if (_mcomm && (sc % 30) != 0) _mcomm = FALSE; - TToken_string& tt = rata(row); - TToken_string& ss = (TToken_string&)srate[row]; - tt.add(sc,0); - ss.add(sc,0); - need_recalc = TRUE; - } - } - - // here's the bell - if (new_value != NULL) - { - if (newv == ZERO || (rsum+newv) > rmax) - return P_RSUM; - // did not sforate - rsum += newv; - TToken_string& rt = rata(row); - // setta nuovo valore e ricalcola cio' che ne consegue - if (is_perc_modified) rt.add(new_value,1); - else rt.add(new_value,4); - // riaggiusta le rate rimanenti - real remainder(0.0); remainder = rmax - rsum; - if (!(exhausted = (remainder == real(0.0)))) - { - // se inited e scelto UGUALI (2) occorre dividere in N e - // aggiungere il resto sulla 1a rata - // controlla se rdiff e' compatibile con - // i dati e se e' il caso riaggiusta - if (rdiff == 3 && !((remainder % newv.integer()) == ZERO)) - rdiff = 2; -// *** 10/8/95: se uguali e non e' multiplo intero lo teniamo cosi' e poi -// *** aggiungiamo alla prima rata utile -// if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) -// rdiff = 1; - _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4); - - // procedi - if (rdiff == 1) - { - // cancella tutte le rate successive, aggiungi un'unica rata - // con il resto dell'importo - if (row < (srate.items()-1)) - { - TToken_string& trt = rata(row+1); - trt.add(remainder.string(), is_perc_modified ? 1 : 4); - for(int j = row+2; j < srate.items(); j++) - _rate.add(NULL,j); - } - else - { - // l'importante e' esagerare - for(int j = row+1; j < srate.items(); j++) - _rate.add(NULL,j); - - TToken_string& trt = add_rata(is_perc_modified ? remainder : (real) 0.0, - oldscad, oldtype); - if (!is_perc_modified) trt.add(remainder.string(),4); - if (_inited) - { - TDate dd = data_rata(row); - next_scad(dd,oldscad,mcomm,row); - trt.add(dd.string(),3); - } - } - } - else // rate non differenziate (dall'inizio o da row) - { - // ripartisci l'importo nel numero necessario di rate per - // mantenere costante il valore - real sum(0.0); - if (_inited) lastdate = data_rata(rdiff == 2 ? first : row); - - TDate dd(lastdate); - int type = oldtype; - int nscd = oldscad; - - int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; - real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; - - // cancelliamo tutto, va' - for (int j = frs; j < srate.items(); j++) - _rate.add(NULL,j); - - if (rdiff != 4) - for (j = frs; sum < mx; j++) - { - // TBI: qui mod se rdiff == 2 - // se c'e' la vecchia rata si tengono i parametri - // altrimenti si calcolano - if (j < srate.items()) - { - TToken_string& trt = (TToken_string&)srate[j]; - if (_inited) dd = trt.get(3); - type = atoi(trt.get(2)); - nscd = j == 0 ? 0 : atoi(trt.get(0)); - if (type == 0) type = 1; - if (j > 0 && nscd == 0) nscd = oldscad; - if (_inited && dd == lastdate && j > 0) - next_scad(dd,nscd,mcomm,j); - } - else if (_inited) - { - if (dd <= botime) dd = lastdate; - next_scad(dd,nscd,mcomm,j); - } - else nscd = _int_rate; - - TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, - nscd, type); - if (_inited) - ttr.add(dd.string(), 3); - if (!is_perc_modified) - { - ttr.add(newv.string(),4); - } - if ((mx - sum) < newv) - { - // add remainder on first rate - newv += (mx - sum); - if (!is_perc_modified) - set_imprata(frs, newv); - else { - TToken_string& t = rata(frs); - t.add(newv.string(), 1); - } - remove_rata(j); - break; - } -// } - sum += newv; - } - else // rdiff == 4; uguali finche' possibile - { - bool basta = FALSE; - for (j = frs; ; j++) - { - // ultima rata puo' differire dalle precedenti - if (mx - sum <= newv) - { - newv = mx - sum; - basta = TRUE; - } - // se c'e' la vecchia rata si tengono i parametri - // altrimenti si calcolano - if (j < srate.items()) - { - TToken_string& trt = (TToken_string&)srate[j]; - if (_inited) dd = trt.get(3); - type = atoi(trt.get(2)); - nscd = j == 0 ? 0 : atoi(trt.get(0)); - if (type == 0) type = 1; - if (j > 0 && nscd == 0) nscd = oldscad; - if (_inited && dd == lastdate && j > 0) - next_scad(dd,nscd,mcomm,j); - } - else if (_inited) next_scad(dd,nscd,mcomm,j); - - TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, - nscd, type); - if (_inited) - ttr.add(dd.string(), 3); - if (!is_perc_modified) - ttr.add(newv.string(),4); - if (basta) break; - sum += newv; - } - } - } - - } - else // exhausted - { - for(int j = row+1; j < srate.items(); j++) - _rate.add(NULL,j); - } - - - if (_inited) - { - // ricalcola il valore secondario (non modificato) - real toshare(100.0); - if (is_perc_modified) - toshare = (_tpr < 4 ? _firstr : _secndr); - TDistrib dt(toshare, is_perc_modified ? _round : 3); - - for (int j = first; j < _rate.items(); j++) - { - real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); - real zpx = rvl/rmax; // percentuale - dt.add(zpx); - } - for (j = first; j < _rate.items(); j++) - { - TToken_string& tr = rata(j); - real rvl = dt.get(); - tr.add(rvl.string(), is_perc_modified ? 4 : 1); - } - - // se e' il caso aggiungi l'importo fisso sulla prima rata - if (_inited && _tpr > 0 && _tpr < 4) - { - TToken_string& tr = rata(0); - real tot = tpay_rata(0) + _firstr; - tr.add(tot.string(), 4); - } - - } - - need_recalc = TRUE; - return P_OK; - } // new_value != NULL - } - else // i != row modified - { - if (i > 0 && !((perc_rata(i-1) == perc_rata(i)))) - { - if (rdiff == 2) rdiff = 1; - _rdiff = FALSE; - } - if (is_perc_modified) - rsum += perc_rata(i); - else - rsum += tpay_rata(i); - - lastdate = data_rata(i); - oldtype = tipo_rata(i); - oldscad = scad_rata(i); - if (_inited && i > 0) - { - if (data_rata(i) <= data_rata(i-1)) - return P_SCAD; - } - else if (lastdate < _inizio) - return P_INIZIO; - } - } - - return P_OK; -} - - -bool TPagamento::read(TTable* t, TTable* r) -{ - // puo' chiamarla chiunque - bool istnew = FALSE; - if (t == NULL) - { - t = new TTable("%CPG"); - istnew = TRUE; - } - t->zero(); t->put("CODTAB",_code); - if (t->read() != NOERR) return FALSE; - - // set everything - _rdiff = t->get_bool("B1"); - _mcomm = t->get_bool("B0"); - _tpr = atoi(t->get("S3")); - _inscad = *((const char*)(t->get("S1"))); - _code = t->get("CODTAB"); - _name = t->get("S0"); - _fixd[0] = t->get_int("I0"); - _fixd[1] = t->get_int("I1"); - _fixd[2] = t->get_int("I2"); - - // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc. - if (_inscad == 'M') - { - if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30); - else _inizio.set_end_month(); - } - else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) - _inizio.set_month(30); - - // leggi rate e scadenze - bool isrnew = FALSE; - if (r == NULL) - { - r = new TTable("%RPG"); - isrnew = TRUE; - } - TString s(16); - - for (int i = 0; ;i++) - { - r->zero(); s.format("%s%3d",(const char*)_code, i); - r->put("CODTAB", (const char*)s); - if (r->read() != NOERR) break; - TToken_string* tt = new TToken_string(16); - tt->add((const char*)(r->get("I0"))); // scadenza - tt->add((const char*)(r->get("R0"))); // percentuale - tt->add((const char*)(r->get("I1"))); // tipo - // data e importo - TDate d = _inizio; - next_scad(d,(int)(r->get_long("I0")),_mcomm,i); - tt->add((const char*)d); - tt->add(""); - tt->add(r->get("S1")); - _slicer.add((real)r->get("R0")); - _rate.add(tt); - } - - if (istnew) delete t; - if (isrnew) delete r; - - return TRUE; -} - - -int TPagamento::write(TTable& r) -{ - // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una - // relapp, che ha scritto il file principale - - TString s(16); int err = NOERR; - for (int i = 0; err == NOERR && i < n_rate(); i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - r.put("I0", (long)scad_rata(i)); - r.put("R0", perc_rata(i).string()); - r.put("I1", (long)tipo_rata(i)); - r.put("S1", ulc_rata(i)); - err = r.write(); - } - return err; -} - -int TPagamento::rewrite(TTable& r) -{ - TString s(16); int err = NOERR; - for (int i = 0; err == NOERR && i < n_rate(); i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - bool was = (r.read() == NOERR); - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - r.put("I0", (long)scad_rata(i)); - r.put("R0", perc_rata(i).string()); - r.put("I1", (long)tipo_rata(i)); - r.put("S1", ulc_rata(i)); - err = (was ? r.rewrite() : r.write()); - } - // erase possible rates > current n. rates - for (;err == NOERR;i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - if (r.read() == NOERR) err = r.remove(); - else break; - } - return err; -} - -int TPagamento::remove(TTable& r) -{ - TString s(16); int err = NOERR; - for (int i = 0 ; err == NOERR; i++) - { - r.zero(); s.format("%s%3d",(const char*)_code, i); - r.put("CODTAB", (const char*)s); - if (r.read() == NOERR) err = r.remove(); - else break; - } - return err; -} - -void TPagamento::set_rate_auto() -{ - // vedi rate esistenti e tipo prima rata - // deve fare riferimento ad un tipo pagamento esistente - // e sensato - int first = 0; - - real toslice = _firstr; - - if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1)) return; - if (_tpr > 3) // ripartisci _firstr su tutte le rate - { - first = 1; - toslice = _secndr; - } - - _slicer.init(toslice); - - if (_tpr > 3) - // prima rata obbligatoria - set_imprata(0, _firstr); - - // se rate uguali dividi l'importo totale per il numero di rate - real r1(0.0), ro(0.0); - if (!_rdiff) - { - int rut = _tpr > 3 ? n_rate() - 1 : n_rate(); - ro = toslice/real(rut); ro.trunc(_round); - r1 = ro + (toslice - (ro*real(rut))); - } - - for (int i = first; i < n_rate(); i++) - // setta le fette e le date di scadenza - set_imprata(i, _rdiff ? _slicer.get() : (i == first ? r1 : ro)); - - // se e' nei primi tre casi, si somma l'importo da non dividere alla - // prima rata - if (_tpr > 0 && _tpr < 4) - set_imprata(0, tpay_rata(0) + _firstr); -} - - - -void TPagamento::set_total(const real& imponibile, const real& imposta, const real& spese) -{ - _imponibile = imponibile; - _imposta = imposta; - _spese = spese; - _inited = TRUE; - - // istanzia _firstr e _secndr a seconda di _tpr - switch(_tpr) - { - case 0: - _firstr = _imponibile + _imposta + _spese; - _secndr = 0.0; - break; - case 1: - _firstr = _imposta; - _secndr = _imponibile + _spese; - break; - case 2: - _firstr = _spese; - _secndr = _imposta + _imponibile; - break; - case 3: - _firstr = _imposta + _spese; - _secndr = _imponibile; - break; - case 4: - _firstr = _spese + _imponibile; - _secndr = _imposta; - break; - case 5: - _firstr = _imponibile + _imposta; - _secndr = _spese; - break; - case 6: - _firstr = _imponibile; - _secndr = _imposta + _spese; - break; - } - - real toslice = _tpr > 1 ? _secndr : _firstr; - - _slicer.init(toslice, TRUE); - - for (int i = 0; i < _rate.items(); i++) - { - TToken_string& t = (TToken_string&)_rate[i]; - real rr(t.get(1)); - _slicer.add(rr); - } -} - - -void TPagamento::set_sheet(TSheet_field& sf, int sscad) -{ - sf.destroy(-1); - if (_inited && _rate.items() > 0) - { - // si istanzia uno sheet di primanota - for (int i = 0; i < n_rate(); i++) - { - TToken_string& ts = sf.row(-1); - // istanzia, o stronzo - ts.add((const char*)data_rata(i)); - ts.add(perc_rata(i).string()); - ts.add(tpay_rata(i).string()); - ts.add(tipo_rata(i)); - ts.add(desc_tipo(tipo_rata(i))); - if (ratapagata(i)) - { - sf.disable_cell(1,1); // percentuale - sf.disable_cell(1,2); // importo - } - } - } - else if (_rate.items() > 0) // not inited: set edit sheet - { - for (int i = 0, scr = 0; i < n_rate(); i++) - { - TToken_string& s = sf.row(-1); - scr += scad_rata(i); - s.add(scr); - s.add(perc_rata(i).string()); - s.add(tipo_rata(i)); - s.add(desc_tipo(tipo_rata(i))); - s.add(ulc_rata(i)); - } - } - else // new: set with 1 or 2 rates according to tpr - { - if (_tpr > 3) - add_rata(ZERO, sscad == -1 ? 0 : sscad, _def_tpr, _def_ulc); - add_rata(real(100.0), sscad == -1 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc); - - _dirty = TRUE; - - for (int i = 0, scr = 0; i < n_rate(); i++) - { - TToken_string& s = sf.row(-1); - scr += scad_rata(i); - s.add(scr); - s.add(perc_rata(i).string()); - s.add(tipo_rata(i)); - s.add(desc_tipo(tipo_rata(i))); - s.add(ulc_rata(i)); - } - } - if (_tpr > 3) - { - // disabilita campi da non toccare sulla prima rata - if (_inited) - { - sf.disable_cell(0,1); // percentuale - sf.disable_cell(0,2); // importo - } - else - { - sf.disable_cell(0,1); // percentuale - } - } - sf.force_update(); -} - -TPagamento::TPagamento(const char* codtab, const char* data) : -_slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), -_spese(0.0), _code(codtab), _dirty(FALSE), _inited(FALSE), -_def_tpr(1), _def_ulc(""), _round(0), _int_rate(30) -{ - _fixd[0] = _fixd[1] = _fixd[2] = 0; - if (data != NULL) - _inizio = data; - if (_code.blank() || !read()) - _new = TRUE; -// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); -} - - -/////////////////////////////////////////////////////////// -// TTree_rectype -/////////////////////////////////////////////////////////// - -TTree_rectype::TTree_rectype(const TRectype& testa, const TRectype& riga, const char* num) - : TRectype(testa), _recarr(riga, num) -{ -} - -TTree_rectype::TTree_rectype(int testa, int riga, const char* num) - : TRectype(testa), _recarr(riga, num) -{ -} - -TTree_rectype::TTree_rectype(const TTree_rectype& t) - : TRectype(t), _recarr(t._recarr) -{ -} - - -TObject* TTree_rectype::dup() const -{ - TTree_rectype* r = new TTree_rectype(*this); - return r; -} - -void TTree_rectype::copy_key_to_row(TRectype& row) const -{ - const int numkey = 0; // Memento! Gli indici delle chiavi partono da zero! - RecDes* recd = rec_des(); // Descrizione del record della testata - - row.zero(); - for (int i = 0; i < recd->Ky[numkey].NkFields; i++) - { - const KeyDes& kd = recd->Ky[numkey]; - const int nf = kd.FieldSeq[i] % MaxFields; - const RecFieldDes& rf = recd->Fd[nf]; - const char* name = rf.Name; - const TString& val = get(name); - row.put(name, val); - } -} - -int TTree_rectype::fill_array() -{ - TRectype* row = (TRectype*)_recarr.key().dup(); - copy_key_to_row(*row); - const int err = _recarr.read(row); - return err; -} - - -int TTree_rectype::read(TBaseisamfile& f, word op) -{ - int err = TRectype::read(f, op); - if (err == NOERR) - fill_array(); - else - _recarr.destroy_rows(); - return err; -} - -int TTree_rectype::next(TBaseisamfile& f) -{ - int err = TRectype::next(f); - if (err == NOERR) - fill_array(); - else - _recarr.destroy_rows(); - return err; -} - -int TTree_rectype::write(TBaseisamfile& f) const -{ - int err = TRectype::write(f); - if (err == NOERR) - err = _recarr.write(); - return err; -} - -int TTree_rectype::rewrite(TBaseisamfile& f) const -{ - int err = TRectype::rewrite(f); - if (err == NOERR) - err = _recarr.rewrite(); - return err; -} - -int TTree_rectype::remove(TBaseisamfile& f) -{ - int err = TRectype::remove(f); - if (err == NOERR) - err = _recarr.remove(); - return err; -} - - -/////////////////////////////////////////////////////////// -// TRiga_scadenze -/////////////////////////////////////////////////////////// - -TRiga_scadenze::TRiga_scadenze(TRiga_partite* r) - : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP"), _riga(r) -{ - CHECK(_riga, "Riga nulla"); -} - -TRiga_scadenze::TRiga_scadenze(const TRiga_scadenze& s) - : TTree_rectype(s), _riga(s._riga) - -{ - CHECK(_riga, "Riga nulla"); -} - -TPartita& TRiga_scadenze::partita() const -{ - return riga().partita(); -} - - -// Controlla se la rata e' in valuta -bool TRiga_scadenze::in_valuta() const -{ - return get(SCAD_CODVAL).not_empty(); -} - -// Controlla se la rata e' stata completamente pagata -int TRiga_scadenze::pagata() const -{ - const TRecord_array& a = rows_array(); - for (int p = a.last_row(); p > 0; p = a.pred_row(p)) - { - const TRectype& pag = a.row(p); - if (pag.get_char("ACCSAL") == 'S') - return p; - } - return 0; -} - -// Calcola il totale dei pagamenti (eventualmente in valuta) -TImporto TRiga_scadenze::importo_pagato(bool val) const -{ - const TPartita& game = partita(); - const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; - TImporto totale; - const TRecord_array& a = rows_array(); - for (int p = a.last_row(); p > 0; p = a.pred_row(p)) - { - const TRectype& pag = a.row(p); // Riga pagamento - const TRiga_partite& sum = game.riga(p); // Riga partite - const TImporto imp(sum.get_char(PART_SEZ), pag.get_real(imp_field)); - totale += imp; - } - - return totale; -} - -// Calcola l'importo da pagare (eventualmente in valuta) -TImporto TRiga_scadenze::importo_da_pagare(bool val) const -{ - const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; - const TRiga_partite& r = riga(); // Riga fattura - const TImporto totale(r.get_char(PART_SEZ), get_real(imp_field)); - return totale; -} - -// Calcola l'abbuono della rata e ritorna il suo tipo: -// 'A' abbuono attivo; 'P' abbuono passivo -// La sezione dell'abbuono calcolato e' quella della riga contabile in cui finira' -char TRiga_scadenze::calcola_abbuono(TImporto& abbuono, bool val) const -{ - bool ap = ' '; - if (pagata()) - { - abbuono = importo_da_pagare(TRUE); - abbuono += importo_pagato(TRUE); - - const int sign = abbuono.valore().sign(); - if (sign != 0) - { - if (sign > 0) - ap = abbuono.sezione() == 'D' ? 'P' : 'A'; - else - ap = abbuono.sezione() == 'D' ? 'A' : 'P'; - } - - if (val && in_valuta()) - { - abbuono.valore() *= get_real(SCAD_CAMBIO); - abbuono.valore().round(); - } - } - else - abbuono.valore() = ZERO; - - return ap; -} - -// Calcola la differenza cambi con la sezione da mettere nella riga contabile corrispondente -TImporto TRiga_scadenze::calcola_differenza_cambio(bool update) -{ - TImporto diffcam; - const int riga_saldo = pagata(); - if (riga_saldo > 0) - { - TRectype& pag = row(riga_saldo, FALSE); - const TRiga_partite& sum = partita().riga(riga_saldo); - const char sez = sum.sezione(); - - if (update) - { - diffcam = importo_da_pagare(FALSE); - diffcam += importo_pagato(FALSE); - - real a = pag.get_real(PAGSCA_ABBUONI); - if (in_valuta()) - { - a *= get_real(SCAD_CAMBIO); - a.round(); - } - - const TImporto abb_lit(sez, a); - diffcam += abb_lit; - diffcam.normalize(sez); - pag.put(PAGSCA_DIFFCAM, diffcam.valore()); - } - else - { - diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM)); - } - } - return diffcam; -} - -real TRiga_scadenze::residuo() const -{ - const char* imp_field = get(SCAD_CODVAL).not_empty() ? SCAD_IMPORTOVAL : SCAD_IMPORTO; - const real da_pagare(get(imp_field)); - const real pagato(get(SCAD_IMPORTOPAG)); - const real residuo = da_pagare - pagato; - return residuo; -} - - -bool TRiga_scadenze::modifica_pagamento(const TRectype& new_pag, - char& old_ap, TImporto& old_abb, TImporto& old_diffcam, - char& new_ap, TImporto& new_abb, TImporto& new_diffcam) -{ - const int nrigp = new_pag.get_int(PAGSCA_NRIGP); - const TRectype old_pag(row(nrigp)); - TRiga_partite& sum = partita().riga(nrigp); - - old_ap = calcola_abbuono(old_abb, FALSE); - old_diffcam = calcola_differenza_cambio(FALSE); - - const char* imp_field = get(SCAD_CODVAL).not_empty() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; - const real importo(new_pag.get(imp_field)); - const bool empty = importo.is_zero(); - if (empty) - rows_array().destroy_row(nrigp); - else - row(nrigp, FALSE) = new_pag; - - TImporto abbuono; - new_ap = calcola_abbuono(abbuono, TRUE); // Calcolo abbuono in valuta - - TImporto imp(abbuono); imp.swap_section(); - imp.normalize(sum.sezione()); - if (new_ap != ' ') - { - CHECK(nrigp == pagata(), "Aggiornamento abbuoni inconsistente"); - TRectype& pag = row(nrigp, FALSE); - pag.put(PAGSCA_ABBUONI, imp.valore()); - - new_abb = abbuono; - if (in_valuta()) - { - new_abb.valore() *= get_real(SCAD_CAMBIO); - new_abb.valore().round(); - } - } - else - new_abb.valore() = ZERO; - - if (old_abb != new_abb) - { - const TImporto old(sum.sezione(), old_pag.get_real(PART_ABBUONI)); - TImporto abbuoni(sum.get_char(PART_SEZABB), sum.get_real(PART_ABBUONI)); - abbuoni -= old; - abbuoni += imp; - abbuoni.normalize(); - sum.put(PART_SEZABB, abbuoni.sezione()); - sum.put(PART_ABBUONI, abbuoni.valore()); - } - - new_diffcam = calcola_differenza_cambio(TRUE); - if (old_diffcam != new_diffcam) - { - TImporto tot_dc(sum.get_char(PART_SEZDIFCAM), sum.get_real(PART_DIFFCAM)); - tot_dc -= old_diffcam; - tot_dc += new_diffcam; - tot_dc.normalize(); - sum.put(PART_SEZDIFCAM, tot_dc.sezione()); - sum.put(PART_DIFFCAM, tot_dc.valore()); - } - - sum.update(old_pag, new_pag, PART_IMPORTO); - sum.update(old_pag, new_pag, PART_IMPORTOVAL); - sum.update(old_pag, new_pag, PART_RITENUTE); - - return empty; -} - -/////////////////////////////////////////////////////////// -// TRiga_partite -/////////////////////////////////////////////////////////// - -TRiga_partite::TRiga_partite(TPartita* game) - : TTree_rectype(LF_PARTITE, LF_SCADENZE, "NRATA"), _partita(game) -{ - CHECK(_partita, "Partita nulla"); -} - -TRiga_partite::TRiga_partite(const TRiga_partite& r) - : TTree_rectype(r), _partita(r._partita) -{ - CHECK(_partita, "Partita nulla"); -} - - -int TRiga_partite::read(TBaseisamfile& f, word op) -{ - int err = TRectype::read(f, op); - if (err == NOERR && get_int(PART_TIPOMOV) == 1) - { - TRiga_scadenze* s = new TRiga_scadenze(this); - copy_key_to_row(*s); - err = _recarr.read(s); // Deve esistere almento una scadenza -#ifdef DBG - if (_recarr.rows() == 0) - yesnofatal_box("Riga di fattura senza nessuna scadenza"); -#endif - } - else - _recarr.destroy_rows(); - return err; -} - -int TRiga_partite::ultimo_pagamento(int r) const -{ - const TRiga_scadenze& s = rata(r); - return s.rows_array().last_row(); -} - -bool TRiga_partite::update(const TRectype& vec, const TRectype& nuo, const char* field) -{ - real totale = get_real(field); - totale -= vec.get_real(field); - totale += nuo.get_real(field); - put(field, totale); - return !totale.is_zero(); -} - - -/////////////////////////////////////////////////////////// -// TPartita -/////////////////////////////////////////////////////////// - -TPartita::TPartita(const TBill& clifo, int anno, const char* num) - : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") -{ - read(clifo, anno, num); -} - -TPartita::TPartita() - : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") -{} - -// Costruisce le righe della partita -bool TPartita::read(const TBill& clifo, int anno, const char* num) -{ - TRiga_partite* partita = new TRiga_partite(this); // Record campione della partita - partita->put(PART_TIPOCF, clifo.tipo()); // Tipo clifo - if (clifo.tipo() <= ' ') - { - partita->put(PART_GRUPPO, clifo.gruppo()); // Scrivi gruppo e conto solamente - partita->put(PART_CONTO, clifo.conto()); // nei conti normali (no clifo) - } - partita->put(PART_SOTTOCONTO, clifo.sottoconto()); // Sottoconto o codice clifo - partita->put(PART_ANNO, anno); // Anno partita - partita->put(PART_NUMPART, num); // Numero partita - _part.read(partita); - -#ifdef DBG - for (int p = last(); p > 0; p = pred(p)) - CHECKD(riga(p)._partita == this, "Riga partite inconsistente", p); -#endif - - TRectype unas(LF_PAGSCA); // Record campione pagamenti non assegnati - unas.zero(); - unas.put(PART_TIPOCF, partita->get(PART_TIPOCF)); // Copia chiave partite - unas.put(PART_GRUPPO, partita->get(PART_GRUPPO)); - unas.put(PART_CONTO, partita->get(PART_CONTO)); - unas.put(PART_SOTTOCONTO, partita->get(PART_SOTTOCONTO)); - unas.put(PART_ANNO, partita->get(PART_ANNO)); - unas.put(PART_NUMPART, partita->get(PART_NUMPART)); - unas.put(PART_NRIGA, 0); // Numeri magici di non assegamento - unas.put(SCAD_NRATA, 0); - _unassigned.read(unas); - - return ok(); -} - -bool TPartita::reread() -{ - TBill zio; - conto(zio); - const int year = anno(); - const TString16 num = numero(); - return read(zio, year, num); -} - -bool TPartita::write(bool re) -{ - const bool ok = _part.write(re); - return ok; -} - -TImporto TPartita::importo_speso(long nreg, int numrig) const -{ - TImporto imp; - - for (int r = _part.last_row(); r > 0; r = pred(r)) - { - const TRectype& pag = riga(r); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - const int num = pag.get_int(PART_NUMRIG); - if (num == numrig) - { - imp = TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); - break; - } - } - } - - return imp; -} - - -void TPartita::update_reg_num(long nreg, const TRectype& mov) -{ - for (int r = _part.last_row(); r > 0; r = pred(r)) - { - TRectype& pag = _part.row(r, FALSE); - - const long reg = pag.get_long(PART_NREG); - if (reg == nreg) - { - pag.put(PART_NREG, mov.get(MOV_NUMREG)); - pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); - pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); - pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); - } - } -} - -// Calcola la riga di movimento relativa a una riga partita -int TPartita::rig2mov(int rp) const -{ - const TRiga_partite& r = riga(rp); - return r.get_int(PART_NUMRIG); -} - -// Calcola la riga di partita relativa a una riga movimento -int TPartita::mov2rig(long numreg, int rm) const -{ - for (int r = _part.last_row(); r > 0; r = pred(r)) - { - const TRiga_partite& row = riga(r); - if (row.get_long(PART_NREG) == numreg && row.get_int(PART_NUMRIG) == rm) - return r; - } - return -1; -} - -// Trova la prima riga della partita contenente una fattura -int TPartita::prima_fattura() const -{ - const int lastrow = last(); - for (int r = first(); r <= lastrow; r = succ(r)) - { - const TRiga_partite& row = riga(r); - const int tipomov = row.get_int(PART_TIPOMOV); - if (tipomov == 1 || tipomov == 2) - return r; - } - return -1; -} - -void TPartita::calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const -{ - doc = pag = imp = TImporto('D', ZERO); - - for (int r = _part.last_row(); r > 0; r = pred(r)) - { - const TRiga_partite& row = riga(r); - TImporto i(row.get_char(PART_SEZ), row.get_real(PART_IMPORTO)); - switch (row.get_int(PART_TIPOMOV)) - { - case 1: - case 2: - doc += i; // documenti - break; - case 3: - pag += i; // pagamenti - break; - default: - imp += i; // altri importi - break; - } - - i.set(row.get_char(PART_SEZ), row.get_real(PART_ABBUONI)); - imp += i; - - i.set(row.get_char(PART_SEZ), row.get_real(PART_DIFFCAM)); - imp += i; - } - - saldo = doc; - saldo += pag; - saldo += imp; -} - - -bool TPartita::utilizzata(int nrigp) const -{ - for (int p = _part.last_row(); p > 0; p = pred(p)) - { - const TRiga_partite& fatt = riga(p); - const int tipomov = fatt.get_int(PART_TIPOMOV); - if (tipomov == 1) - { - for (int r = fatt.rate(); r > 0; r--) - { - const TRiga_scadenze& scad = fatt.rata(r); - if (scad.rows_array().exist(nrigp)) - return TRUE; - } - } - } - return FALSE; -} - -bool TPartita::modifica_pagamento(const TRectype& new_pag, - char& old_ap, TImporto& old_abb, TImporto& old_diffcam, - char& new_ap, TImporto& new_abb, TImporto& new_diffcam) -{ - const int nriga = new_pag.get_int(PAGSCA_NRIGA); - const TRiga_partite& fattura = riga(nriga); - - const int nrata = new_pag.get_int(PAGSCA_NRATA); - TRiga_scadenze& scaden = fattura.rata(nrata); - - const int nrigp = new_pag.get_int(PAGSCA_NRIGP); - const TRectype& old_pag = scaden.row(nrigp); - - const bool empty = scaden.modifica_pagamento(new_pag, - old_ap, old_abb, old_diffcam, - new_ap, new_abb, new_diffcam); - - if (empty && !utilizzata(nrigp)) - _part.destroy_row(nrigp); - - return empty; -} - -/////////////////////////////////////////////////////////// -// TPartite_array -/////////////////////////////////////////////////////////// - -// Certified 99% -const TString& TPartite_array::key(const TBill& clifo, int anno, const char* num) -{ - if (clifo.tipo() > ' ') - _key.format("%c%3d%3d%6ld%4d%s", clifo.tipo(), 0, 0, clifo.sottoconto(), anno, num); - else - _key.format("%c%3d%3d%6ld%4d%s", - clifo.tipo(), clifo.gruppo(), clifo.conto(), clifo.sottoconto(), anno, num); - return _key; -} - -// Certified 99% -TPartita* TPartite_array::find(const TBill& clifo, int anno, const char* num, bool create) -{ - const TString& k = key(clifo, anno, num); - TPartita* p = (TPartita*)objptr(k); - if (p == NULL && create) - { - p = new TPartita(clifo, anno, num); - if (p->ok()) - add(k, p); - else - { - delete p; - p = NULL; - } - } - return p; -} - -TPartita* TPartite_array::find(const TRectype& r, bool create) -{ - TBill zio; zio.get(r); - const int anno = r.get_int(PART_ANNO); - const char* num = r.get_str(PART_NUMPART); - return find(zio, anno, num, create); -} - -TPartita& TPartite_array::partita(const TBill& clifo, int anno, const char* num) -{ - TPartita* game = find(clifo, anno, num, TRUE); - CHECKS(game, "Partita errata ", num); - return *game; -} - -TPartita& TPartite_array::partita(const TRectype& r) -{ - TPartita* game = find(r, TRUE); - CHECK(game, "Partita errata"); - return *game; -} - -bool TPartite_array::write(bool re) -{ - int err = NOERR; - - TPartita* game; - restart(); - while ((game = (TPartita*)get()) != NULL) - { - err = game->write(re); - if (err != NOERR) // L'errore viene gia' segnalato dalla partita - break; - } - - return err == NOERR; -} - -// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg -int TPartite_array::add_reg_num(long nreg, int numrig) -{ - TRelation rel(LF_PARTITE); - TRectype& part = rel.lfile().curr(); - - // Costruzione filtro del cursore - part.zero(); - part.put(PART_NREG, nreg); - if (numrig > 0) - part.put(PART_NUMRIG, numrig); - - const TRectype filter(part); - - TCursor cur(&rel, "", 2, &filter, &filter); - - for (cur = 0; cur.ok(); ++cur) - partita(part); // Aggiungi partita se non esiste gia' - - return (int)cur.items(); -} - -TImporto TPartite_array::importo_speso(long nreg, int numrig) -{ - TImporto imp; - add_reg_num(nreg, numrig); - for (TPartita* game = first(); game; game = next()) - imp += game->importo_speso(nreg, numrig); - return imp; -} - -void TPartite_array::update_reg_num(long nreg, const TRectype& mov) -{ - add_reg_num(nreg, 0); - for (TPartita* game = first(); game; game = next()) - game->update_reg_num(nreg, mov); -} - +#include + +#include "pagament.h" + +#include +#include +#include +#include + +int TPagamento::_rata_ifield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.get_int(f); +} + +real TPagamento::_rata_rfield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return real(t.get(f)); +} + +TDate TPagamento::_rata_dfield(int n, int f) const +{ + TToken_string& t = (TToken_string&)_rate[n]; + return TDate(t.get(f)); +} + +const char* TPagamento::_rata_sfield(int n, int f) const +{ + static char kak[6]; + TToken_string& t = (TToken_string&)_rate[n]; + strcpy(kak,t.get(f)); + return kak; +} + + +bool TPagamento::ratapagata(int n) +{ + TToken_string& t = (TToken_string&)_rate[n]; + return t.items() > 6; +} + + + +void TPagamento::set_intervallo_rate(int in) +{ + _dirty = TRUE; + _int_rate = in; + if (_mcomm && (in % 30) != 0) + _mcomm = FALSE; + for (int i = 0; i < n_rate(); i++) + { + TToken_string& ts = rata(i); + ts.add(i == 0 ? (scad_rata(0) == 0 ? "0" : format("%d",in)) + : format("%d",in), 0); + } +} + +void TPagamento::set_mese_commerciale(bool v, int& sscad) +{ + _dirty = FALSE; + if (_mcomm == v) return; + if (sscad == -1) sscad = 30; + + if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1); + set_intervallo_rate(sscad); + + _mcomm = v; +} + +void TPagamento::set_rate_differenziate(int v) +{ + _dirty = FALSE; + if (!_rdiff && v == 2) return; + + if (v == 2 && (100 % n_rate()) == 0) + { + int p = 100 / n_rate(); + for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(p,1); + } + _rdiff = !(v == 2); + _dirty = TRUE; + } +} + +void TPagamento::set_tipo_prima_rata(int v, int sscad) +{ + _dirty = FALSE; + if (_tpr == v) return; + + if (v < 4 && _tpr > 3) + { + for (int i = n_rate() - 1; i > 0; i--) + { + TToken_string& tt = rata(i); + tt.add(scad_rata(i-1),0); + tt.add(tipo_rata(i-1),2); + tt.add(ulc_rata(i-1),5); + } + _rate.add(NULL,0); + _rate.pack(); + } + else if ( _tpr < 4 && v > 3) + { + TToken_string* ttn = new TToken_string(32); + ttn->add(0,0); + ttn->add(0,1); + ttn->add(1,2); + ttn->add("",3); + ttn->add("",4); + ttn->add("",5); + _rate.insert(ttn,0); + for (int i = 0; i < (n_rate()-1); i++) + { + TToken_string& tt = rata(i); + tt.add(scad_rata(i+1),0); + tt.add(tipo_rata(i+1),2); + tt.add(ulc_rata(i+1),5); + } + } + _tpr = v; + _dirty = TRUE; +} + +void TPagamento::set_numero_rate(int n, int sscad) +{ + _dirty = FALSE; + if (n == 0 || n == n_rate()) return; + + real p = real(100) / real(n); + p.round(2); + int nr = n_rate(); + int first = _tpr < 4 ? 0 : 1; + real sum = 0.0; + + for (int i = first; sum < real(100.0); i++) + { + if ((real(100.0) - sum) < p) + p = real(100.0) - sum; + + sum += p; + + // if necessary add remainder on first one + if ((real(100.0) - sum) /* still */ < p) + { + real prc = perc_rata(first); + prc += real(100.0) - sum; + TToken_string& rt = rata(first); + rt.add(prc.string(),1), + sum = 100; + } + + set_rata(i, real(p), + i == 0 ? (i < nr ? scad_rata(0) : 0): + (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad), + (i < nr ? tipo_rata(i) : tipo_rata(nr-1))); + } + // erase remaining + for (; i < nr; i++) + _rate.add(NULL,i); + _rate.pack(); + + _dirty = TRUE; +} + + +void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata) +{ + if (mcomm) + { + int nm = scad / 30; + int ny = nm / 12; + nm %= 12; + + int newm = d.month() + nm; + if (newm > 12) { newm -= 12; ny++; } + + bool last = d.is_end_month() && inizio_scadenza() == 'M'; + + int dy = d.day(); + + // la palla del febbraio & c. + if (rata > 1) + { + TDate oldd(data_rata(rata-2)); + if (oldd.day() > dy) dy = oldd.day(); + } + + d.set_day(1); // il giorno 1 ce l'hanno tutti + d.set_month(newm); + d.set_year(d.year()+ny); + + d.set_end_month(); + if (!last && dy < d.day()) + d.set_day(dy); + } + else + { + d += scad; + } + + // riaggiusta la minchia se ci sono scadenze fissate + if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0) + { + for (int i = 0; i < 3; i++) + { + if (_fixd[i] > d.day()) + { + if (d.last_day(d.month(), d.year()) <= _fixd[i]) + d.set_day(_fixd[i]); + else d.set_end_month(); + break; + } + } + + if (i == 3) + { + if (_fixd[0] > 0 && _fixd[0] < d.day()) + { + d.set_day(_fixd[0]); + d.set_month(d.month() == 12 ? 1 : d.month() + 1); + } + } + + } +} + + +void TPagamento::set_default_type(int type, bool change_existing) +{ + _def_tpr = type; + if (change_existing) + { + for (int i = 0; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(type, 2); + } + _dirty = TRUE; + } +} + +void TPagamento::set_default_ulc(const char* ulc, bool change_existing) +{ + _def_ulc = ulc; + if (change_existing) + { + for (int i = 0; i < n_rate(); i++) + { + TToken_string& tt = rata(i); + tt.add(ulc, 5); + } + _dirty = TRUE; + } +} + +void TPagamento::remove_rata(int i) +{ + // non fa nessun ricalcolo, si limita ad impacchettare se + // necessario + _rate.add(NULL,i); + _rate.pack(); + _dirty = TRUE; +} + +TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc) +{ + TToken_string* tt = new TToken_string(16); + tt->add(day); // scadenza + tt->add(perc.string()); // percentuale + tt->add(type); // tipo + tt->add(""); + tt->add(""); + tt->add(ulc); + _rate.add(tt); + _dirty = TRUE; + return *tt; +} + +TToken_string& TPagamento::set_rata (int index, real perc, int day, int type, + const char* ulc, const char* imp, + const char* data) +{ + TToken_string* tt = (TToken_string*)_rate.objptr(index); + const bool nwr = (tt == NULL); + if (nwr) tt = new TToken_string(16); + + tt->add(day,0); // scadenza + tt->add(perc.string(),1); // percentuale + tt->add(type,2); // tipo + tt->add(data == NULL ? "" : data,3); + tt->add(imp == NULL ? "" : imp,4); + tt->add(ulc == NULL ? "" : ulc,5); + + if (!nwr) + { + if (index > _rate.items()) + { + error_box("Rate non contigue"); + delete tt; + } + } + else + { + _rate.add(tt,index); + _dirty = TRUE; + } + return *tt; +} + +void TPagamento::set_imprata(int i, real r) +{ + TToken_string& tt = (TToken_string&)_rate[i]; + TDate d = _inizio; + + for (int n = 0; n <= i; n++) + next_scad(d, scad_rata(n), _mcomm, n); + + tt.add((const char*)d, 3); + tt.add(r.string(), 4); +} + +TToken_string& TPagamento::set_rata(int index, const real& howmuch, + const TDate& date, int type,const char* ulc, bool pagato) +{ + // calcola percentuali e scadenze a partire dagli importi + TToken_string* tt = (TToken_string*)_rate.objptr(index); + + const bool nwr = (tt == NULL); // nuova rata + + if (nwr) tt = new TToken_string(16); + + TDate oldd = index > 0 ? data_rata(index -1) : _inizio; + int day = date - oldd; + real toshare(_tpr < 4 ? _firstr : _secndr); + real perc = (_tpr > 3 && index == 0) ? ZERO : howmuch/toshare; + perc *= real(100.0); + perc.round(2); + + tt->add(day,0); // scadenza + tt->add(perc.string(),1); // percentuale + tt->add(type,2); // tipo + tt->add(date.string(),3); + tt->add(howmuch.string(),4); + tt->add(ulc,5); + if (pagato) tt->add("X",6); + + if (!nwr) + { + if (index > _rate.items()) + { + error_box("Rate non contigue"); + delete tt; + } + } + else + { + _rate.add(tt, index); + _dirty = TRUE; + } + return *tt; +} + + + +word TPagamento::validate() const +{ + word res = 0x0000; + real r(0.0); + + int first = _tpr < 4 ? 0 : 1; + real toshare(_tpr < 4 ? _firstr : _secndr); + TDistrib ds(toshare,0); + + // check percentages & prepare slicer + for (int i = first; i < n_rate(); i++) + { + real p(perc_rata(i)); + ds.add(p); + r += p; + } + + if (r != real(100.0)) + res |= P_RSUM; + + + if (_inited) + { + ds.init(toshare); + // check importi rate consistenti con la percentuale + for (int i = first; i < n_rate(); i++) + { + real r1(tpay_rata(i)); + real r2(ds.get()); + if (r1 != r2) + { res |= P_IMPNC; break; } + } + + // check errori date scadenze (se istanziate) + TDate d(data_rata(0)); + if (d < _inizio) + res |= P_INIZIO; + for (i = 1; i < n_rate(); i++) + { + if (data_rata(i) <= d) + { res |= P_SCAD; break; } + d = data_rata(i); + } + } + return res; +} + + +void TPagamento::strerr(word err, TString& s) +{ + s = "Errore:"; + if (err & P_RSUM) + s << "\n Le percentuali non sommano a 100"; + if (err & P_IMPNC) + s << "\n Le percentuali sono inconsistenti con gli importi"; + if (err & P_SCAD) + s << "\n Le scadenze non sono consecutive"; + if (err & P_INIZIO) + s << "\n La prima rata e' antecedente alla data movimento"; +} + +const char* TPagamento::desc_tpr() const +{ + const char* o; + switch (_tpr) + { + case 0: o = "Totale su tutte le rate"; break; + case 1: o = "Tutte le imposte su 1a"; break; + case 2: o = "Tutte le spese su 1a"; break; + case 3: o = "Imposte + spese su 1a"; break; + case 4: o = "Spese + merce su 1a"; break; + case 5: o = "Merce + imposte su 1a"; break; + case 6: o = "Tutta la merce su 1a"; break; + default: o = ""; break; + } + return o; +} + +const char* TPagamento::desc_tipo(int i) const +{ + const char* o; + switch (i) + { + case 1: o = "Rimessa diretta o contanti"; break; + case 2: o = "Tratta"; break; + case 3: o = "Ricevuta bancaria"; break; + case 4: o = "Cessione"; break; + case 5: o = "Paghero'"; break; + case 6: o = "Lettera di credito"; break; + case 7: o = "Tratta accettata"; break; + case 8: o = "Rapporti interbancari diretti"; break; + case 9: o = "Bonifici"; break; + case 10: o = "Altro pagamento"; break; + } + return o; +} + +word TPagamento::recalc_rate(int row, bool is_perc_modified, + const char* new_value, const char* scad, + const char* typ, int rdiff, bool mcomm, + bool& need_recalc) + // ricalcola le rate sulla base di parametri modificati sulla riga row + // parametri: tutti i const char* possono essere NULL, il che vuol dire + // che i dati corrispondenti non sono stati modificati; + // se new_value non e' NULL puo' essere la percentuale (e + // allora is_perc_modified e' TRUE) o l'importo. Non e' + // possibile modificare entrambi; se succede viene data + // priorita' alla percentuale. +{ + CHECK(!(!is_perc_modified && new_value != NULL && !_inited), + "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!"); + + if (_rate.items() == 0) return P_OK; + + real rsum(0.0), newv(0.0), rmax(0.0); + int oldtype = tipo_rata(0); + int oldscad = scad_rata(0); + TDate lastdate = data_rata(0); + int first = _tpr < 4 ? 0 : 1; + TArray srate(_rate); // rate come erano + + + if (srate.items() > 1) + { + // calcola defaults per tipo pagamento e scadenza + // nel caso di rate nuove + oldscad = scad_rata(1); + } + + if (oldscad == 0) oldscad = 30; + if (oldtype == 0) oldtype = 1; + + if (new_value != NULL) + { + newv = new_value; + rmax = is_perc_modified? (real) 100.0 : (_tpr < 4 ? _firstr : _secndr); + if (newv > rmax) return P_RSUM; + } + + bool exhausted = FALSE; + + for (int i = first; i < srate.items(); i++) + { + if (i == row) + { + if (typ != NULL) + { + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + tt.add(typ,2); + ss.add(typ,2); + // no error is possible + } + + if (scad != NULL) + { + // if !_inited scad e' il n. giorni, se no e' la rata + if (_inited) + { + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + lastdate = scad; + // controlla errore sulla data scadenza + if (i > 0) + { + oldscad = (int)(lastdate - data_rata(i-1)); + if (oldscad <= 0l) return P_SCAD; + } + else if (lastdate < _inizio) return P_INIZIO; + tt.add(scad,3); + ss.add(scad,3); + // ricalcola rate successive: se si vuole modificarne solo una + // ci si fotte e si disabilita il ricalcolo + TDate ddd (lastdate); + for (int j = row+1; j < srate.items(); j++) + { + TToken_string& tt = rata(j); + TToken_string& ss = (TToken_string&)srate[j]; + next_scad(ddd,scad_rata(j),mcomm,j); + tt.add(ddd.string(),3); + ss.add(ddd.string(),3); + need_recalc = TRUE; + } + } + else + { + // nulla di speciale visto che si memorizza la derivata + int sc = atoi(scad); + for (int i = 0; i < row; i ++) + sc -= scad_rata(i); + if (sc < 0 || (row > 0 && sc == 0)) return P_SCAD; + if (_mcomm && (sc % 30) != 0) _mcomm = FALSE; + TToken_string& tt = rata(row); + TToken_string& ss = (TToken_string&)srate[row]; + tt.add(sc,0); + ss.add(sc,0); + need_recalc = TRUE; + } + } + + // here's the bell + if (new_value != NULL) + { + if (newv == ZERO || (rsum+newv) > rmax) + return P_RSUM; + // did not sforate + rsum += newv; + TToken_string& rt = rata(row); + // setta nuovo valore e ricalcola cio' che ne consegue + if (is_perc_modified) rt.add(new_value,1); + else rt.add(new_value,4); + // riaggiusta le rate rimanenti + real remainder(0.0); remainder = rmax - rsum; + if (!(exhausted = (remainder == real(0.0)))) + { + // se inited e scelto UGUALI (2) occorre dividere in N e + // aggiungere il resto sulla 1a rata + // controlla se rdiff e' compatibile con + // i dati e se e' il caso riaggiusta + if (rdiff == 3 && !((remainder % newv.integer()) == ZERO)) + rdiff = 2; +// *** 10/8/95: se uguali e non e' multiplo intero lo teniamo cosi' e poi +// *** aggiungiamo alla prima rata utile +// if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) +// rdiff = 1; + _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4); + + // procedi + if (rdiff == 1) + { + // cancella tutte le rate successive, aggiungi un'unica rata + // con il resto dell'importo + if (row < (srate.items()-1)) + { + TToken_string& trt = rata(row+1); + trt.add(remainder.string(), is_perc_modified ? 1 : 4); + for(int j = row+2; j < srate.items(); j++) + _rate.add(NULL,j); + } + else + { + // l'importante e' esagerare + for(int j = row+1; j < srate.items(); j++) + _rate.add(NULL,j); + + TToken_string& trt = add_rata(is_perc_modified ? remainder : (real) 0.0, + oldscad, oldtype); + if (!is_perc_modified) trt.add(remainder.string(),4); + if (_inited) + { + TDate dd = data_rata(row); + next_scad(dd,oldscad,mcomm,row); + trt.add(dd.string(),3); + } + } + } + else // rate non differenziate (dall'inizio o da row) + { + // ripartisci l'importo nel numero necessario di rate per + // mantenere costante il valore + real sum(0.0); + if (_inited) lastdate = data_rata(rdiff == 2 ? first : row); + + TDate dd(lastdate); + int type = oldtype; + int nscd = oldscad; + + int frs = (rdiff == 3 || rdiff == 4) ? row+1 : first; + real mx = (rdiff == 3 || rdiff == 4) ? remainder : rmax; + + // cancelliamo tutto, va' + for (int j = frs; j < srate.items(); j++) + _rate.add(NULL,j); + + if (rdiff != 4) + for (j = frs; sum < mx; j++) + { + // TBI: qui mod se rdiff == 2 + // se c'e' la vecchia rata si tengono i parametri + // altrimenti si calcolano + if (j < srate.items()) + { + TToken_string& trt = (TToken_string&)srate[j]; + if (_inited) dd = trt.get(3); + type = atoi(trt.get(2)); + nscd = j == 0 ? 0 : atoi(trt.get(0)); + if (type == 0) type = 1; + if (j > 0 && nscd == 0) nscd = oldscad; + if (_inited && dd == lastdate && j > 0) + next_scad(dd,nscd,mcomm,j); + } + else if (_inited) + { + if (dd <= botime) dd = lastdate; + next_scad(dd,nscd,mcomm,j); + } + else nscd = _int_rate; + + TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, + nscd, type); + if (_inited) + ttr.add(dd.string(), 3); + if (!is_perc_modified) + { + ttr.add(newv.string(),4); + } + if ((mx - sum) < newv) + { + // add remainder on first rate + newv += (mx - sum); + if (!is_perc_modified) + set_imprata(frs, newv); + else { + TToken_string& t = rata(frs); + t.add(newv.string(), 1); + } + remove_rata(j); + break; + } +// } + sum += newv; + } + else // rdiff == 4; uguali finche' possibile + { + bool basta = FALSE; + for (j = frs; ; j++) + { + // ultima rata puo' differire dalle precedenti + if (mx - sum <= newv) + { + newv = mx - sum; + basta = TRUE; + } + // se c'e' la vecchia rata si tengono i parametri + // altrimenti si calcolano + if (j < srate.items()) + { + TToken_string& trt = (TToken_string&)srate[j]; + if (_inited) dd = trt.get(3); + type = atoi(trt.get(2)); + nscd = j == 0 ? 0 : atoi(trt.get(0)); + if (type == 0) type = 1; + if (j > 0 && nscd == 0) nscd = oldscad; + if (_inited && dd == lastdate && j > 0) + next_scad(dd,nscd,mcomm,j); + } + else if (_inited) next_scad(dd,nscd,mcomm,j); + + TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO, + nscd, type); + if (_inited) + ttr.add(dd.string(), 3); + if (!is_perc_modified) + ttr.add(newv.string(),4); + if (basta) break; + sum += newv; + } + } + } + + } + else // exhausted + { + for(int j = row+1; j < srate.items(); j++) + _rate.add(NULL,j); + } + + + if (_inited) + { + // ricalcola il valore secondario (non modificato) + real toshare(100.0); + if (is_perc_modified) + toshare = (_tpr < 4 ? _firstr : _secndr); + TDistrib dt(toshare, is_perc_modified ? _round : 3); + + for (int j = first; j < _rate.items(); j++) + { + real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); + real zpx = rvl/rmax; // percentuale + dt.add(zpx); + } + for (j = first; j < _rate.items(); j++) + { + TToken_string& tr = rata(j); + real rvl = dt.get(); + tr.add(rvl.string(), is_perc_modified ? 4 : 1); + } + + // se e' il caso aggiungi l'importo fisso sulla prima rata + if (_inited && _tpr > 0 && _tpr < 4) + { + TToken_string& tr = rata(0); + real tot = tpay_rata(0) + _firstr; + tr.add(tot.string(), 4); + } + + } + + need_recalc = TRUE; + return P_OK; + } // new_value != NULL + } + else // i != row modified + { + if (i > 0 && !((perc_rata(i-1) == perc_rata(i)))) + { + if (rdiff == 2) rdiff = 1; + _rdiff = FALSE; + } + if (is_perc_modified) + rsum += perc_rata(i); + else + rsum += tpay_rata(i); + + lastdate = data_rata(i); + oldtype = tipo_rata(i); + oldscad = scad_rata(i); + if (_inited && i > 0) + { + if (data_rata(i) <= data_rata(i-1)) + return P_SCAD; + } + else if (lastdate < _inizio) + return P_INIZIO; + } + } + + return P_OK; +} + + +bool TPagamento::read(TTable* t, TTable* r) +{ + // puo' chiamarla chiunque + bool istnew = FALSE; + if (t == NULL) + { + t = new TTable("%CPG"); + istnew = TRUE; + } + t->zero(); t->put("CODTAB",_code); + if (t->read() != NOERR) return FALSE; + + // set everything + _rdiff = t->get_bool("B1"); + _mcomm = t->get_bool("B0"); + _tpr = atoi(t->get("S3")); + _inscad = *((const char*)(t->get("S1"))); + _code = t->get("CODTAB"); + _name = t->get("S0"); + _fixd[0] = t->get_int("I0"); + _fixd[1] = t->get_int("I1"); + _fixd[2] = t->get_int("I2"); + + // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc. + if (_inscad == 'M') + { + if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30); + else _inizio.set_end_month(); + } + else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) + _inizio.set_month(30); + + // leggi rate e scadenze + bool isrnew = FALSE; + if (r == NULL) + { + r = new TTable("%RPG"); + isrnew = TRUE; + } + TString s(16); + + for (int i = 0; ;i++) + { + r->zero(); s.format("%s%3d",(const char*)_code, i); + r->put("CODTAB", (const char*)s); + if (r->read() != NOERR) break; + TToken_string* tt = new TToken_string(16); + tt->add((const char*)(r->get("I0"))); // scadenza + tt->add((const char*)(r->get("R0"))); // percentuale + tt->add((const char*)(r->get("I1"))); // tipo + // data e importo + TDate d = _inizio; + next_scad(d,(int)(r->get_long("I0")),_mcomm,i); + tt->add((const char*)d); + tt->add(""); + tt->add(r->get("S1")); + _slicer.add((real)r->get("R0")); + _rate.add(tt); + } + + if (istnew) delete t; + if (isrnew) delete r; + + return TRUE; +} + + +int TPagamento::write(TTable& r) +{ + // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una + // relapp, che ha scritto il file principale + + TString s(16); int err = NOERR; + for (int i = 0; err == NOERR && i < n_rate(); i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + r.put("I0", (long)scad_rata(i)); + r.put("R0", perc_rata(i).string()); + r.put("I1", (long)tipo_rata(i)); + r.put("S1", ulc_rata(i)); + err = r.write(); + } + return err; +} + +int TPagamento::rewrite(TTable& r) +{ + TString s(16); int err = NOERR; + for (int i = 0; err == NOERR && i < n_rate(); i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + bool was = (r.read() == NOERR); + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + r.put("I0", (long)scad_rata(i)); + r.put("R0", perc_rata(i).string()); + r.put("I1", (long)tipo_rata(i)); + r.put("S1", ulc_rata(i)); + err = (was ? r.rewrite() : r.write()); + } + // erase possible rates > current n. rates + for (;err == NOERR;i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + if (r.read() == NOERR) err = r.remove(); + else break; + } + return err; +} + +int TPagamento::remove(TTable& r) +{ + TString s(16); int err = NOERR; + for (int i = 0 ; err == NOERR; i++) + { + r.zero(); s.format("%s%3d",(const char*)_code, i); + r.put("CODTAB", (const char*)s); + if (r.read() == NOERR) err = r.remove(); + else break; + } + return err; +} + +void TPagamento::set_rate_auto() +{ + // vedi rate esistenti e tipo prima rata + // deve fare riferimento ad un tipo pagamento esistente + // e sensato + int first = 0; + + real toslice = _firstr; + + if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1)) return; + if (_tpr > 3) // ripartisci _firstr su tutte le rate + { + first = 1; + toslice = _secndr; + } + + _slicer.init(toslice); + + if (_tpr > 3) + // prima rata obbligatoria + set_imprata(0, _firstr); + + // se rate uguali dividi l'importo totale per il numero di rate + real r1(0.0), ro(0.0); + if (!_rdiff) + { + int rut = _tpr > 3 ? n_rate() - 1 : n_rate(); + ro = toslice/real(rut); ro.trunc(_round); + r1 = ro + (toslice - (ro*real(rut))); + } + + for (int i = first; i < n_rate(); i++) + // setta le fette e le date di scadenza + set_imprata(i, _rdiff ? _slicer.get() : (i == first ? r1 : ro)); + + // se e' nei primi tre casi, si somma l'importo da non dividere alla + // prima rata + if (_tpr > 0 && _tpr < 4) + set_imprata(0, tpay_rata(0) + _firstr); +} + + + +void TPagamento::set_total(const real& imponibile, const real& imposta, const real& spese) +{ + _imponibile = imponibile; + _imposta = imposta; + _spese = spese; + _inited = TRUE; + + // istanzia _firstr e _secndr a seconda di _tpr + switch(_tpr) + { + case 0: + _firstr = _imponibile + _imposta + _spese; + _secndr = 0.0; + break; + case 1: + _firstr = _imposta; + _secndr = _imponibile + _spese; + break; + case 2: + _firstr = _spese; + _secndr = _imposta + _imponibile; + break; + case 3: + _firstr = _imposta + _spese; + _secndr = _imponibile; + break; + case 4: + _firstr = _spese + _imponibile; + _secndr = _imposta; + break; + case 5: + _firstr = _imponibile + _imposta; + _secndr = _spese; + break; + case 6: + _firstr = _imponibile; + _secndr = _imposta + _spese; + break; + } + + real toslice = _tpr > 1 ? _secndr : _firstr; + + _slicer.init(toslice, TRUE); + + for (int i = 0; i < _rate.items(); i++) + { + TToken_string& t = (TToken_string&)_rate[i]; + real rr(t.get(1)); + _slicer.add(rr); + } +} + + +void TPagamento::set_sheet(TSheet_field& sf, int sscad) +{ + sf.destroy(-1); + if (_inited && _rate.items() > 0) + { + // si istanzia uno sheet di primanota + for (int i = 0; i < n_rate(); i++) + { + TToken_string& ts = sf.row(-1); + // istanzia, o stronzo + ts.add((const char*)data_rata(i)); + ts.add(perc_rata(i).string()); + ts.add(tpay_rata(i).string()); + ts.add(tipo_rata(i)); + ts.add(desc_tipo(tipo_rata(i))); + if (ratapagata(i)) + { + sf.disable_cell(1,1); // percentuale + sf.disable_cell(1,2); // importo + } + } + } + else if (_rate.items() > 0) // not inited: set edit sheet + { + for (int i = 0, scr = 0; i < n_rate(); i++) + { + TToken_string& s = sf.row(-1); + scr += scad_rata(i); + s.add(scr); + s.add(perc_rata(i).string()); + s.add(tipo_rata(i)); + s.add(desc_tipo(tipo_rata(i))); + s.add(ulc_rata(i)); + } + } + else // new: set with 1 or 2 rates according to tpr + { + if (_tpr > 3) + add_rata(ZERO, sscad == -1 ? 0 : sscad, _def_tpr, _def_ulc); + add_rata(real(100.0), sscad == -1 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc); + + _dirty = TRUE; + + for (int i = 0, scr = 0; i < n_rate(); i++) + { + TToken_string& s = sf.row(-1); + scr += scad_rata(i); + s.add(scr); + s.add(perc_rata(i).string()); + s.add(tipo_rata(i)); + s.add(desc_tipo(tipo_rata(i))); + s.add(ulc_rata(i)); + } + } + if (_tpr > 3) + { + // disabilita campi da non toccare sulla prima rata + if (_inited) + { + sf.disable_cell(0,1); // percentuale + sf.disable_cell(0,2); // importo + } + else + { + sf.disable_cell(0,1); // percentuale + } + } + sf.force_update(); +} + +TPagamento::TPagamento(const char* codtab, const char* data) : +_slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), +_spese(0.0), _code(codtab), _dirty(FALSE), _inited(FALSE), +_def_tpr(1), _def_ulc(""), _round(0), _int_rate(30) +{ + _fixd[0] = _fixd[1] = _fixd[2] = 0; + if (data != NULL) + _inizio = data; + if (_code.blank() || !read()) + _new = TRUE; +// if (_new && data != NULL) error_box("Modalita' pagamento inesistente"); +} + + +/////////////////////////////////////////////////////////// +// TTree_rectype +/////////////////////////////////////////////////////////// + +TTree_rectype::TTree_rectype(const TRectype& testa, const TRectype& riga, const char* num) + : TRectype(testa), _recarr(riga, num) +{ +} + +TTree_rectype::TTree_rectype(int testa, int riga, const char* num) + : TRectype(testa), _recarr(riga, num) +{ +} + +TTree_rectype::TTree_rectype(const TTree_rectype& t) + : TRectype(t), _recarr(t._recarr) +{ +} + + +TObject* TTree_rectype::dup() const +{ + TTree_rectype* r = new TTree_rectype(*this); + return r; +} + +void TTree_rectype::copy_key_to_row(TRectype& row) const +{ + const int numkey = 0; // Memento! Gli indici delle chiavi partono da zero! + RecDes* recd = rec_des(); // Descrizione del record della testata + + row.zero(); + for (int i = 0; i < recd->Ky[numkey].NkFields; i++) + { + const KeyDes& kd = recd->Ky[numkey]; + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd->Fd[nf]; + const char* name = rf.Name; + const TString& val = get(name); + row.put(name, val); + } +} + +int TTree_rectype::fill_array() +{ + TRectype* row = (TRectype*)_recarr.key().dup(); + copy_key_to_row(*row); + const int err = _recarr.read(row); + return err; +} + + +int TTree_rectype::read(TBaseisamfile& f, word op) +{ + int err = TRectype::read(f, op); + if (err == NOERR) + fill_array(); + else + _recarr.destroy_rows(); + return err; +} + +int TTree_rectype::next(TBaseisamfile& f) +{ + int err = TRectype::next(f); + if (err == NOERR) + fill_array(); + else + _recarr.destroy_rows(); + return err; +} + +int TTree_rectype::write(TBaseisamfile& f) const +{ + int err = TRectype::write(f); + if (err == NOERR) + err = _recarr.write(); + return err; +} + +int TTree_rectype::rewrite(TBaseisamfile& f) const +{ + int err = TRectype::rewrite(f); + if (err == NOERR) + err = _recarr.rewrite(); + return err; +} + +int TTree_rectype::remove(TBaseisamfile& f) +{ + int err = TRectype::remove(f); + if (err == NOERR) + err = _recarr.remove(); + return err; +} + + +/////////////////////////////////////////////////////////// +// TRiga_scadenze +/////////////////////////////////////////////////////////// + +TRiga_scadenze::TRiga_scadenze(TRiga_partite* r) + : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP"), _riga(r) +{ + CHECK(_riga, "Riga nulla"); +} + +TRiga_scadenze::TRiga_scadenze(const TRiga_scadenze& s) + : TTree_rectype(s), _riga(s._riga) + +{ + CHECK(_riga, "Riga nulla"); +} + +TPartita& TRiga_scadenze::partita() const +{ + return riga().partita(); +} + + +// Controlla se la rata e' in valuta +bool TRiga_scadenze::in_valuta() const +{ + return get(SCAD_CODVAL).not_empty(); +} + +// Controlla se la rata e' stata completamente pagata +int TRiga_scadenze::pagata() const +{ + const TRecord_array& a = rows_array(); + for (int p = a.last_row(); p > 0; p = a.pred_row(p)) + { + const TRectype& pag = a.row(p); + if (pag.get_char("ACCSAL") == 'S') + return p; + } + return 0; +} + +// Calcola il totale dei pagamenti (eventualmente in valuta) +TImporto TRiga_scadenze::importo_pagato(bool val) const +{ + const TPartita& game = partita(); + const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + TImporto totale; + const TRecord_array& a = rows_array(); + for (int p = a.last_row(); p > 0; p = a.pred_row(p)) + { + const TRectype& pag = a.row(p); // Riga pagamento + const TRiga_partite& sum = game.riga(p); // Riga partite + const TImporto imp(sum.get_char(PART_SEZ), pag.get_real(imp_field)); + totale += imp; + } + + return totale; +} + +// Calcola l'importo da pagare (eventualmente in valuta) +TImporto TRiga_scadenze::importo_da_pagare(bool val) const +{ + const char* imp_field = in_valuta() && val ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + const TRiga_partite& r = riga(); // Riga fattura + const TImporto totale(r.get_char(PART_SEZ), get_real(imp_field)); + return totale; +} + +// Calcola l'abbuono della rata e ritorna il suo tipo: +// 'A' abbuono attivo; 'P' abbuono passivo +// La sezione dell'abbuono calcolato e' quella della riga contabile in cui finira' +char TRiga_scadenze::calcola_abbuono(TImporto& abbuono, bool val) const +{ + bool ap = ' '; + if (pagata()) + { + abbuono = importo_da_pagare(TRUE); + abbuono += importo_pagato(TRUE); + + const int sign = abbuono.valore().sign(); + if (sign != 0) + { + if (sign > 0) + ap = abbuono.sezione() == 'D' ? 'P' : 'A'; + else + ap = abbuono.sezione() == 'D' ? 'A' : 'P'; + } + + if (val && in_valuta()) + { + abbuono.valore() *= get_real(SCAD_CAMBIO); + abbuono.valore().round(); + } + } + else + abbuono.valore() = ZERO; + + return ap; +} + +// Calcola la differenza cambi con la sezione da mettere nella riga contabile corrispondente +TImporto TRiga_scadenze::calcola_differenza_cambio(bool update) +{ + TImporto diffcam; + const int riga_saldo = pagata(); + if (riga_saldo > 0) + { + TRectype& pag = row(riga_saldo, FALSE); + const TRiga_partite& sum = partita().riga(riga_saldo); + const char sez = sum.sezione(); + + if (update) + { + diffcam = importo_da_pagare(FALSE); + diffcam += importo_pagato(FALSE); + + real a = pag.get_real(PAGSCA_ABBUONI); + if (in_valuta()) + { + a *= get_real(SCAD_CAMBIO); + a.round(); + } + + const TImporto abb_lit(sez, a); + diffcam += abb_lit; + diffcam.normalize(sez); + pag.put(PAGSCA_DIFFCAM, diffcam.valore()); + } + else + { + diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM)); + } + } + return diffcam; +} + +real TRiga_scadenze::residuo() const +{ + const char* imp_field = get(SCAD_CODVAL).not_empty() ? SCAD_IMPORTOVAL : SCAD_IMPORTO; + const real da_pagare(get(imp_field)); + const real pagato(get(SCAD_IMPORTOPAG)); + const real residuo = da_pagare - pagato; + return residuo; +} + + +bool TRiga_scadenze::modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam) +{ + const int nrigp = new_pag.get_int(PAGSCA_NRIGP); + const TRectype old_pag(row(nrigp)); + TRiga_partite& sum = partita().riga(nrigp); + + old_ap = calcola_abbuono(old_abb, FALSE); + old_diffcam = calcola_differenza_cambio(FALSE); + + const char* imp_field = get(SCAD_CODVAL).not_empty() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO; + const real importo(new_pag.get(imp_field)); + const bool empty = importo.is_zero(); + if (empty) + rows_array().destroy_row(nrigp); + else + row(nrigp, FALSE) = new_pag; + + TImporto abbuono; + new_ap = calcola_abbuono(abbuono, TRUE); // Calcolo abbuono in valuta + + TImporto imp(abbuono); imp.swap_section(); + imp.normalize(sum.sezione()); + if (new_ap != ' ') + { + CHECK(nrigp == pagata(), "Aggiornamento abbuoni inconsistente"); + TRectype& pag = row(nrigp, FALSE); + pag.put(PAGSCA_ABBUONI, imp.valore()); + + new_abb = abbuono; + if (in_valuta()) + { + new_abb.valore() *= get_real(SCAD_CAMBIO); + new_abb.valore().round(); + } + } + else + new_abb.valore() = ZERO; + + sum.update(old_abb, new_abb, PART_SEZABB, PART_ABBUONI); + + new_diffcam = calcola_differenza_cambio(TRUE); + sum.update(old_diffcam, new_diffcam, PART_SEZDIFCAM, PART_DIFFCAM); + + sum.update(old_pag, new_pag, PART_IMPORTO); + sum.update(old_pag, new_pag, PART_IMPORTOVAL); + sum.update(old_pag, new_pag, PART_RITENUTE); + + return empty; +} + +/////////////////////////////////////////////////////////// +// TRiga_partite +/////////////////////////////////////////////////////////// + +TRiga_partite::TRiga_partite(TPartita* game) + : TTree_rectype(LF_PARTITE, LF_SCADENZE, "NRATA"), _partita(game) +{ + CHECK(_partita, "Partita nulla"); +} + +TRiga_partite::TRiga_partite(const TRiga_partite& r) + : TTree_rectype(r), _partita(r._partita) +{ + CHECK(_partita, "Partita nulla"); +} + + +int TRiga_partite::read(TBaseisamfile& f, word op) +{ + int err = TRectype::read(f, op); + if (err == NOERR && get_int(PART_TIPOMOV) == 1) + { + TRiga_scadenze* s = new TRiga_scadenze(this); + copy_key_to_row(*s); + err = _recarr.read(s); // Deve esistere almento una scadenza +#ifdef DBG + if (_recarr.rows() == 0) + yesnofatal_box("Riga di fattura senza nessuna scadenza"); +#endif + } + else + _recarr.destroy_rows(); + return err; +} + +int TRiga_partite::ultimo_pagamento(int r) const +{ + const TRiga_scadenze& s = rata(r); + return s.rows_array().last_row(); +} + +bool TRiga_partite::update(const TRectype& vec, const TRectype& nuo, const char* field) +{ + real totale(get(field)); + totale -= vec.get_real(field); + totale += nuo.get_real(field); + put(field, totale); + return totale.is_zero(); +} + +bool TRiga_partite::update(const TImporto& vec, const TImporto& nuo, + const char* sez, const char* val) +{ + bool zero = FALSE; + TImporto grow(nuo); grow -= vec; // Variazione al totale + + if (!grow.is_zero()) + { + const char sezione = get_char(sez); // Sezione del totale + TImporto totale; + if (sezione > ' ') // Se c'era una sezione (e quindi un importo) ... + totale.set(sezione, get_real(val)); // ... inizializza il totale + else + CHECKS(vec.is_zero(), "Sezione errata per l'importo ", val); + totale += grow; // incrementa il totale + totale.normalize(); + put(sez, totale.sezione()); // Aggiorna il totale sul record + put(val, totale.valore()); + zero = totale.is_zero(); + } + else + zero = get_real(val).is_zero(); + + return zero; +} + + + +/////////////////////////////////////////////////////////// +// TPartita +/////////////////////////////////////////////////////////// + +TPartita::TPartita(const TBill& clifo, int anno, const char* num) + : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") +{ + read(clifo, anno, num); +} + +TPartita::TPartita() + : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP") +{} + +// Costruisce le righe della partita +bool TPartita::read(const TBill& clifo, int anno, const char* num) +{ + TRiga_partite* partita = new TRiga_partite(this); // Record campione della partita + partita->put(PART_TIPOCF, clifo.tipo()); // Tipo clifo + if (clifo.tipo() <= ' ') + { + partita->put(PART_GRUPPO, clifo.gruppo()); // Scrivi gruppo e conto solamente + partita->put(PART_CONTO, clifo.conto()); // nei conti normali (no clifo) + } + partita->put(PART_SOTTOCONTO, clifo.sottoconto()); // Sottoconto o codice clifo + partita->put(PART_ANNO, anno); // Anno partita + partita->put(PART_NUMPART, num); // Numero partita + _part.read(partita); + +#ifdef DBG + for (int p = last(); p > 0; p = pred(p)) + CHECKD(riga(p)._partita == this, "Riga partite inconsistente", p); +#endif + + TRectype unas(LF_PAGSCA); // Record campione pagamenti non assegnati + unas.zero(); + unas.put(PART_TIPOCF, partita->get(PART_TIPOCF)); // Copia chiave partite + unas.put(PART_GRUPPO, partita->get(PART_GRUPPO)); + unas.put(PART_CONTO, partita->get(PART_CONTO)); + unas.put(PART_SOTTOCONTO, partita->get(PART_SOTTOCONTO)); + unas.put(PART_ANNO, partita->get(PART_ANNO)); + unas.put(PART_NUMPART, partita->get(PART_NUMPART)); + unas.put(PART_NRIGA, 0); // Numeri magici di non assegamento + unas.put(SCAD_NRATA, 0); + _unassigned.read(unas); + + return ok(); +} + +bool TPartita::reread() +{ + TBill zio; + conto(zio); + const int year = anno(); + const TString16 num = numero(); + return read(zio, year, num); +} + +bool TPartita::write(bool re) +{ + const bool ok = _part.write(re); + return ok; +} + +TImporto TPartita::importo_speso(long nreg, int numrig) const +{ + TImporto imp; + + for (int r = _part.last_row(); r > 0; r = pred(r)) + { + const TRectype& pag = riga(r); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + const int num = pag.get_int(PART_NUMRIG); + if (num == numrig) + { + imp = TImporto(pag.get_char(PART_SEZ), pag.get_real(PART_IMPORTO)); + break; + } + } + } + + return imp; +} + + +void TPartita::update_reg_num(long nreg, const TRectype& mov) +{ + for (int r = _part.last_row(); r > 0; r = pred(r)) + { + TRectype& pag = _part.row(r, FALSE); + + const long reg = pag.get_long(PART_NREG); + if (reg == nreg) + { + pag.put(PART_NREG, mov.get(MOV_NUMREG)); + pag.put(PART_DATAREG, mov.get(MOV_DATAREG)); + pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC)); + pag.put(PART_DATADOC, mov.get(MOV_DATADOC)); + } + } +} + +// Calcola la riga di movimento relativa a una riga partita +int TPartita::rig2mov(int rp) const +{ + const TRiga_partite& r = riga(rp); + return r.get_int(PART_NUMRIG); +} + +// Calcola la riga di partita relativa a una riga movimento +int TPartita::mov2rig(long numreg, int rm) const +{ + for (int r = _part.last_row(); r > 0; r = pred(r)) + { + const TRiga_partite& row = riga(r); + if (row.get_long(PART_NREG) == numreg && row.get_int(PART_NUMRIG) == rm) + return r; + } + return -1; +} + +// Trova la prima riga della partita contenente una fattura +int TPartita::prima_fattura() const +{ + const int lastrow = last(); + for (int r = first(); r <= lastrow; r = succ(r)) + { + const TRiga_partite& row = riga(r); + const int tipomov = row.get_int(PART_TIPOMOV); + if (tipomov == 1 || tipomov == 2) + return r; + } + return -1; +} + +void TPartita::calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const +{ + doc = pag = imp = TImporto('D', ZERO); + + for (int r = _part.last_row(); r > 0; r = pred(r)) + { + const TRiga_partite& row = riga(r); + TImporto i(row.get_char(PART_SEZ), row.get_real(PART_IMPORTO)); + switch (row.get_int(PART_TIPOMOV)) + { + case 1: + case 2: + doc += i; // documenti + break; + case 3: + pag += i; // pagamenti + break; + default: + imp += i; // altri importi + break; + } + + i.set(row.get_char(PART_SEZ), row.get_real(PART_ABBUONI)); + imp += i; + + i.set(row.get_char(PART_SEZ), row.get_real(PART_DIFFCAM)); + imp += i; + } + + saldo = doc; + saldo += pag; + saldo += imp; +} + + +bool TPartita::utilizzata(int nrigp) const +{ + for (int p = _part.last_row(); p > 0; p = pred(p)) + { + const TRiga_partite& fatt = riga(p); + const int tipomov = fatt.get_int(PART_TIPOMOV); + if (tipomov == 1) + { + for (int r = fatt.rate(); r > 0; r--) + { + const TRiga_scadenze& scad = fatt.rata(r); + if (scad.rows_array().exist(nrigp)) + return TRUE; + } + } + } + return FALSE; +} + +bool TPartita::modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam) +{ + const int nriga = new_pag.get_int(PAGSCA_NRIGA); + const TRiga_partite& fattura = riga(nriga); + + const int nrata = new_pag.get_int(PAGSCA_NRATA); + TRiga_scadenze& scaden = fattura.rata(nrata); + + const int nrigp = new_pag.get_int(PAGSCA_NRIGP); + const TRectype& old_pag = scaden.row(nrigp); + + const bool empty = scaden.modifica_pagamento(new_pag, + old_ap, old_abb, old_diffcam, + new_ap, new_abb, new_diffcam); + + if (empty && !utilizzata(nrigp)) + _part.destroy_row(nrigp); + + return empty; +} + +/////////////////////////////////////////////////////////// +// TPartite_array +/////////////////////////////////////////////////////////// + +// Certified 99% +const TString& TPartite_array::key(const TBill& clifo, int anno, const char* num) +{ + if (clifo.tipo() > ' ') + _key.format("%c%3d%3d%6ld%4d%s", clifo.tipo(), 0, 0, clifo.sottoconto(), anno, num); + else + _key.format("%c%3d%3d%6ld%4d%s", + clifo.tipo(), clifo.gruppo(), clifo.conto(), clifo.sottoconto(), anno, num); + return _key; +} + +// Certified 99% +TPartita* TPartite_array::find(const TBill& clifo, int anno, const char* num, bool create) +{ + const TString& k = key(clifo, anno, num); + TPartita* p = (TPartita*)objptr(k); + if (p == NULL && create) + { + p = new TPartita(clifo, anno, num); + if (p->ok()) + add(k, p); + else + { + delete p; + p = NULL; + } + } + return p; +} + +TPartita* TPartite_array::find(const TRectype& r, bool create) +{ + TBill zio; zio.get(r); + const int anno = r.get_int(PART_ANNO); + const char* num = r.get_str(PART_NUMPART); + return find(zio, anno, num, create); +} + +TPartita& TPartite_array::partita(const TBill& clifo, int anno, const char* num) +{ + TPartita* game = find(clifo, anno, num, TRUE); + CHECKS(game, "Partita errata ", num); + return *game; +} + +TPartita& TPartite_array::partita(const TRectype& r) +{ + TPartita* game = find(r, TRUE); + CHECK(game, "Partita errata"); + return *game; +} + +bool TPartite_array::write(bool re) +{ + int err = NOERR; + + TPartita* game; + restart(); + while ((game = (TPartita*)get()) != NULL) + { + err = game->write(re); + if (err != NOERR) // L'errore viene gia' segnalato dalla partita + break; + } + + return err == NOERR; +} + +// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg +int TPartite_array::add_reg_num(long nreg, int numrig) +{ + TRelation rel(LF_PARTITE); + TRectype& part = rel.lfile().curr(); + + // Costruzione filtro del cursore + part.zero(); + part.put(PART_NREG, nreg); + if (numrig > 0) + part.put(PART_NUMRIG, numrig); + + const TRectype filter(part); + + TCursor cur(&rel, "", 2, &filter, &filter); + + for (cur = 0; cur.ok(); ++cur) + partita(part); // Aggiungi partita se non esiste gia' + + return (int)cur.items(); +} + +TImporto TPartite_array::importo_speso(long nreg, int numrig) +{ + TImporto imp; + add_reg_num(nreg, numrig); + for (TPartita* game = first(); game; game = next()) + imp += game->importo_speso(nreg, numrig); + return imp; +} + +void TPartite_array::update_reg_num(long nreg, const TRectype& mov) +{ + add_reg_num(nreg, 0); + for (TPartita* game = first(); game; game = next()) + game->update_reg_num(nreg, mov); +} + \ No newline at end of file diff --git a/cg/pagament.h b/cg/pagament.h index 95192e210..3ca84b1eb 100755 --- a/cg/pagament.h +++ b/cg/pagament.h @@ -1,347 +1,351 @@ -#ifndef __PAGAMENT_H -#define __PAGAMENT_H - -#ifndef __ASSOC_H -#include -#endif - -#ifndef __MSKSHEET_H -#include -#endif - -#ifndef __RELATION_H -#include -#endif - -#ifndef __TABUTIL_H -#include -#endif - -#ifndef __CONTO_H -#include "conto.h" -#endif - -// Error codes for pagation -const word P_OK = 0x0000; // ok -const word P_RSUM = 0x0001; // percentages do not sum up to 100 -const word P_IMPNC = 0x0002; // inconsistenza percentuali / importi -const word P_SCAD = 0x0004; // scadenze non consecutive -const word P_INIZIO = 0x0008; // data 1a rata < data inizio pagamenti - -class TPagamento : public TObject -{ - TString _code; // codice - TString _name; // descrizione - real _imponibile; // imponibile da affettare - real _imposta; // imposta da affettare - real _spese; // spese da affettare - TDistrib _slicer; // affettatrice - bool _new; // non letto da database - TArray _rate; // rate medesime - char _inscad; // inizio scadenze: S1 - bool _mcomm; // mese commerciale: B0 - bool _rdiff; // rate differenziate: B1 - int _tpr; // tipo prima rata: S3 - bool _dirty; // modificato (strutturalmente!) - TDate _inizio; // data inizio pagamenti - bool _inited; // vero se c'e' un movimento di riferimento - real _firstr; // importo da pagare in prima rata (o distribuire se tpr == 0) - real _secndr; // importo da distribuire - - int _fixd[3]; // giorni scadenza fissa, se desiderati - int _round; // decimali arrotondamento importo - int _int_rate; - - int _rata_ifield(int n, int f) const; - real _rata_rfield(int n, int f) const; - TDate _rata_dfield(int n, int f) const; - const char* _rata_sfield(int n, int f) const; - - int _def_tpr; // tipo rata default - TString16 _def_ulc; // ulteriore classificazione default - -public: - - // pregasi notare la straordinaria dovizia di const - int n_rate() const { return _rate.items(); } - bool is_new() const { return _new; } - bool dirty() const { return _dirty; } - - real imponibile() const { return _imponibile; } - real imposta() const { return _imposta; } - real spese() const { return _spese; } - - int tipo_rata(int n) const { return _rata_ifield(n,2);} - real perc_rata(int n) const { return _rata_rfield(n,1);} - int scad_rata(int n) const { return _rata_ifield(n,0);} - TDate data_rata(int n) const { return _rata_dfield(n,3);} - real tpay_rata(int n) const { return _rata_rfield(n,4);} - const char* ulc_rata(int n) const { return _rata_sfield(n,5);} - char inizio_scadenza() const { return _inscad; } - bool mese_commerciale() const { return _mcomm; } - bool rate_differenziate() const { return _rdiff; } - int tipo_prima_rata() const { return _tpr; } - int decs() const { return _round; } - - // mi scuso per la mancanza di underscore, ma mi piaceva cosi' - bool ratapagata(int n); - - const TString& name() const { return _name; } - const TString& code() const { return _code; } - const char* desc_tpr() const; - const char* desc_tipo(int) const; - - // giorni scadenza fissi, aggiunti poi - void set_fixed_scad(int a, int ind) { _fixd[ind] = a; } - - // queste vengono usate solo per movimenti editabili nella struttura - // (da tabella pagamenti) e riaggiustano tutte le rate in accordo - // con il parametro modificato - void set_intervallo_rate(int i); - void set_mese_commerciale(bool v, int& sscad); - void set_rate_differenziate(int v); - void set_tipo_prima_rata(int v, int sscad = -1); - void set_numero_rate(int n, int sscad = -1); - - void set_inizio_scadenza(char v) { _inscad = v; } - void set_code(const char* c) { _code = c; } - void set_round(int n) { _round = n; } - - // check consistency: returns word with errors flagged, 0 if ok - word validate() const; - void strerr(word err, TString& s); - - // read/write from database - // relapp passa i files, se no vengono aperti - bool read(TTable* cpg = NULL, TTable* rpg = NULL); - - // chiamabili solo da relapp, agiscono solo su %RPG - int write(TTable& rpg); - int rewrite(TTable& rpg); - int remove(TTable& rpg); - - // modifica rate manualmente o non - TToken_string& rata(int r) { return (TToken_string&)_rate[r]; } - TToken_string& add_rata (real perc, int day, int type, const char* ulc = ""); - TToken_string& set_rata (int index, real perc, int day, int type, - const char* ulc = NULL, const char* imp = NULL, - const char* data = NULL); - // questa calcola percentuali e scadenze a partire dagli importi - TToken_string& set_rata (int index, const real& howmuch, const TDate& date, int type, - const char* ulc, bool pagato); - - // settano tipo rata e ult. class default per le rate; se bool = TRUE - // modificano anche le eventuali rate esistenti - void set_default_type(int type, bool change_existing = TRUE); - void set_default_ulc(const char* ulc, bool change_existing = TRUE); - - void remove_rata(int r); - void zap_rate () { _rate.destroy(); } - // calcola le rate automaticamente secondo quanto specificato - void set_rate_auto(); - // data una rata esistente, riaggiusta gli importi usando lo slicer e - // le scadenze usando la data di inizio - void set_imprata(int i, real r); - - // slicer interface - void set_total(const real& ib, const real& im, const real& sp); - - // istanzia uno sheet field come diobue comanda - void set_sheet(TSheet_field& sf, int sscad = -1); - // ricalcola automaticamente tutto il ricalcolabile - // alla modifica di una percentuale (o di un importo) - // ritorna TRUE se non si poteva; non occorre che sia inizializzato - // con un importo - word recalc_rate(int row, bool is_perc_modified, const char* new_value, - const char* scad, const char* typ, int rdiff, - bool mcomm, bool& need_recalc); - - // determina la prossima scadenza - void next_scad(TDate& d, int scad, bool mcomm, int rata); - - // se codtab non e' NULL legge da file (e da' errore se non c'e') - // se si vuole fare un pagamento nuovo si da' il codice con set_code - TPagamento(const char* codtab = NULL, const char* data = NULL); - virtual ~TPagamento() {} -}; - - -#ifndef __PARTITE_H -#include -#endif - -class TTree_rectype : public TRectype -{ -protected: - TRecord_array _recarr; - - void copy_key_to_row(TRectype& row) const; - int fill_array(); - -protected: // TRectype - virtual TObject* dup() const; - - virtual int read(TBaseisamfile& f, word op = _isequal); - virtual int next(TBaseisamfile& f); - virtual int write(TBaseisamfile& f) const; - virtual int rewrite(TBaseisamfile& f) const; - virtual int remove(TBaseisamfile& f); - -public: - const TRecord_array& rows_array() const { return _recarr; } - TRecord_array& rows_array() { return _recarr; } - const TRectype& row(int r) const { return ((TRecord_array&)_recarr).row(r, FALSE); } - TRectype& row(int r, bool create) { return _recarr.row(r, create); } - - TTree_rectype(const TRectype& testata, const TRectype& riga, const char* num); - TTree_rectype(int testata, int riga, const char* num); - TTree_rectype(const TTree_rectype& t); - virtual ~TTree_rectype() {} -}; - - -class TRiga_scadenze : public TTree_rectype -{ - friend class TPartita; - friend class TRiga_partite; - - TRiga_partite* _riga; - -protected: - char calcola_abbuono(TImporto& abbuono, bool val) const; - TImporto calcola_differenza_cambio(bool update); - - bool modifica_pagamento(const TRectype& new_pag, - char& old_ap, TImporto& old_abb, TImporto& old_diffcam, - char& new_ap, TImporto& new_abb, TImporto& new_diffcam); - -protected: // TRecord_tree - virtual TObject* dup() const { return new TRiga_scadenze(*this); } - -public: - int pagata() const; // Riga che chiude la rata o 0 se non pagata completamente - - real residuo() const; - - bool in_valuta() const; - - TPartita& partita() const; - TRiga_partite& riga() const { CHECK(_riga, "Riga nulla"); return *_riga; } // Riga partite - - TImporto importo_pagato(bool val) const; - TImporto importo_da_pagare(bool val) const; - - TRiga_scadenze(TRiga_partite* riga); - TRiga_scadenze(const TRiga_scadenze& s); - virtual ~TRiga_scadenze() {} -}; - -class TRiga_partite : public TTree_rectype -{ - friend class TPartita; - friend class TRiga_scadenze; - TPartita* _partita; - -protected: - bool update(const TRectype& vec, const TRectype& nuo, const char* field); - -public: // TTree_rectype - virtual TObject* dup() const { return new TRiga_partite(*this); } - virtual int read(TBaseisamfile& f, word op); - -public: - int rate() const { return _recarr.rows(); } - TRiga_scadenze& rata(int r) const { return (TRiga_scadenze&)_recarr.row(r); } - - int ultimo_pagamento(int rata) const; - char sezione() const { return get_char("SEZ"); } - - TPartita& partita() const { CHECK(_partita, "Partita nulla"); return *_partita; } - - TRiga_partite(TPartita* game); - TRiga_partite(const TRiga_partite& r); - virtual ~TRiga_partite() {} -}; - -class TPartita : public TObject -{ - TRecord_array _part; - TRecord_array _unassigned; - -public: // TObject - virtual bool ok() const { return _part.rows() > 0; } - -public: - TRiga_partite& riga(int r) const { return (TRiga_partite&)_part.row(r); } - TRiga_partite& nuova_riga() { return (TRiga_partite&)_part.row(last()+1, TRUE); } - - int succ(int r) const { return _part.succ_row(r); } - int pred(int r) const { return _part.pred_row(r); } - int first() const { return _part.first_row(); } - int last() const { return _part.last_row(); } - - bool reread(); - bool read(const TBill& clifo, int anno, const char* num); - bool write(bool re = FALSE); - bool rewrite() { return write(TRUE); } - - int mov2rig(long nreg, int rmov) const; - int rig2mov(int rmov) const; - int prima_fattura() const; - bool utilizzata(int r) const; // Controlla se esistono pagamenti sommati alla riga r - - void conto(TBill& c) const { c.get(_part.key()); } - int anno() const { return _part.key().get_int(PART_ANNO); } - const TString& numero() const { return _part.key().get(PART_NUMPART); } - const TString& descrizione() const { return _part.key().get(PART_DESCR); } - - TImporto importo_speso(long numreg, int numrig) const; - void update_reg_num(long nreg, const TRectype& mov); - void calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const; - - bool modifica_pagamento(const TRectype& new_pag, - char& old_ap, TImporto& old_abb, TImporto& old_diffcam, - char& new_ap, TImporto& new_abb, TImporto& new_diffcam); - - TPartita(const TBill& clifo, int anno, const char* num); - TPartita(); -}; - - -class TPartite_array : private TAssoc_array -{ - TString80 _key; // Work string - -protected: - const TString& key(const TBill& clifo, int anno, const char* num); // Build key for TAssoc_array - TPartita* find(const TBill& clifo, int anno, const char* numero, bool create); - TPartita* find(const TRectype& part, bool create); - -public: // TAssoc_array - virtual void destroy() { TAssoc_array::destroy(); } - -public: - TPartita& partita(const TBill& clifo, int anno, const char* numero); - TPartita& partita(const TRectype& r); - - TPartita* exist(const TBill& clifo, int anno, const char* numero) const - { return ((TPartite_array*)this)->find(clifo, anno, numero, FALSE); } - - TPartita* exist(const TRectype& part) const - { return ((TPartite_array*)this)->find(part, FALSE); } - - bool write(bool re = FALSE); - bool rewrite() { return write(TRUE); } - - int add_reg_num(long numreg, int numrig); - TImporto importo_speso(long numreg, int numrig); - void update_reg_num(long nreg, const TRectype& mov); - - TPartita* first() { restart(); return next(); } - TPartita* next() { return (TPartita*)get(); } - - TPartite_array() {} - virtual ~TPartite_array() {} -}; - -#endif +#ifndef __PAGAMENT_H +#define __PAGAMENT_H + +#ifndef __ASSOC_H +#include +#endif + +#ifndef __MSKSHEET_H +#include +#endif + +#ifndef __RELATION_H +#include +#endif + +#ifndef __TABUTIL_H +#include +#endif + +#ifndef __CONTO_H +#include "conto.h" +#endif + +// Error codes for pagation +const word P_OK = 0x0000; // ok +const word P_RSUM = 0x0001; // percentages do not sum up to 100 +const word P_IMPNC = 0x0002; // inconsistenza percentuali / importi +const word P_SCAD = 0x0004; // scadenze non consecutive +const word P_INIZIO = 0x0008; // data 1a rata < data inizio pagamenti + +class TPagamento : public TObject +{ + TString _code; // codice + TString _name; // descrizione + real _imponibile; // imponibile da affettare + real _imposta; // imposta da affettare + real _spese; // spese da affettare + TDistrib _slicer; // affettatrice + bool _new; // non letto da database + TArray _rate; // rate medesime + char _inscad; // inizio scadenze: S1 + bool _mcomm; // mese commerciale: B0 + bool _rdiff; // rate differenziate: B1 + int _tpr; // tipo prima rata: S3 + bool _dirty; // modificato (strutturalmente!) + TDate _inizio; // data inizio pagamenti + bool _inited; // vero se c'e' un movimento di riferimento + real _firstr; // importo da pagare in prima rata (o distribuire se tpr == 0) + real _secndr; // importo da distribuire + + int _fixd[3]; // giorni scadenza fissa, se desiderati + int _round; // decimali arrotondamento importo + int _int_rate; + + int _rata_ifield(int n, int f) const; + real _rata_rfield(int n, int f) const; + TDate _rata_dfield(int n, int f) const; + const char* _rata_sfield(int n, int f) const; + + int _def_tpr; // tipo rata default + TString16 _def_ulc; // ulteriore classificazione default + +public: + + // pregasi notare la straordinaria dovizia di const + int n_rate() const { return _rate.items(); } + bool is_new() const { return _new; } + bool dirty() const { return _dirty; } + + real imponibile() const { return _imponibile; } + real imposta() const { return _imposta; } + real spese() const { return _spese; } + + int tipo_rata(int n) const { return _rata_ifield(n,2);} + real perc_rata(int n) const { return _rata_rfield(n,1);} + int scad_rata(int n) const { return _rata_ifield(n,0);} + TDate data_rata(int n) const { return _rata_dfield(n,3);} + real tpay_rata(int n) const { return _rata_rfield(n,4);} + const char* ulc_rata(int n) const { return _rata_sfield(n,5);} + char inizio_scadenza() const { return _inscad; } + bool mese_commerciale() const { return _mcomm; } + bool rate_differenziate() const { return _rdiff; } + int tipo_prima_rata() const { return _tpr; } + int decs() const { return _round; } + + // mi scuso per la mancanza di underscore, ma mi piaceva cosi' + bool ratapagata(int n); + + const TString& name() const { return _name; } + const TString& code() const { return _code; } + const char* desc_tpr() const; + const char* desc_tipo(int) const; + + // giorni scadenza fissi, aggiunti poi + void set_fixed_scad(int a, int ind) { _fixd[ind] = a; } + + // queste vengono usate solo per movimenti editabili nella struttura + // (da tabella pagamenti) e riaggiustano tutte le rate in accordo + // con il parametro modificato + void set_intervallo_rate(int i); + void set_mese_commerciale(bool v, int& sscad); + void set_rate_differenziate(int v); + void set_tipo_prima_rata(int v, int sscad = -1); + void set_numero_rate(int n, int sscad = -1); + + void set_inizio_scadenza(char v) { _inscad = v; } + void set_code(const char* c) { _code = c; } + void set_round(int n) { _round = n; } + + // check consistency: returns word with errors flagged, 0 if ok + word validate() const; + void strerr(word err, TString& s); + + // read/write from database + // relapp passa i files, se no vengono aperti + bool read(TTable* cpg = NULL, TTable* rpg = NULL); + + // chiamabili solo da relapp, agiscono solo su %RPG + int write(TTable& rpg); + int rewrite(TTable& rpg); + int remove(TTable& rpg); + + // modifica rate manualmente o non + TToken_string& rata(int r) { return (TToken_string&)_rate[r]; } + TToken_string& add_rata (real perc, int day, int type, const char* ulc = ""); + TToken_string& set_rata (int index, real perc, int day, int type, + const char* ulc = NULL, const char* imp = NULL, + const char* data = NULL); + // questa calcola percentuali e scadenze a partire dagli importi + TToken_string& set_rata (int index, const real& howmuch, const TDate& date, int type, + const char* ulc, bool pagato); + + // settano tipo rata e ult. class default per le rate; se bool = TRUE + // modificano anche le eventuali rate esistenti + void set_default_type(int type, bool change_existing = TRUE); + void set_default_ulc(const char* ulc, bool change_existing = TRUE); + + void remove_rata(int r); + void zap_rate () { _rate.destroy(); } + // calcola le rate automaticamente secondo quanto specificato + void set_rate_auto(); + // data una rata esistente, riaggiusta gli importi usando lo slicer e + // le scadenze usando la data di inizio + void set_imprata(int i, real r); + + // slicer interface + void set_total(const real& ib, const real& im, const real& sp); + + // istanzia uno sheet field come diobue comanda + void set_sheet(TSheet_field& sf, int sscad = -1); + // ricalcola automaticamente tutto il ricalcolabile + // alla modifica di una percentuale (o di un importo) + // ritorna TRUE se non si poteva; non occorre che sia inizializzato + // con un importo + word recalc_rate(int row, bool is_perc_modified, const char* new_value, + const char* scad, const char* typ, int rdiff, + bool mcomm, bool& need_recalc); + + // determina la prossima scadenza + void next_scad(TDate& d, int scad, bool mcomm, int rata); + + // se codtab non e' NULL legge da file (e da' errore se non c'e') + // se si vuole fare un pagamento nuovo si da' il codice con set_code + TPagamento(const char* codtab = NULL, const char* data = NULL); + virtual ~TPagamento() {} +}; + + +#ifndef __PARTITE_H +#include +#endif + +class TTree_rectype : public TRectype +{ +protected: + TRecord_array _recarr; + + void copy_key_to_row(TRectype& row) const; + int fill_array(); + +protected: // TRectype + virtual TObject* dup() const; + + virtual int read(TBaseisamfile& f, word op = _isequal); + virtual int next(TBaseisamfile& f); + virtual int write(TBaseisamfile& f) const; + virtual int rewrite(TBaseisamfile& f) const; + virtual int remove(TBaseisamfile& f); + +public: + const TRecord_array& rows_array() const { return _recarr; } + TRecord_array& rows_array() { return _recarr; } + const TRectype& row(int r) const { return ((TRecord_array&)_recarr).row(r, FALSE); } + TRectype& row(int r, bool create) { return _recarr.row(r, create); } + + int last() const { return _recarr.last_row(); } + int pred(int r) const { return _recarr.pred_row(r); } + + TTree_rectype(const TRectype& testata, const TRectype& riga, const char* num); + TTree_rectype(int testata, int riga, const char* num); + TTree_rectype(const TTree_rectype& t); + virtual ~TTree_rectype() {} +}; + + +class TRiga_scadenze : public TTree_rectype +{ + friend class TPartita; + friend class TRiga_partite; + + TRiga_partite* _riga; + +protected: + char calcola_abbuono(TImporto& abbuono, bool val) const; + TImporto calcola_differenza_cambio(bool update); + + bool modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam); + +protected: // TRecord_tree + virtual TObject* dup() const { return new TRiga_scadenze(*this); } + +public: + int pagata() const; // Riga che chiude la rata o 0 se non pagata completamente + + real residuo() const; + + bool in_valuta() const; + + TPartita& partita() const; + TRiga_partite& riga() const { CHECK(_riga, "Riga nulla"); return *_riga; } // Riga partite + + TImporto importo_pagato(bool val) const; + TImporto importo_da_pagare(bool val) const; + + TRiga_scadenze(TRiga_partite* riga); + TRiga_scadenze(const TRiga_scadenze& s); + virtual ~TRiga_scadenze() {} +}; + +class TRiga_partite : public TTree_rectype +{ + friend class TPartita; + friend class TRiga_scadenze; + TPartita* _partita; + +protected: + bool update(const TRectype& vec, const TRectype& nuo, const char* field); + bool update(const TImporto& vec, const TImporto& nuo, const char* sez, const char* val); + +public: // TTree_rectype + virtual TObject* dup() const { return new TRiga_partite(*this); } + virtual int read(TBaseisamfile& f, word op); + +public: + int rate() const { return _recarr.rows(); } + TRiga_scadenze& rata(int r) const { return (TRiga_scadenze&)_recarr.row(r); } + + int ultimo_pagamento(int rata) const; + char sezione() const { return get_char("SEZ"); } + + TPartita& partita() const { CHECK(_partita, "Partita nulla"); return *_partita; } + + TRiga_partite(TPartita* game); + TRiga_partite(const TRiga_partite& r); + virtual ~TRiga_partite() {} +}; + +class TPartita : public TObject +{ + TRecord_array _part; + TRecord_array _unassigned; + +public: // TObject + virtual bool ok() const { return _part.rows() > 0; } + +public: + TRiga_partite& riga(int r) const { return (TRiga_partite&)_part.row(r); } + TRiga_partite& nuova_riga() { return (TRiga_partite&)_part.row(last()+1, TRUE); } + + int succ(int r) const { return _part.succ_row(r); } + int pred(int r) const { return _part.pred_row(r); } + int first() const { return _part.first_row(); } + int last() const { return _part.last_row(); } + + bool reread(); + bool read(const TBill& clifo, int anno, const char* num); + bool write(bool re = FALSE); + bool rewrite() { return write(TRUE); } + + int mov2rig(long nreg, int rmov) const; + int rig2mov(int rmov) const; + int prima_fattura() const; + bool utilizzata(int r) const; // Controlla se esistono pagamenti sommati alla riga r + + void conto(TBill& c) const { c.get(_part.key()); } + int anno() const { return _part.key().get_int(PART_ANNO); } + const TString& numero() const { return _part.key().get(PART_NUMPART); } + const TString& descrizione() const { return _part.key().get(PART_DESCR); } + + TImporto importo_speso(long numreg, int numrig) const; + void update_reg_num(long nreg, const TRectype& mov); + void calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const; + + bool modifica_pagamento(const TRectype& new_pag, + char& old_ap, TImporto& old_abb, TImporto& old_diffcam, + char& new_ap, TImporto& new_abb, TImporto& new_diffcam); + + TPartita(const TBill& clifo, int anno, const char* num); + TPartita(); +}; + + +class TPartite_array : private TAssoc_array +{ + TString80 _key; // Work string + +protected: + const TString& key(const TBill& clifo, int anno, const char* num); // Build key for TAssoc_array + TPartita* find(const TBill& clifo, int anno, const char* numero, bool create); + TPartita* find(const TRectype& part, bool create); + +public: // TAssoc_array + virtual void destroy() { TAssoc_array::destroy(); } + +public: + TPartita& partita(const TBill& clifo, int anno, const char* numero); + TPartita& partita(const TRectype& r); + + TPartita* exist(const TBill& clifo, int anno, const char* numero) const + { return ((TPartite_array*)this)->find(clifo, anno, numero, FALSE); } + + TPartita* exist(const TRectype& part) const + { return ((TPartite_array*)this)->find(part, FALSE); } + + bool write(bool re = FALSE); + bool rewrite() { return write(TRUE); } + + int add_reg_num(long numreg, int numrig); + TImporto importo_speso(long numreg, int numrig); + void update_reg_num(long nreg, const TRectype& mov); + + TPartita* first() { restart(); return next(); } + TPartita* next() { return (TPartita*)get(); } + + TPartite_array() {} + virtual ~TPartite_array() {} +}; + +#endif