#include "770100a.h" #include "770101.h" #include "770102.h" #include void TSchedaPercipienti::init_mask(TMask& m) { update_lasts(m); // se collegamento if (tipo_coll() != nessuno) { const bool variazione = coll_variazione(); if (!variazione) compila_testata(m); switch (tipo_coll()) { case pagamento: case occasionale: // Compilo riga di pagamento SOLO SE NON ce ne sono gia'.. if ( (tipo_coll() == pagamento && _rel->pag_items() == 0) || tipo_coll() == occasionale ) { const real totrit(m.get(F_TOTRIT)); const real totdoc(m.get(F_TOTDOC)); const real compenso(m.get(F_COMPENS)); const real spese(m.get(F_SPESE)); if ((tipo_coll() == pagamento && (_coll._compenso + totrit == totdoc) ) || (tipo_coll() == occasionale)) { TSheet_field& pags = pag_sheet_enabled(m); TRectype rpag(_rel->pag(0)); rpag.zero(); real& imponibile = _coll._compenso; rpag.put("DATAPAG", _coll._datadoc); rpag.put("COMPENSO", compenso); rpag.put("SPESA", spese); // Update spreadsheet rec2row(pags.row(0), rpag, 0); // ricalcolo riga pagamento TString16 codcau(m.get(F_CODCAUS)); TTable cau("%ca7"); cau.zero(); cau.put("CODTAB", codcau); if (cau.read() != NOERR) warning_box("Causale non presente in tabella"); const real h_PercAssImp = cau.get_real("R4"); const real h_PercCassaPrev = cau.get_real("R5"); const real h_PercRitenuta = cau.get_real("R0"); const real h_PercInps = cau.get_real("R1"); const real h_PercAssImpInps = cau.get_real("R2"); const real h_PercCommitInps = cau.get_real("R3"); Pag_struct c; Pag_struct s; TToken_string& t = pags.row(0); from_sheet_to_struct(t, s); calcola_riga_pag(s, c, TRUE, h_PercAssImp, h_PercCassaPrev, h_PercRitenuta, h_PercInps, h_PercAssImpInps, h_PercCommitInps); from_struct_to_sheet(s, t); // forzo ridisegno sheet pags.force_update(); } } default: // per evitare di riscrivere tutto dopo registra _coll._tipo_coll = nessuno; break; } } fill_sheet(m); } bool TSchedaPercipienti::vers_notify(TSheet_field& s, int r, KEY k) { switch(k) { // Inserimento riga case K_INS: // Impedisce inserimento di nuove righe return FALSE; // Inizio modifica riga case K_SPACE: { // Pulisco descrizioni luogo e tipo versamento (solo se non gia' indicati!) TSheet_field& vers = app().vers(); TMask& mp = vers.sheet_mask(); TString16 tipo(mp.get(F_TIPOVERS)); TString16 luo (mp.get(F_LUOVERS)); if (tipo.empty()) mp.reset(70); if (luo.empty()) mp.reset(71); break; } default: break; } return TRUE; } bool TSchedaPercipienti::pags_notify(TSheet_field& s, int r, KEY k) { switch(k) { // Inserimento riga case K_INS: // Impedisce inserimento di nuove righe return FALSE; // Inizio modifica riga case K_SPACE: { break; } // Fine modifica di una riga case K_ENTER: break; default: break; } return TRUE; } TSheet_field& TSchedaPercipienti::pags() const { TSheet_field& s = pag_sheet_enabled(curr_mask()); return s; } TSheet_field& TSchedaPercipienti::vers() const { TSheet_field& s = (TSheet_field&)curr_mask().field(F_VERSAMENTI); return s; } bool TSchedaPercipienti::my_empty_items(TToken_string& r, bool vers) { TString rr; // controlla se riga versamento significativa if (vers) for (int i=0; i < COLONNE_SIGNIFICATIVE_SPREADSHEET_VERSAMENTI; i++) { rr = r.get(i); rr.trim(); switch (i) { case 0: // 1015 if (rr.not_empty()) return FALSE; break; case 1: if (rr.not_empty()) return FALSE; break; case 2: // lugo e tipo vers. case 3: if (rr.not_empty()) if (rr != "N") return FALSE; break; case 4: case 5: if (rr.not_empty()) return FALSE; break; case 6: if (rr.not_empty()) { real rrr(real::ita2eng(rr)); if (rrr != ZERO) return FALSE; } break; default: break; } } // controlla se riga pagamento significativa else { rr = r.get(token_pos("DATAPAG")); rr.trim(); if (rr.not_empty()) return FALSE; } return TRUE; } void TSchedaPercipienti::pag_pack() { TString_array& rows = pags().rows_array(); const int max = rows.items(); for (int i = 0; i < max; i++) { TToken_string& r = (TToken_string&)rows[i]; if (my_empty_items(r, FALSE)) // Remove all empty strings rows.destroy(i, FALSE); } rows.pack(); } void TSchedaPercipienti::ver_pack() { TString_array& rows = vers().rows_array(); const int max = rows.items(); for (int i = 0; i < max; i++) { TToken_string& r = (TToken_string&)rows[i]; if (my_empty_items(r, TRUE)) // Remove all empty strings rows.destroy(i, FALSE); } rows.pack(); } // Inizializza array sheet dei pagamenti void TSchedaPercipienti::load_pag_sheet(const long numvers) { real comp, spese, imp, ritpag; int i, iNumRigaAS; TSheet_field& pag = pags(); _pags->destroy(); // numero di riga dell'array-sheet. Viene incrementato // solo quando si trovano pagamenti 'giusti' (cioe' solo // quando si aggiungono elementi all'array-sheet) iNumRigaAS = 0; for ( i = 0; i < pag.items(); i++) { TToken_string* d = new TToken_string(64); TToken_string& riga = pag.row(i); // Scarto le righe non significative if (my_empty_items(riga, FALSE)) continue; const long nvers = riga.get_long(token_pos("NUMVERS")); // "Se il pagamento e' gia' stato selezionato DA UN ALTRO versamento // NON si deve vedere! " if (nvers > 0 && nvers != numvers) continue; const long npag = i; const int LARGHEZZA_COL = 15; TString80 dep; d->add(" "); // 0 spazio per la 'X' di selezione dep = riga.get(token_pos("DATAPAG")); d->add(dep); // 1 data pagamento comp = riga.get(token_pos("COMPENSO")); const TCurrency soldi_compenso(comp); dep = soldi_compenso.string(TRUE); dep.right_just(LARGHEZZA_COL); d->add(dep); // 2 compenso ritpag = riga.get(token_pos("RITENUTA")); const TCurrency soldi_ritenuta(ritpag); dep = soldi_ritenuta.string(TRUE); dep.right_just(LARGHEZZA_COL); d->add(dep); // 3 ritenuta d->add(i); // 4 numero riga d->add(nvers); // 5 numero versamento collegato _pags->add(*d); // aggiungo la riga nell'array_sheet // Setto il bit alla posizione numpag e metto la X if (nvers == numvers) { _selected.set(npag); _pags->check(iNumRigaAS, TRUE); } iNumRigaAS++; // ignoro in questo contatore i pagamenti che NON // si vedono (se il pagamento e' scartato prima di qui // non ci passa) } } void TSchedaPercipienti::attach_pag_vers (int pag, long numvers) { TSheet_field& pag_s = pags(); TToken_string& riga = pag_s.row(pag); // setta NUMVERS nello sheet riga.destroy(token_pos("NUMVERS")); riga.add(numvers, token_pos("NUMVERS")); // setta NUMVERS nel record _rel->pag(pag).put("NUMVERS", numvers); } void TSchedaPercipienti::detach_pag_vers (int pag) { TSheet_field& pag_s = pags(); TToken_string& riga = pag_s.row(pag); riga.destroy(token_pos("NUMVERS")); riga.add(-1L, token_pos("NUMVERS")); // setta NUMVERS nel record _rel->pag(pag).put("NUMVERS", -1L); } // // VERS_ATTACHED ( numvers ) // // Determina se c'e' ALMENO UN pagamento collegato al versamento NUMVERS // bool TSchedaPercipienti::vers_attached(const long numvers) { long numv = 0L; // Aggiorna lo sheet dei pagamenti per questo versamento app().load_pag_sheet(numvers); for (int j = 0; j < _pags->items(); j++) { // Leggo NUMVERS TToken_string& riga = _pags->row(j); numv = riga.get_long(AS_POS_NVER); if (numv > 0L) if (numv == numvers) return TRUE; } return FALSE; } // // CHECK_PAGAMENTI // Questo serve solo a impedire di uscire senza aver collegato almeno // un pagamento bool TSchedaPercipienti::check_pagamenti(TMask_field& f, KEY k) { const long numvers = get_numvers(f); return app().vers_attached(numvers); } void TSchedaPercipienti::setta_ritvers(TMask_field& f, const real& ritenuta) { TString80 rit_str(ritenuta.string()); f.mask().set(F_RITVERS, rit_str); f.mask().field(F_RITVERS).set_dirty(); // Forza on_hit() } // Guardo se ho compilato la data OPP. il flag 1015 // Leggo la maschera o la riga dello ss bool TSchedaPercipienti::compilato_vers(TMask_field& f) { TString16 datav; char v1015; if (f.mask().is_running()) { datav = f.mask().get(F_DATAVERS); v1015 = f.mask().get(F_VERS_1015)[0]; } else { TSheet_field& ver = app().vers(); const int riga_corr = ver.selected(); TToken_string& riga = ver.row(riga_corr); v1015 = riga.get(0)[0]; datav = riga.get(1); datav.trim(); } return datav.not_empty() || v1015 == 'X'; } // GET_NUMVERS // // Determina il numero di versamento corrente, prendendolo // dalla riga corrente dello spreadsheet long TSchedaPercipienti::get_numvers(TMask_field& f) { long numvers = 0L; TSheet_field& ver = app().vers(); const int riga_corr = ver.selected(); TToken_string& riga = ver.row(riga_corr); numvers = riga_corr + 1; return numvers; } bool TSchedaPercipienti::pag_azzera(TMask_field& f, KEY k) { if (k == K_SPACE) { Pag_struct s; app().from_struct_to_mask(app().clear_struct(s), f.mask()); } return TRUE; } bool TSchedaPercipienti::ver_azzera (TMask_field& f, KEY k) { long numvers = get_numvers(f); int nriga = 0; TNikArray_sheet& pags = *app()._pags; if (k == K_SPACE) { app().load_pag_sheet(numvers); for (int j = 0; j < pags.items(); j++) { TToken_string& riga = pags.row(j); long numv = riga.get_long(AS_POS_NVER); if (numv > 0L) if (numv == numvers) { nriga = pags.row(j).get_int(AS_POS_NRIGA); pags.row(j).add(-1L, AS_POS_NVER); app().detach_pag_vers(nriga); } } } return TRUE; } // // PAG_SELECT // // Collegamento tra versamenti e pagamenti // // Calcolo ritenuta = SUM(ritpag) {dei pagamenti collegati} // // Usa: load_pag_sheet() attach_pag_vers() e detach_pag_vers() // bool TSchedaPercipienti::pag_select (TMask_field& f, KEY k) { if (k == K_SPACE) { if (!app().compilato_vers(f)) return f.warning_box("Inserire prima la data del versamento"); long numvers = get_numvers(f); long numpag = 0L; int nriga = 0; // 13.7.95 Ricalcola la ritenuta, azzerando contenuto precedente real ritenuta = ZERO; TBit_array& selected = app()._selected; selected.reset(); // Costruisce array_sheet dei pagamenti app().load_pag_sheet(numvers); TNikArray_sheet& ASpags = *app()._pags; // seleziona e aggiungi alle gia' selezionate if (ASpags.run() == K_ENTER) { for (int j = 0; j < ASpags.items(); j++) { // get effettivo numero riga pag. nriga = ASpags.row(j).get_int(AS_POS_NRIGA); int mesec = -1; int annoc = -1; // competenza if (ASpags.checked(j)) { // Scrive nello spread-sheet e nella relazione app().attach_pag_vers(nriga, numvers); // Scrive nell'array_sheet (e' da qui che leggo dopo) ASpags.row(j).add((long)numvers, AS_POS_NVER); TDate datapag(ASpags.row(j).get(1)); if (mesec < 0) { mesec = datapag.month(); annoc = datapag.year(); } else { if (mesec != datapag.month() || annoc != datapag.year()) { // TBI inserire un'altra riga di versamento (?) } } selected.set(numpag); real dep(real::ita2eng(ASpags.row(j).get(AS_POS_RITPAG))); ritenuta += dep; } else // pags.checked() { // resetta se era stato settato prima if (selected[numpag]) { selected.reset(numpag); ASpags.row(j).add(-1L, AS_POS_NVER); app().detach_pag_vers(nriga); } } } setta_ritvers(f, ritenuta); } // if k==K_ENTER } return TRUE; } void TSchedaPercipienti::work_tipoluogo(TMask_field& f) { TMask& m = f.mask(); char tipo = m.get(F_TIPOVERS)[0]; char luogo = m.get(F_LUOVERS)[0]; bool v1015 = m.get_bool(F_VERS_1015); TSheet_field& ss = app().vers(); const int row = ss.selected(); m.hide (-2); // nasconde tutto // disabilita CAB se versamento 1015 // perchè non appartenendo alla riga // non viene disabilitato nella "rec2row" if (v1015) m.disable(F_CAB); else m.enable(F_CAB); if (tipo == 'B') { // ABI e CAB m.show (-6); // abilita progressivo vers.banca if (!v1015) m.enable(SM_PROGRBANCA); } else { m.disable(SM_PROGRBANCA); if (tipo == 'D') { if (luogo == 'T') { m.show(-3); // SOLO quietanza ss.disable_cell(row,4); } else { m.show(-4); // serie e numero ss.enable_cell(row,4); } } // else if (tipo == 'C') { m.show (-5); // SOLO numero versamento ss.disable_cell(row,4); } } } bool TSchedaPercipienti::luo_hndl(TMask_field& f, KEY k) { if (k == K_TAB) work_tipoluogo(f); if (k == K_ENTER) { work_tipoluogo(f); TMask& m = f.mask(); char tipo = m.get(F_TIPOVERS)[0]; char luogo = m.get(F_LUOVERS)[0]; // Se ho indicato il luogo => devo indicare anche il TIPO if (isalpha(luogo)) return tipo == ' ' || tipo == '\0' ? f.warning_box("Indicare il tipo del versamento") : TRUE; } return TRUE; } bool TSchedaPercipienti::abicab_hndl(TMask_field& f, KEY k) { if (f.to_check(k)) { TString16 park(f.get()); TMask& m = f.mask(); char tipo = m.get(F_TIPOVERS)[0]; // ABI/CAB solo se tipo e' B if (tipo != 'B') return TRUE; for (int i=0; i 5) { f.reset(); return f.warning_box("Codice CAB non valido"); } // controllo numericità del codice ABI/CAB if (!isdigit(park[i])) return f.warning_box("Il codice ABI/CAB deve essere numerico"); } } return TRUE; } bool TSchedaPercipienti::tipo_hndl(TMask_field& f, KEY k) { if (k == K_TAB) work_tipoluogo(f); if (k == K_ENTER || k == K_TAB) { TMask& m = f.mask(); char tipo = m.get(F_TIPOVERS)[0]; char luogo = m.get(F_LUOVERS)[0]; // Se ho indicato il tipo => devo indicare anche il LUOGO if (isalpha(tipo)) return luogo == ' ' || luogo == '\0' ? f.warning_box("Indicare il luogo del versamento") : TRUE; } return TRUE; } // // VERS1015_HANDLER // bool TSchedaPercipienti::vers1015_handler(TMask_field& f, KEY k) { if (k == K_ENTER) { TString16 datas = f.mask().get(F_DATAVERS); const bool v1015 = f.mask().get_bool(F_VERS_1015); const bool attaccati = check_pagamenti(f,k); if (attaccati) if (!v1015 && datas.empty()) return f.warning_box("Manca la data del versamento"); // Non considerare versamenti non significativi if (v1015 || datas.not_empty()) return attaccati ? TRUE : f.warning_box("Nessun pagamento collegato"); const real rite (f.mask().get(F_RITVERS)); // Pero' se c'e' la ritenuta non lo far passare if (rite != ZERO) return f.warning_box("Manca la data oppure il flag di versamento 1015"); return TRUE; } if (k == K_SPACE || k == K_F2) { TSheet_field& ss = app().vers(); const bool v1015 = (f.get() == "X"); const int row = ss.selected(); int i; // Disabilito tutto MA NON ritenuta if (v1015) { // Se son gia' disabilitati non fare nulla if (ss.cell_disabled(row, 1)) return TRUE; f.mask().reset(102); f.mask().reset(103); f.mask().reset(104); f.mask().reset(105); f.mask().reset(106); f.mask().disable(102); f.mask().disable(103); f.mask().disable(104); f.mask().disable(105); f.mask().disable(106); for (i=1; i<6; i++) ss.disable_cell(row,i); } else { f.mask().enable(102); f.mask().enable(103); f.mask().enable(104); f.mask().enable(105); f.mask().enable(106); for (i=1; i<6; i++) ss.enable_cell(row,i); } } return TRUE; } // handler codice causale bool TSchedaPercipienti::check_causale(TMask_field& f, KEY k) { TMask& m = f.mask(); TString16 cod_qua(m.get(F_CODQUA)); // creo run-time gli items per la causale quadro app().build_causqua_items(m, cod_qua); if (k == K_TAB && m.is_running()) { // leggo causale indicata TFixed_string cod_caus(f.get(),3); // cose da fare solo se viene modificato il codice causale if (f.to_check(k)) { // forzo causale quadro con il valore in tabella TEdit_field& f_causqua = m.efield(F_CAUSQUA); f_causqua.reset(); if (cod_qua == "SC") f_causqua.set(m.get(F_TABCAUSQUASC)); if (cod_qua == "SE") f_causqua.set(m.get(F_TABCAUSQUASE)); if (cod_qua == "SF") f_causqua.set(m.get(F_TABCAUSQUASF)); if (cod_qua == "SG") f_causqua.set(m.get(F_TABCAUSQUASG)); // attiva sheet pagamenti in base al quadro app().activate_pag_sheet(m); } } return TRUE; } bool TSchedaPercipienti::pag_standard_handler(TMask_field& f, KEY k) { static Pag_struct s; static Pag_struct c; static Pag_struct nullpag; app().clear_struct(nullpag); // reperisco dati documento TMask& mm = app().curr_mask(); const bool d_forzatura = mm.get_bool(F_FORCED); TString16 d_codqua(mm.get(F_CODQUA)); // eseguo calcolo solo per K_TAB (singolo campo), // oppure per K_ENTER, ma solo per il primo campo, // questo per migliorare le prestazioni if (f.to_check(k)) { if (k == K_TAB || (k == K_ENTER && f.dlg() == 101)) { // reperisco valori nascosti compilati dalla tabella causali const real h_PercAssImp = mm.get_real(F_QUOTAIMP); const real h_PercCassaPrev = mm.get_real(F_CASSA_PREV); const real h_PercRitenuta = mm.get_real(F_PERRIT); const bool h_FlagInps = mm.get_bool(F_FLAG_INPS); const real h_PercInps = mm.get_real(F_PERC_INPS); const real h_PercAssImpInps = mm.get_real(F_PERC_ASS_INPS); const real h_PercCommitInps = mm.get_real(F_PERC_COMMIT_INPS); // inizializzo struttura calcolati app().clear_struct(c); // riempimento struttura pagamento app().from_mask_to_struct(f.mask(), s); // non proseguo se riga vuota if (s == c) return TRUE; // richiamo calcolo di riga app().calcola_riga_pag(s, c, FALSE, h_PercAssImp, h_PercCassaPrev, h_PercRitenuta, h_PercInps, h_PercAssImpInps, h_PercCommitInps); // riporto valori a maschera app().from_struct_to_mask(s, f.mask()); } // eseguo controlli solo per K_ENTER // utilizzando i valori memorizzati nelle strutture statiche if (k == K_ENTER) { // non proseguo se riga vuota if (s == nullpag) return TRUE; // reperisco nome campo su record const TString& name = f.field()->name(); // controllo data pagamento if (name == "DATAPAG") if (!s.datapag.ok() && (s.compenso != ZERO || s.spesa != ZERO)) return f.error_box("Data pagamento non indicata"); // controllo compenso e/o spese if (name == "COMPENSO" || name == "SPESA") if (s.compenso == ZERO && s.spesa == ZERO) return f.error_box("Compenso o spese non indicati"); // controllo imponibile if (name == "IMPONIBILE") if (d_codqua != "E1" && abs(s.imponibile) > abs(s.compenso)) return f.error_box("Imponibile maggiore del compenso"); // controllo ritenuta if (name == "RITENUTA" && !d_forzatura) if (s.ritenuta != c.ritenuta) return f.error_box("Ritenuta diversa da importo calcolato"); // controllo detrazioni lavoro dipendente if (name == "DETLAVDIP") if (s.detlavdip == ZERO && s.giolavdip != 0) return f.error_box("Detrazioni lavoro dipendente non indicate"); // controllo CPA if (name == "IMPCPA") { if ((d_codqua != "SC") && s.impcpa != ZERO) return f.error_box("CPA valido solo per causali con quadro SC"); if (abs(s.impcpa) > abs(s.compenso)) return f.error_box("CPA maggiore del compenso"); } // controllo somme reg.conv. if (name == "SOMREGCONV") { // if ((d_codqua != "SC" && d_codqua != "SE") && s.somregconv != ZERO) nell'ultima versione dei quadri le SOMREGCONV valgono per tutti i tipi di quadro (SC,SE,SF,SG) // return f.error_box("Somme reg.conv. valido solo per causali con quadro SC e SE"); 12/07/2000 if (!app()._soggnres && s.somregconv != ZERO) return f.error_box("Somme reg.conv. valido solo se percipiente non residente"); } // controllo contributo 10% percipiente if (name == "CTSSNPERC" && !d_forzatura) if (s.ctssnperc != c.ctssnperc) return f.error_box("Contributo Inps percipiente diverso da importo calcolato"); // controllo contributo 10% complessivo if (name == "CTSSNCOMP" && !d_forzatura) if (s.ctssncomp != c.ctssncomp) return f.error_box("Contributo Inps complessivo diverso da importo calcolato"); // controllo numero quote if (name == "NQUOTE" && !d_forzatura) if (s.nquote == ZERO) return f.error_box("Numero quote non indicate"); } } return TRUE; }