#include #include #include #include #include #include #include #include #include #include "..\cg\cgsaldac.h" #include "..\cg\cg2103.h" #include "..\ve\velib.h" #include "cm1100a.h" #include "cm1100b.h" #include "cm1100.h" //=============================================================================================== //maschera di configurazione class TPag_per_cms_configmask: public TAutomask { public: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void config_loader(TSheet_field& sf, const char* paragrafo); void config_setter(TSheet_field& sf, const char* paragrafo); TPag_per_cms_configmask():TAutomask("cm1100b") { config_loader(sfield(F_COSTI), "Costi"); config_loader(sfield(F_PAGAMENTI), "Pagamenti"); config_loader(sfield(F_RITFIS), "Fiscali"); config_loader(sfield(F_RITSOC), "Sociali"); } }; bool TPag_per_cms_configmask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_SAVEREC: { config_setter(sfield(F_COSTI), "Costi"); config_setter(sfield(F_PAGAMENTI), "Pagamenti"); config_setter(sfield(F_RITFIS), "Fiscali"); config_setter(sfield(F_RITSOC), "Sociali"); } break; default: break; } return true; } void TPag_per_cms_configmask::config_loader(TSheet_field& sf, const char* paragrafo) { TConfig config("cm1100.ini", paragrafo); TString_array conti; int n = config.list_variables(conti, true, paragrafo, true); FOR_EACH_ARRAY_ROW(conti, i, row) { TToken_string conto(row->get(1), '.'); //prende il valore della riga TBill uncle(conto, 0); uncle.add_to(sf.row(i), 0, 0x2); } } void TPag_per_cms_configmask::config_setter(TSheet_field& sf, const char* paragrafo) { TConfig config("cm1100.ini", paragrafo); config.remove_all(); //svuota il paragrafo sul .ini prima di ricompilarlo (se non si facesse //non si riuscirebbero ad ammazzare le righe sul .ini FOR_EACH_SHEET_ROW (sf, i, row) { TToken_string conto("", '.'); conto.add(row->get(0)); conto.add(row->get(1)); conto.add(row->get(2)); config.set("conto", conto, NULL, true, i); } } //=============================================================================================== //maschera principale class TPag_per_cms_mask: public TAutomask { public: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); TPag_per_cms_mask():TAutomask("cm1100a") {} }; bool TPag_per_cms_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_CONFIG: if (e == fe_button) { TPag_per_cms_configmask configmask; //lancia la maschera di configurazione configmask.run(); } break; default: break; } return true; } //=============================================================================================== // class dei dati da passare in stampa class TPag_per_cms_struct : public TSortable { protected: virtual int compare(const TSortable& s) const; public: static bool _ordina_forn; int _tipo; long _codforn; TDate _datapag; TCurrency _importopagato; TCurrency _importopagato_prec; TString _descrpagamento; TString _numfat; TDate _datafat; long _protiva; TCurrency _totfat; long _nreg; TBill _conto; //gruppocontosottoconto TString _commessa; TString _fase; TCurrency _importocommessa; TPag_per_cms_struct() : _tipo(0), _codforn(0), _nreg(0), _protiva(0) { } }; bool TPag_per_cms_struct::_ordina_forn = false; int TPag_per_cms_struct::compare(const TSortable& s) const { const TPag_per_cms_struct& pcs = (const TPag_per_cms_struct&)s; int cmp = 0; if(_ordina_forn) { if (_tipo == 0) cmp = _codforn - pcs._codforn; else cmp = _conto.compare(pcs._conto); if (cmp == 0) cmp = _nreg - pcs._nreg; } else { cmp = _commessa.compare(pcs._commessa); //ordinamento per commessa if (cmp == 0) { cmp = _fase.compare(pcs._fase); //sotto-ordinamento per fase if (cmp == 0) { cmp = _tipo - pcs._tipo; //sotto-sotto-ordinamento per tipo pagamento if (cmp == 0) { //caso pagamento o costo non saldacontato if (_tipo == 0) cmp = _nreg - pcs._nreg; else cmp = _conto.compare(pcs._conto); } } } } return cmp; } //=============================================================================================== // struct del residuo struct TPag_per_cms_residual : public TObject { TCurrency _fatt, _pag; }; //=============================================================================================== //form class TPag_per_cms_form : public TForm { TArray& _righe; //puntatore all'arrayone dei pagamenti int _curr_pag; //pagamento corrente TAssoc_array _tot_fatt; //assoc_array contenente i movimenti che generano i pagamenti TCurrency _totfatcms; //totale fatture per commessa TCurrency _totpagcms, _totpagfsc; //totale pagamenti sulla commessa e sulla fase protected: virtual long records() const {return _righe.items();} virtual bool validate(TForm_item &cf, TToken_string &s); const TString& prev_cms() const; const TString& prev_fsc() const; const long prev_forn() const; // const TString& next_cms() const; int prev_type () const; const TPag_per_cms_struct& curr() const { return(TPag_per_cms_struct&)_righe[_curr_pag]; } void print_title (const char * title); void stampa_totali(); void stampa_totali_fase(); void azzera_totali(); void azzera_totali_fase(); public: void print(const TMask& m); TPag_per_cms_form(TArray& pag); virtual ~TPag_per_cms_form(); }; const TString& TPag_per_cms_form::prev_cms() const { if (_curr_pag <= 0) return EMPTY_STRING; const TPag_per_cms_struct& prev = (const TPag_per_cms_struct&)_righe[_curr_pag-1]; return prev._commessa; } const TString& TPag_per_cms_form::prev_fsc() const { if (_curr_pag <= 0) return EMPTY_STRING; const TPag_per_cms_struct& prev = (const TPag_per_cms_struct&)_righe[_curr_pag-1]; return prev._fase; } const long TPag_per_cms_form::prev_forn() const { if (_curr_pag <= 0) return 0; const TPag_per_cms_struct& prev = (const TPag_per_cms_struct&)_righe[_curr_pag-1]; return prev._codforn; } /*const TString& TPag_per_cms_form::next_cms() const { if (_curr_pag >= _righe.last()) return EMPTY_STRING; const TPag_per_cms_struct& next = (const TPag_per_cms_struct&)_righe[_curr_pag+1]; return next._commessa; }*/ int TPag_per_cms_form::prev_type() const { if (_curr_pag <= 0) return 0; const TPag_per_cms_struct& prev = (const TPag_per_cms_struct&)_righe[_curr_pag-1]; return prev._tipo; } void TPag_per_cms_form::print_title (const char * title) { TPrint_section& last_head = section('H', last_page); last_head.find_field(FR_HL_CODCMS).set(title); last_head.update(); for (word i = 0; i < last_head.height(); i++) printer().print(last_head.row(i)); } void TPag_per_cms_form::azzera_totali() { _totfatcms = ZERO; //azzera il totale pagamenti della commessa per non sommarlo alla commessa successiva _totpagcms = ZERO; } void TPag_per_cms_form::stampa_totali() { stampa_totali_fase(); TPrintrow pr; TString80 str; TCurrency tot; if (TPag_per_cms_struct::_ordina_forn) pr.put("@bTotali per fornitore", 21); else pr.put("@bTotali per commessa", 21); FOR_EACH_ASSOC_OBJECT(_tot_fatt, h, k, obj) { const TPag_per_cms_residual* imp = (const TPag_per_cms_residual*)obj; tot += imp->_fatt; } const int tipo = prev_type(); //astruso modo per poter stampare il totale imputato nel caso di movimenti.. str = tipo > 0 ? _totpagcms.string(true) : tot.string(true); //..senza doc di vendita;si deve usare il tipo prec.. str.right_just(15); pr.put(str, 102); str = _totpagcms.string(true); str.right_just(15); pr.put(str, 117); /* const TCurrency residuo = _totfatcms - _totpagcms; if (!residuo.is_zero()) { str = residuo.string(true); str.right_just(15); pr.put(str, 132); }*/ //****non serve piu' printer().print(pr); azzera_totali(); } void TPag_per_cms_form::azzera_totali_fase() { _tot_fatt.destroy(); _totpagfsc = ZERO; } void TPag_per_cms_form::stampa_totali_fase() { TPrintrow pr; pr.put("@bTotali per fase", 21); TString80 str; TCurrency tot; FOR_EACH_ASSOC_OBJECT(_tot_fatt, h, k, obj) { const TPag_per_cms_residual* imp = (const TPag_per_cms_residual*)obj; tot += imp->_fatt; } const int tipo = prev_type(); //astruso modo per poter stampare il totale imputato nel caso di movimenti.. str = tipo > 0 ? _totpagfsc.string(true) : tot.string(true); //..senza doc di vendita;si deve usare il tipo prec.. str.right_just(15); //x' l'ultima riga utile per la stampa tot e' quella prima di quella corrente pr.put(str, 102); str = _totpagfsc.string(true); str.right_just(15); pr.put(str, 117); /* const TCurrency residuo = tot - _totpagfsc; if (!residuo.is_zero()) { str = residuo.string(true); str.right_just(15); pr.put(str, 132); }*/ //****non serve piu' _totfatcms += tot; _totpagcms += _totpagfsc; //stampa solo se != zero almeno una cifra if (!tot.is_zero() || !_totpagfsc.is_zero()) printer().print(pr); azzera_totali_fase(); } bool TPag_per_cms_form::validate(TForm_item &cf, TToken_string &s) { if (s == "_NEXTPAG") { _curr_pag ++; //aggiorna il contatore pagamenti quando ne trova uno sull'arrayone return true; } if (s == "_TIPORIGA") { TString8 str; str << curr()._tipo; cf.set(str); return true; } if (s == "_CODCMS") { bool cambio = false; TString80 titolo; if (TPag_per_cms_struct::_ordina_forn) { const long forn = curr()._codforn; cambio = forn != prev_forn(); TString16 key; key.format("F|%ld", forn); titolo = cache().get(LF_CLIFO, key, CLI_RAGSOC); } else { const TString& cms = curr()._commessa; cambio = cms != prev_cms(); titolo << cms << " " << cache().get("CMS", cms, "S0"); } if (cambio) { if (_curr_pag > 0) { stampa_totali(); if (_curr_pag < _righe.last()) //se sei all'ultimo movimento non aggiungere pagine vuote printer().formfeed(); } if (titolo.not_empty()) print_title(titolo); } return true; } if (s == "_CODFSC") { bool cambio = false; TString80 titolo; const TString& fsc = curr()._fase; cambio = fsc != prev_fsc(); titolo << fsc << " " << cache().get("FSC", fsc, "S0"); if (cambio) { if (_curr_pag > 0) stampa_totali_fase(); if (titolo.not_empty()) { titolo.insert(" "); print_title(titolo); } } else { const int tipo = curr()._tipo; if (tipo > 0 && tipo != prev_type()) { switch (tipo) { case 1:print_title(" Costi");break; case 2:print_title(" Pagamenti");break; case 3:print_title(" Ritenute Fiscali");break; case 4:print_title(" Ritenute Sociali");break; default:break; } } } return true; } if (s == "_NREG") { TString8 str; str << curr()._nreg; cf.set(str); TPag_per_cms_residual* mov = (TPag_per_cms_residual*) _tot_fatt.objptr(str); if (mov == NULL) { mov = new TPag_per_cms_residual; mov->_fatt = curr()._importocommessa; mov->_pag = curr()._importopagato_prec; _tot_fatt.add(str, mov); //agginge nreg ed importo all'array dei totali } return true; } if (s == "_DATAPAG") { cf.set(curr()._datapag.string()); return true; } if (s == "_GRUPPO") { TString8 str; str << curr()._conto.gruppo(); cf.set(str); return true; } if (s == "_CONTO") { TString8 str; str << curr()._conto.conto(); cf.set(str); return true; } if (s == "_SOTTOCONTO") { TString8 str; str << curr()._conto.sottoconto(); cf.set(str); return true; } if (s == "_DESCGRCOST") { cf.set(curr()._conto.descrizione()); return true; } if (s == "_DESCRPAG") { cf.set(curr()._descrpagamento); return true; } if (s == "_NFAT") { cf.set(curr()._numfat); return true; } if (s == "_DATAFAT") { cf.set(curr()._datafat.string()); return true; } if (s == "_PROTIVA") { TString str; str << curr()._protiva; cf.set(str); return true; } if (s == "_TOTFAT") { cf.set(curr()._totfat.get_num().string()); return true; } if (s == "_TOTIMP") { const int tipo = curr()._tipo; if (tipo > 0) //caso pagamenti senza documento di vendita (deve essere = a _TOTPAG) cf.set(curr()._importopagato.get_num().string()); else cf.set(curr()._importocommessa.get_num().string()); //caso pagamenti da documento vendita return true; } if (s == "_TOTPAG") { cf.set(curr()._importopagato.get_num().string()); _totpagfsc += curr()._importopagato; TString8 str; str << curr()._nreg; TPag_per_cms_residual* mov = (TPag_per_cms_residual*) _tot_fatt.objptr(str); if (mov != NULL) mov->_pag += curr()._importopagato; return true; } if (s == "_TOTRES") { const int tipo = curr()._tipo; if (tipo == 0) { TCurrency residuo = curr()._importocommessa - curr()._importopagato_prec; cf.set(residuo.get_num().string()); } else cf.set(""); return true; } if (s == "_CODFORN") { TString80 str; if (!TPag_per_cms_struct::_ordina_forn) str << curr()._codforn; cf.set(str); return true; } if (s == "_CODCMS_B") { TString80 str; if (TPag_per_cms_struct::_ordina_forn) str << curr()._commessa; cf.set(str); return true; } if (s == "_DESFORN") { TString80 str; if (!TPag_per_cms_struct::_ordina_forn) { const long forn = curr()._codforn; if (forn > 0) { TString16 key; key.format("F|%ld", forn); str << " " << cache().get(LF_CLIFO, key, CLI_RAGSOC); } } cf.set(str); } if (s == "_DESCMS_B") { TString80 str; if (TPag_per_cms_struct::_ordina_forn) str << cache().get("CMS", curr()._commessa, "S0"); cf.set(str); } return TForm::validate(cf,s); } void TPag_per_cms_form::print(const TMask& m) { //header odd del form (intestazione della pagina) TPrint_section& header = section('H', odd_page); header.find_field(FR_HO_DATAINI).set(m.get(F_DATAINI)); header.find_field(FR_HO_DATAFIN).set(m.get(F_DATAFIN)); header.find_field(FR_HO_DACDC).set(m.get(F_DACDC)); const TRectype& dacms = cache().get("CMS", m.get(F_DACDC)); TString80 des = dacms.get("S0"); header.find_field(FR_HO_DADESC).set(des); header.find_field(FR_HO_ACDC).set(m.get(F_ACDC)); const TRectype& acms = cache().get("CMS", m.get(F_ACDC)); des = acms.get("S0"); header.find_field(FR_HO_ADESC).set(des); header.find_field(FR_HO_DACFSC).set(m.get(F_DAFSC)); const TRectype& dafsc = cache().get("FSC", m.get(F_DAFSC)); des = dafsc.get("S0"); header.find_field(FR_HO_DADESFSC).set(des); header.find_field(FR_HO_ACFSC).set(m.get(F_AFSC)); const TRectype& afsc = cache().get("FSC", m.get(F_AFSC)); des = afsc.get("S0"); header.find_field(FR_HO_ADESFSC).set(des); header.find_field(FR_HO_DACODFOR).set(m.get(F_DACODFOR)); header.find_field(FR_HO_DADESFOR).set(m.get(F_DADESFOR)); header.find_field(FR_HO_ACODFOR).set(m.get(F_ACODFOR)); header.find_field(FR_HO_ADESFOR).set(m.get(F_ADESFOR)); if (TPag_per_cms_struct::_ordina_forn) header.find_field(FR_HO_FORNCMS).set("Commessa"); else header.find_field(FR_HO_FORNCMS).set("Fornitore"); _curr_pag = 0; azzera_totali(); azzera_totali_fase(); //aggiunge una riga vuota (ppcs vuoto) per forzare il totale dell'ultima commessa TPag_per_cms_struct* ppcs = new TPag_per_cms_struct; _righe.add(ppcs); //chiama la vera print dopo aver azzerato il contatore ed i totali TForm::print(); } TPag_per_cms_form::TPag_per_cms_form(TArray& pag) :TForm ("cm1100a"), _righe(pag) { } TPag_per_cms_form::~TPag_per_cms_form() { } //=============================================================================================== //Applicazione class TPag_per_cms : public TSkeleton_application { TPag_per_cms_mask* _mask; TPag_per_cms_form* _form; TArray _righe; //array delle righe da stampare in tutti i casi TAssoc_array _costi,_pagamenti,_fiscali,_sociali; //array che contengono i conti TAssoc_array _righecosti,_righepagamenti,_righefiscali,_righesociali; //array delle righe da stampare in caso di costi,pagamenti,ritenute TString8 _campodata; protected: virtual void main_loop(); virtual bool create(); virtual bool destroy(); bool cms_in_range(const TString& codcms, const TString& codfase) const; long find_movimento(const TRectype& riga_pag) const; void find_commesse(const long nreg, const TRectype& riga_pag); void find_commesse_cg(const long nreg); void lettura_conti(const char * paragrafo, TAssoc_array& assoc); static bool part_callback(const TRelation& rel, void* pJolly); static bool mov_callback(const TRelation& rel, void* pJolly); bool cerca_conto(const TBill& bill, const TAssoc_array& assoc) const; bool cerca_costo(const TBill& bill) const; bool cerca_pagamento(const TBill& bill) const; bool cerca_fiscali(const TBill& bill) const; bool cerca_sociali(const TBill& bill) const; void add_importo(TAssoc_array& assoc, const TRectype& rmov) const; int cerca_riga_fattura_origine(const TPartita& match, const TRectype& riga_pag); real calcola_pagato_prec(const TPartita& match, const int riga_fatt, const TRectype& riga_pag); void crea_righe_stampa(TAssoc_array& assoc, const int tipo); real totale_documento(const TRectype& mov) const; bool test_swap(TCausale& caus, bool ritsoc) const; public: void scan_pags(); void scan_movs(); }; long TPag_per_cms::find_movimento(const TRectype& riga_pag) const { int n_fatture = 0; //numero di fatture trovate int first_fatt = 0; //numero riga della prima fattura //scan della partita dall'ultima alla prima riga const TPartita partita(riga_pag); for (int p = partita.last(); p > 0; p = partita.pred(p)) { const TRiga_partite& fatt = partita.riga(p); if (fatt.is_fattura()) { n_fatture++; first_fatt = p; } } if (n_fatture > 1) { const int linea_pag = riga_pag.get_int(PART_NRIGA); int linea_fattura = 0; for (int f = first_fatt; (f > 0) && (f <= partita.last()) && (linea_fattura == 0); f = partita.succ(f)) { const TRiga_partite& fatt = partita.riga(f); if (fatt.is_fattura()) { for (int r = 1; r <= fatt.rate(); r++) { const TRiga_scadenze& rata = fatt.rata(r); if (rata.exist(linea_pag)) { linea_fattura = f; break; } } } } if (linea_fattura > 0) // oppure anche (linea_fattura > first_fatt) first_fatt = linea_fattura; } long nreg = 0; if (first_fatt > 0) { const TRiga_partite& fatt = partita.riga(first_fatt); nreg = fatt.get_long(PART_NREG); } return nreg; } bool TPag_per_cms::cms_in_range(const TString& codcms, const TString& codfase) const { if (codcms.empty()) return false; const TString& dallac = _mask->get(F_DACDC); if (dallac.not_empty() && codcms < dallac) return false; const TString& allac = _mask->get(F_ACDC); if (allac.not_empty() && codcms > allac) return false; //la fase puo' essere vuota!! if (codfase.empty()) return true; const TString& dallaf = _mask->get(F_DAFSC); if (dallaf.not_empty() && codfase < dallaf) return false; const TString& allaf = _mask->get(F_AFSC); if (allaf.not_empty() && codfase > allaf) return false; return true; } // Controlla sulla causale se il segno del totale documento (ritsoc=FALSE) // o quello delle ritenute sociali (ritsoc=TRUE) e' invertito rispetto al normale bool TPag_per_cms::test_swap(TCausale& caus, bool ritsoc) const { const char sez = ritsoc ? caus.sezione_ritsoc() : caus.sezione_clifo(); const bool s = (caus.iva() == iva_vendite) ^ (sez == 'D'); return s; } // Calcola il totale del documento tenendo conto del segno della prima riga e di quella delle // ritenute sociali sulla causale real TPag_per_cms::totale_documento(const TRectype& mov) const { real tot = mov.get_real(MOV_TOTDOC); // Legge totale const real ritfis = mov.get_real(MOV_RITFIS); tot += ritfis; // Somma ritenute fiscali const real ritsoc = mov.get_real(MOV_RITSOC); if (!ritsoc.is_zero()) { TCausale caus(mov.get(MOV_CODCAUS)); const bool swapt = test_swap(caus, false); // Totale invertito ? const bool swaps = test_swap(caus, true); // Ritenute sociali invertite ? if (swapt ^ swaps) // Somma ritenute sociali con segno tot -= ritsoc; else tot += ritsoc; } return tot; } int TPag_per_cms::cerca_riga_fattura_origine(const TPartita& match, const TRectype& riga_pag) { //scansione delle righe partita passata, precedenti alla riga_pag const int k = riga_pag.get_int(PART_NRIGA); for (int i = match.pred(k); i > 0; i = match.pred(i)) { const TRiga_partite& riga_part = match.riga(i); if (riga_part.is_fattura()) { for (int j = riga_part.rate(); j > 0; j--) { if (match.esiste(i, j, k)) //se esiste il pagamento k della rata j della riga partita i contenente la fattura return i; } } } return 0; } real TPag_per_cms::calcola_pagato_prec(const TPartita& match, const int riga_fatt, const TRectype& riga_pag) { real pagato = ZERO; if (riga_fatt > 0) { const int k = riga_pag.get_int(PART_NRIGA); const TDate data_rif = riga_pag.get(_campodata); //data di riferimento selezionata sulla maschera const TRiga_partite& riga_part = match.riga(riga_fatt); for (int i = riga_part.rate(); i > 0; i--) { TRiga_scadenze& sc = riga_part.rata(i); for (int j = sc.last(); j > 0; j = sc.pred(j)) { const TRiga_partite& pag = match.riga(j); const TDate datapag = pag.get_date(_campodata); const long cmp = datapag - data_rif; //la riga pagamento e' da considerare quando ha data anteriore a quella di riferimento oppur //ha data uguale ma numero di registrazione inferiore (insomma, il pagamento e' precedente //a quello di riga_pag) if (cmp < 0 || (cmp == 0 && j <= k)) { pagato += pag.get_real(PAGSCA_IMPORTO); } } } } return pagato; } //prepara l'assoc con tutte le righe da mandare in stapa per quanto riguarda i movimenti con //saldaconto (siano essi con o senza iva) void TPag_per_cms::find_commesse(const long nreg, const TRectype& riga_pag) { TMovimentoPN pn; pn.curr().put(MOV_NUMREG, nreg); if (pn.read() == NOERR) { const TRectype& movfat = pn.curr(); real totdoc_cms; real totdoc, totdoc_netto; TAssoc_array commesse; //Movimenti CON SALDACONTO //se movimento IVA.. if (pn.iva_items() > 0) { for (int i = 0; i < pn.iva_items(); i++) { const TRectype& rmoviva = pn.iva(i); const TString& codcms = rmoviva.get("CODCMS"); const TString& codfase = rmoviva.get("FASCMS"); const TBill conto(rmoviva); if (cms_in_range(codcms, codfase) && conto.indicatore_bilancio() != 5) { TToken_string cms_fsc = codcms; if (codfase.not_empty()) cms_fsc.add(codfase); const real importo = rmoviva.get_real(RMI_IMPONIBILE); real imposta = rmoviva.get_real(RMI_IMPOSTA); real* imp = (real*)commesse.objptr(cms_fsc); if (imp == NULL) { imp = new real; commesse.add(cms_fsc, imp); } *imp += importo; totdoc_cms += importo; if (imposta != ZERO) { //controllo prorata const TRectype& pla = cache().get("CMS", codcms); const bool prorata = pla.get_bool("B4"); if (prorata) { const TDate datareg = pn.curr().get_date(MOV_DATAREG); const int anno = datareg.year(); TRegistro registro(pn.curr().get(MOV_REG), anno); imposta *= (CENTO - registro.prorata(anno))/CENTO; imposta.round(TCurrency::get_firm_dec()); //ci vanno i decimali della ditta } *imp += imposta; totdoc_cms += imposta; } } } totdoc = totale_documento(pn.curr()); //tot doc con ritenute fiscali + ritenute sociali (da stampare) totdoc_netto = pn.curr().get_real(MOV_TOTDOC); //questo si usa solo per il calcolo del residuo } else //..movimento NON iva (sempre con saldaconto) { for (int i = 0; i < pn.cg_items(); i++) { const TRectype& rmov = pn.cg(i); const TBill conto(rmov); TImporto importo(rmov.get_char(RMV_SEZIONE), rmov.get_real(RMV_IMPORTO)); importo.normalize('D'); if (conto.tipo() > ' ') { totdoc -= importo.valore(); totdoc_netto -= importo.valore(); //valore per il calcolo del residuo continue; } if (cerca_fiscali(conto) || cerca_sociali(conto)) { totdoc -= importo.valore(); //valore da stampare nella colonna Tot.fattura con ritenute continue; } const TString& codcms = rmov.get("CODCMS"); const TString& codfase = rmov.get("FASCMS"); if (cms_in_range(codcms,codfase) && conto.indicatore_bilancio() != 5) { TToken_string cms_fsc = codcms; if (codfase.not_empty()) cms_fsc.add(codfase); real* imp = (real*)commesse.objptr(cms_fsc); if (imp == NULL) { imp = new real; commesse.add(cms_fsc, imp); } *imp += importo.valore(); totdoc_cms += importo.valore(); } } } //parte comune a movimenti IVA e non (vengono anche qui considerate le ritenute fiscali //e sociali perche' possono essere state inserite direttamente nella partita e non nel movimento //(quindi non si puo' in questo caso applicare la totale_documento() //Le ritenute fiscali vanno sempre sommate.. real totpagato = riga_pag.get_real(PART_IMPORTO) + riga_pag.get_real(PART_RITENUTE); //Le ritenute sociali invece vanno testate con la test_swap.. const real ritsoc = riga_pag.get_real(PART_RITSOC); if (!ritsoc.is_zero()) { const TRectype& mov = pn.curr(); TCausale caus(mov.get(MOV_CODCAUS)); const bool swapt = test_swap(caus, false); // Totale invertito ? const bool swaps = test_swap(caus, true); // Ritenute sociali invertite ? if (swapt ^ swaps) // Somma ritenute sociali con segno totpagato -= ritsoc; else totpagato += ritsoc; } const real percentuale = totpagato / totdoc_netto; //calcolo del residuo (solo movimenti saldacontati) //mi servono,dalla riga partita che viene passata,i valori dei campi per la chiave del //file delle scadenze const TPartita match(riga_pag); //ci serve la riga di fattura che origina la nostra riga pagamento const int riga_fatt = cerca_riga_fattura_origine(match, riga_pag); //quanto era stato pagato del documento prima della attuale riga_pag const real totpagato_prec = calcola_pagato_prec(match, riga_fatt, riga_pag); const real perc_prec = totpagato_prec / totdoc_netto; TGeneric_distrib distributore(totdoc_cms * percentuale, TCurrency::get_firm_dec()); TGeneric_distrib distributore_prec(totdoc_cms * perc_prec, TCurrency::get_firm_dec()); { FOR_EACH_ASSOC_OBJECT(commesse, h, k, imp) { const real& impcms = *(real*)imp; distributore.add(impcms); distributore_prec.add(impcms); //distributore di importo pagato sulle commesse } } FOR_EACH_ASSOC_OBJECT(commesse, h, k, imp) { const real& impcms = *(real*)imp; TPag_per_cms_struct* ppcs = new TPag_per_cms_struct; // campi del pagamento ppcs->_tipo = 0; //movimenti da saldaconto ppcs->_codforn = riga_pag.get_long(PART_SOTTOCONTO); ppcs->_datapag = riga_pag.get_date(_campodata); ppcs->_importopagato.set_num(distributore.get()); //pagamento nella partita ppcs->_importopagato_prec.set_num(distributore_prec.get()); //pagamenti precedenti al ppcs->_descrpagamento = riga_pag.get(PART_DESCR); // campi della fattura ppcs->_nreg = nreg; ppcs->_numfat = movfat.get(MOV_NUMDOC); ppcs->_datafat = movfat.get_date(MOV_DATADOC); ppcs->_protiva = movfat.get_long(MOV_PROTIVA); ppcs->_totfat = totdoc; //questo e' quello che viene stampato in Tot.fattura TToken_string cms_fsc = k; ppcs->_commessa = cms_fsc.get(0); ppcs->_fase = cms_fsc.get(1); ppcs->_importocommessa.set_num(impcms); //importo da pagare scritto sulla fattura _righe.add(ppcs); //aggiunge il pagamento all'array dei pagamenti } } } void TPag_per_cms::add_importo(TAssoc_array& assoc, const TRectype& rmov) const { TBill conto(rmov); TToken_string chiave; conto.add_to(chiave, 0); chiave.add(rmov.get("CODCMS")); chiave.add(rmov.get("FASCMS")); chiave.add(rmov.get(RMV_NUMREG)); TImporto* importo = (TImporto*)assoc.objptr(chiave); if (importo == NULL) { importo = new TImporto; assoc.add(chiave,importo); } //incremento l'importo del conto commessa con l'importo movimento (importocontocms += importormov) const char sezione = rmov.get_char(RMV_SEZIONE); const real valore = rmov.get_real(RMV_IMPORTO); const TImporto imp(sezione, valore); *importo += imp; } //prepara gli oggetti (_righecosti,_righepagamenti) contenenti le righe dei pagamenti senza saldaconto void TPag_per_cms::find_commesse_cg(const long nreg) { TMovimentoPN pn; pn.curr().put(MOV_NUMREG, nreg); if (pn.read() == NOERR) { for (int i = 0; i < pn.cg_items(); i++) { const TRectype& rmov = pn.cg(i); const TString& codcms = rmov.get("CODCMS"); const TString& codfase = rmov.get("FASCMS"); if (cms_in_range(codcms,codfase)) { const TBill conto(rmov); if (cerca_costo(conto)) add_importo(_righecosti, rmov); else if (cerca_pagamento(conto)) add_importo(_righepagamenti, rmov); } } } } bool TPag_per_cms::cerca_conto(const TBill& bill, const TAssoc_array& assoc) const { TToken_string key(15,'.'); key.add(bill.gruppo()); if (assoc.is_key(key)) return true; key.add(bill.conto()); if (assoc.is_key(key)) return true; key.add(bill.sottoconto()); if (assoc.is_key(key)) return true; return false; } bool TPag_per_cms::cerca_costo(const TBill& bill) const { return cerca_conto(bill, _costi); } bool TPag_per_cms::cerca_pagamento(const TBill& bill) const { return cerca_conto(bill, _pagamenti); } bool TPag_per_cms::cerca_fiscali(const TBill& bill) const { return cerca_conto(bill, _fiscali); } bool TPag_per_cms::cerca_sociali(const TBill& bill) const { return cerca_conto(bill, _sociali); } void TPag_per_cms::lettura_conti(const char* paragrafo, TAssoc_array& assoc) { TConfig conti("cm1100.ini",paragrafo); //paragrafo da scandire nell ini TAssoc_array& vars = conti.list_variables(); FOR_EACH_ASSOC_STRING(vars, h, k, val) //riempie l'assoc con i soli valori del paragrafo dell'ini assoc.add(val); } // Mettere in libreria al piu' presto!!!! typedef bool (*SCAN_FUNC)(const TRelation& rel, void* pJolly); bool scan_cursor(TCursor& cur, const char* msg, SCAN_FUNC func, void* pJolly) { TRecnotype items = 0; // Temporarily TProgind pi(items, msg, true, true); { TWait_cursor hourglass; items = cur.items(); } bool ok = true; if (items > 0) { cur.freeze(); pi.setmax(items); for (cur = 0; cur.pos() < items; ++cur) { pi.addstatus(1); if (pi.iscancelled()) { ok = false; break; } if (!func(*cur.relation(), pJolly)) { ok = false; break; } } cur.freeze(false); } return ok; } bool TPag_per_cms::part_callback(const TRelation& rel, void* pJolly) { TPag_per_cms* app = (TPag_per_cms*)pJolly; const TRectype& riga_part_pag = rel.curr(); const long nreg = app->find_movimento(riga_part_pag); //prima cerco un movimento della fattura... if (nreg > 0) //..se ne trovo almeno uno cerco la commessa corrispondente app->find_commesse(nreg, riga_part_pag); return true; } void TPag_per_cms::scan_pags() { //costruzione filtro const long dacodfor = _mask->get_long(F_DACODFOR); const long acodfor = _mask->get_long(F_ACODFOR); TRectype darec(LF_PARTITE); TRectype arec(LF_PARTITE); darec.put(PART_TIPOCF, 'F'); darec.put(PART_GRUPPO, 0); darec.put(PART_CONTO, 0); arec = darec; if (dacodfor > 0) darec.put(PART_SOTTOCONTO, dacodfor); if (acodfor >= dacodfor) arec.put(PART_SOTTOCONTO, acodfor); TString filtro = "(TIPOMOV>=\"3\")"; //deve essere un pagamento a fornitore!!! const TDate dataini = _mask->get(F_DATAINI); const TDate datafin = _mask->get(F_DATAFIN); if (dataini.ok()) { TString80 f; f.format("&&(ANSI(%s)>=\"%s\")", (const char*)_campodata, dataini.string(ANSI)); filtro << f; } if (datafin.ok()) { TString80 f; f.format("&&(ANSI(%s)<=\"%s\")", (const char*)_campodata, datafin.string(ANSI)); filtro << f; } //applica il filtro alla relazione TRelation rel(LF_PARTITE); TCursor cur(&rel, filtro, 1, &darec, &arec); scan_cursor(cur, "Ricerca commesse...", part_callback, this); } bool TPag_per_cms::mov_callback(const TRelation& rel, void* pJolly) { TPag_per_cms* app = (TPag_per_cms*)pJolly; const long nreg = rel.curr().get_long(MOV_NUMREG); app->find_commesse_cg(nreg); return true; } void TPag_per_cms::scan_movs() { if (_campodata == PART_DATAPAG) // I movimenti non hanno DATAPAG _campodata = PART_DATAREG; TString filtro = "(REG==\"\")&&(TIPOMOV==\"\")"; const TDate dataini = _mask->get(F_DATAINI); const TDate datafin = _mask->get(F_DATAFIN); TRectype darec(LF_MOV), arec(LF_MOV); if (_campodata == MOV_DATAREG) { if (dataini.ok()) darec.put(MOV_DATAREG, dataini); if (datafin.ok()) arec.put(MOV_DATAREG, datafin); } else { TString80 f; if (dataini.ok()) { f.format("&&(ANSI(%s)>=\"%s\")", (const char*)_campodata, dataini.string(ANSI)); filtro << f; } if (datafin.ok()) { f.format("&&(ANSI(%s)<=\"%s\")", (const char*)_campodata, datafin.string(ANSI)); filtro << f; } } TRelation rel(LF_MOV); TCursor cur(&rel, filtro, 2, &darec, &arec); scan_cursor(cur, "Ricerca movimenti...", mov_callback, this); crea_righe_stampa(_righecosti, 1); crea_righe_stampa(_righepagamenti, 2); crea_righe_stampa(_righefiscali, 3); crea_righe_stampa(_righesociali, 4); } void TPag_per_cms::crea_righe_stampa(TAssoc_array& assoc, const int tipo) { TToken_string tok; FOR_EACH_ASSOC_OBJECT(assoc, h, k ,i) { tok = k; TImporto imp = *(TImporto*)i; switch (tipo) { case 1:imp.normalize('D');break; case 2:imp.normalize('A');break; case 3:imp.normalize('D');break; case 4:imp.normalize('A');break; default:break; } TPag_per_cms_struct* ppcs = new TPag_per_cms_struct; ppcs->_tipo = tipo; //movimenti di costo/pagamento ppcs->_codforn = 0; ppcs->_datapag = cache().get(LF_MOV, tok.get(5), MOV_DATACOMP); ppcs->_importopagato.set_num(imp.valore()); //pagamento nella partita ppcs->_nreg = tok.get_long(5); ppcs->_commessa = tok.get(3); ppcs->_fase = tok.get(4); ppcs->_conto.get(tok, 0); ppcs->_descrpagamento = cache().get(LF_MOV, tok.get(5), MOV_DESCR); _righe.add(ppcs); //aggiunge il pagamento all'array dei pagamenti e lo spedisce in stampa } } bool TPag_per_cms::create() { _mask = new TPag_per_cms_mask; _form = new TPag_per_cms_form(_righe); lettura_conti("Costi", _costi); //caricamento dei conti dei costi lettura_conti("Pagamenti", _pagamenti); // "" pagamenti lettura_conti("Fiscali", _fiscali); // ""ritenute fiscali **** lettura_conti("Sociali", _sociali); // """sociali **** return TSkeleton_application::create(); } bool TPag_per_cms::destroy() { delete _mask; delete _form; return TRUE; } void TPag_per_cms::main_loop() { while (_mask->run() == K_ENTER) { _campodata = PART_DATAREG; switch(_mask->get_int(F_TIPODATA)) { case 1:_campodata = PART_DATADOC;break; case 2:_campodata = PART_DATAPAG;break; default:break; } TPag_per_cms_struct::_ordina_forn = _mask->get_bool(F_ORDINAMENTO); _righe.destroy(); //azzera gli arrayoni dei pagamenti e roba simile _righecosti.destroy(); _righepagamenti.destroy(); _righefiscali.destroy(); _righesociali.destroy(); scan_pags(); //se c'e' un filtro sui fornitori, non si fa lo scan dei movimenti senza saldaconto const long dacodfor = _mask->get_long(F_DACODFOR); const long acodfor = _mask->get_long(F_ACODFOR); if (dacodfor == 0 && acodfor == 0) scan_movs(); if (_righe.items() > 0) { _righe.sort(); _form->print(*_mask); } } } int cm1100(int argc, char* argv[]) { TPag_per_cms a; a.run(argc,argv,TR("Stampa pagato per commessa")); return 0; }