#include #include #include #include #include #include #include #include "../cg/cglib01.h" #include "../cg/cg2103.h" #include "../cg/cgsaldac.h" #include "lv4.h" #include "lv4100.h" #include "lv4200a.h" #include #include #include #include #include #include #include enum CGC_SALDAC { CGC_NULL, CGC_TIPOCF, CGC_ANNO, CGC_NUMPART, CGC_CODCF, CGC_NUMEROREC, CGC_CAMBIO, CGC_VALUTA, CGC_TIPODOC, CGC_DATADOC, CGC_SCADENZA, CGC_IMPORTO, CGC_IMPORTO_VAL,CGC_NUMDOC }; class TCausali_cache : public TCache { TString4 _cln, _frn; protected: virtual TObject* key2obj(const char* key); public: const TCausale& causale(char tipocf, tipo_movimento tm); void init(const char* cln, const char* frn) { _cln = cln; _frn = frn; } }; TObject* TCausali_cache::key2obj(const char* key) { const char tipocf = key[0]; const tipo_movimento tm = tipo_movimento(key[1]-'0'); TString4 codcaus; if (tm == tm_fattura) codcaus = tipocf == 'F' ? _frn : _cln; if (codcaus.blank()) { TString query; query << "USE CAUS\nSELECT (TIPOMOV='" << tm << "')&&(RCAUS->TIPOCF='" << tipocf << "')" << "\nJOIN RCAUS INTO CODCAUS=CODCAUS NRIGA=1"; TISAM_recordset caus(query); if (caus.move_first()) codcaus = caus.get(CAU_CODCAUS).as_string(); } TCausale* pcaus = new TCausale(codcaus); return pcaus; } const TCausale& TCausali_cache::causale(const char tipocf, tipo_movimento tm) { // Metodo bastardo per evitare TToken_string temporanee "a randa" // creo chiave a lunghezza fissa TIPOCF+TIPOMOV+ANNO = C12010 const char key[4] = { tipocf, '0'+tm, '\0' }; return *(const TCausale*)objptr(key); } /////////////////////////////////////////////////////////// // TAutomask /////////////////////////////////////////////////////////// class TImporta_sc_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TImporta_sc_mask(); }; TImporta_sc_mask::TImporta_sc_mask() :TAutomask ("lv4200a") { } bool TImporta_sc_mask::on_field_event(TOperable_field& f, TField_event e, long jolly) { switch (f.dlg()) { //giochetto per avere la lista dei files validi nella directory di trasferimento! case F_NAME: if (e == fe_button) { TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32"); TFilename path = get(F_PATH); path.add("*.txt"); //file da importare list_files(path, as.rows_array()); TFilename name; FOR_EACH_ARRAY_ROW(as.rows_array(), i, row) { name = *row; *row = name.name(); } if (as.run() == K_ENTER) f.set(as.row(as.selected())); } break; default: break; } return true; } /////////////////////////////////////// // TSkeleton_application /////////////////////////////////////// class TImporta_sc : public TSkeleton_application { TImporta_sc_mask* _msk; TCausali_cache _cache_causali; TBill _clienti, _fornitori; int _fattsosp; private: void nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm, bool is_riba); bool paga_rata(TPartita& game, int nrata, int nrigp, real& importo) const; void set_descr(TRectype& rec) const; protected: bool log_error(TLog_report& log, const char* msg, const TRecordset& recset); const TCausale& causale(char tipocf, tipo_movimento tm); char get_tmcf(int gruppo, int conto) const; bool find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto); TRiga_partite& nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game); long fattura_in_sospensione(const TImporta_cogeco_recset& recset, const TRiga_partite& rigafat, long nmov); void nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game, bool is_riba); void nuova_riba(const TImporta_cogeco_recset& recset, TPartita& game); void nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game); void nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game); bool nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log); void salva_partita(TPartita*& game, long nmov); public: virtual bool create(); virtual bool destroy(); virtual void main_loop(); void transfer(const TFilename& file); }; // Cerca una causale appropriata in base a TIPOCF (C o F) e TIPOMOV (1, 2, 3, ...) const TCausale& TImporta_sc::causale(char tipocf, tipo_movimento tm) { return _cache_causali.causale(tipocf, tm); } // Ricava il campo TMCF (Cliente o Fornitore) di un dato conto char TImporta_sc::get_tmcf(int gruppo, int conto) const { char tmcf = ' '; if (gruppo > 0 && conto > 0) { TString8 key; key.format("%d|%d", gruppo, conto); const TRectype& pcon = cache().get(LF_PCON, key); tmcf = pcon.get_char(PCN_TMCF); } return tmcf; } // Trova il conto cliente di una certa anagrafica bool TImporta_sc::find_clifo_bill(char tipocf, int& gruppo, int& conto, long sottoconto) { bool found = false; TString8 key; gruppo = conto = 0; // Prima lo cerca sull'anagrafica stessa key.format("%c|%ld", tipocf, sottoconto); const TRectype& clifo = cache().get(LF_CLIFO, key); gruppo = clifo.get_int(CLI_GRUPPO); conto = clifo.get_int(CLI_CONTO); // Controlla che il conto esista found = get_tmcf(gruppo, conto) == tipocf; if (!found) { // Cerca sulla prima riga dellla causale const TCausale& caus = causale(tipocf, tm_fattura); TBill bill; caus.bill(1, bill); gruppo = bill.gruppo(); conto = bill.conto(); found = get_tmcf(gruppo, conto) == tipocf; } if (!found) { // Usa un conto C/F trovato preventivamente in fase di inizializzazione if (tipocf == 'C') { gruppo = _clienti.gruppo(); conto = _clienti.conto(); } else { gruppo = _fornitori.gruppo(); conto = _fornitori.conto(); } found = gruppo > 0 && conto > 0; } return found; } void TImporta_sc::set_descr(TRectype& rec) const { TString descr; descr << "*** "; switch (rec.num()) { case LF_SCADENZE: descr << TR("Rata") << ' ' << rec.get(SCAD_NRATA); rec.put(SCAD_DESCR, descr); break; case LF_PARTITE: switch (tipo_movimento(rec.get_int(PART_TIPOMOV))) { case tm_fattura : descr << TR("Fattura") << ' ' << rec.get(PART_ANNO) << '/' << rec.get(PART_NUMDOC); break; case tm_nota_credito: descr << TR("Nota di credito") << rec.get(PART_ANNO) << '/' << rec.get(PART_NUMDOC); break; case tm_insoluto : descr << TR("Insoluto"); break; default : descr << TR("Pagamento"); break; } rec.put(PART_DESCR, descr); break; default: break; } } // Aggiunge una nuova riga fattura a 'game' in base ai dati in 'recset' TRiga_partite& TImporta_sc::nuova_fattura(const TImporta_cogeco_recset& recset, TPartita& game) { int nriga = game.prima_fattura(); if (game.prima_fattura() <= 0) { TRiga_partite& fattura = game.new_row(); const TDate datadoc = recset.get_date(CGC_DATADOC); fattura.put(PART_DATAREG, datadoc); fattura.put(PART_DATADOC, datadoc); const long numdoc = recset.get(CGC_NUMDOC).as_int(); if (numdoc > 0) fattura.put(PART_NUMDOC, numdoc); const char tipocf = game.conto().tipo(); const TCausale& caus = causale(tipocf, tm_fattura); if (caus.ok()) { fattura.put(PART_CODCAUS, caus.codice()); fattura.put(PART_REG, caus.reg().name()); fattura.put(PART_TIPOMOV, caus.tipomov()); fattura.put(PART_SEZ, caus.sezione(1)); } else { fattura.put(PART_TIPOMOV, tm_fattura); fattura.put(PART_SEZ, tipocf == 'C' ? 'D' : 'A'); } set_descr(fattura); nriga = fattura.get_int(PART_NRIGA); } TRiga_partite& fattura = game.riga(nriga); const real importo = recset.get_real(CGC_IMPORTO); fattura.add(PART_IMPTOTDOC, importo); fattura.add(PART_IMPORTO, importo); return fattura; } long TImporta_sc::fattura_in_sospensione(const TImporta_cogeco_recset& recset, const TRiga_partite& rigafat, long nmov) { TFilename temp(_msk->get(F_PATHOUT)); temp << '/' << format("%05ld", nmov++); temp.ext("ini"); if (fexist(temp)) remove_file(temp); TConfig conf(temp); conf.set_paragraph("Transaction"); //setto il paragrafo [Transaction] del file ini conf.set("Action","INSERT"); conf.set("Mode","AUTO"); conf.set_paragraph("23"); //setto il paragrafo [23] del file ini (testata) conf.set(MOV_CODCAUS, rigafat.get(PART_CODCAUS)); TDate datareg = rigafat.get_date(PART_DATAREG); if (esercizi().date2esc(datareg) == 0) datareg = esercizi().esercizio(esercizi().first()).inizio(); conf.set(MOV_DATAREG, datareg); TDate datadoc = rigafat.get_date(PART_DATADOC); if (!datadoc.ok()) datadoc = esercizi().esercizio(esercizi().first()).inizio(); conf.set(MOV_DATADOC, datadoc); TString16 numdoc = rigafat.get(PART_NUMDOC); if (numdoc.blank()) numdoc = "1"; conf.set(MOV_NUMDOC, numdoc); conf.set("SOLAIVA", "X"); conf.set(MOV_STAMPATO, "X"); conf.set(MOV_REGST, "X"); conf.set(MOV_LIQDIFF, "X"); conf.set(MOV_DESCR, rigafat.get(PART_DESCR)); conf.set(MOV_TIPO, rigafat.get(PART_TIPOCF)); conf.set(MOV_CODCF, rigafat.get(PART_SOTTOCONTO)); conf.set(MOV_TOTDOC, rigafat.get(PART_IMPTOTDOC)); conf.set("CODIVA", _msk->get(F_CODIVA)); _fattsosp++; return nmov; } // Aggiunge una nuova rata alla UNICA fattura di 'game'. // Attenzione: in assenza di fattura ne viene creata una "al volo" di pari importo. void TImporta_sc::nuova_scadenza(const TImporta_cogeco_recset& recset, TPartita& game, bool is_riba) { int nriga = game.prima_fattura(); // PART_NRIGA della fattura (solitamente = 1) if (nriga <= 0) // Se non ci sono fattura in questa partita ... { nuova_fattura(recset, game); // Creo una nuova fattura nriga = game.prima_fattura(); // Aggiorno PART_NRIGA che valeva -1 } TRiga_partite& fattura = game.riga(nriga); // Accedo alla riga di fattura, che ora DEVE esistere! // Se la scadenza coincide o precede l'ultima, non creo una rata nuova const TDate datascad = recset.get_date(CGC_SCADENZA); int nrata = fattura.rate(); if (nrata > 0) { const TRiga_scadenze& rata = fattura.rata(nrata); if (datascad > rata.get_date(SCAD_DATASCAD)) nrata = 0; // Devo creare una rata nuova } if (nrata <= 0) { TRiga_scadenze& scadenza = fattura.new_row(); // Creo nuova rata, alla faccia di SCAD_CODPAG nrata = scadenza.get_int(SCAD_NRATA); // valeva 0 scadenza.put(SCAD_DATASCAD, recset.get_date(CGC_SCADENZA)); scadenza.put(SCAD_TIPOPAG, is_riba ? 3 : 1); set_descr(scadenza); } TRiga_scadenze& scadenza = fattura.rata(nrata); const real importo = recset.get_real(CGC_IMPORTO); scadenza.add(SCAD_IMPORTO, importo); } bool TImporta_sc::paga_rata(TPartita& game, int nrata, int nrigp, real& importo) const { const int nriga = game.prima_fattura(); if (nriga > 0) { const TRiga_partite& fattura = game.riga(nriga); TRiga_scadenze& scadenza = fattura.rata(nrata); const real residuo = scadenza.residuo(false).valore(); if (!residuo.is_zero()) // Considera solo rate aperte { // Elenco dei campi chiave da riportare dalla rata al pagamento const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART, PAGSCA_NRIGA, PAGSCA_NRATA, NULL }; const real pagare = residuo > importo ? importo : residuo; // Importo da pagare sulla rata TRectype rpag(LF_PAGSCA); for (int k = 0; field[k]; k++) rpag.put(field[k], scadenza.get(field[k])); rpag.put(PAGSCA_NRIGP, nrigp); // Completa la chiave di PAGSCA col numero riga di partita rpag.put(PAGSCA_IMPORTO, pagare); rpag.put(PAGSCA_ACCSAL, pagare >= residuo ? 'S' : 'A'); const TValuta euro; game.modifica_pagamento(rpag, euro, true); // Speriamo che faccia tutto lei :-) importo -= pagare; return true; } } return false; } // Aggiunge una nuova riga tipo 2 (n.c.) o 3 (pag.) alla partita void TImporta_sc::nuovo_pagamento_o_nota(const TImporta_cogeco_recset& recset, TPartita& game, tipo_movimento tm, bool is_riba) { // Crea una nuova riga di partita TRiga_partite& pagamento = game.new_row(); const int nrigp = pagamento.get_int(PART_NRIGA); // Ricorda numero da mettere in PAGSCA_NRIGP const TDate datadoc = recset.get_date(CGC_DATADOC); pagamento.put(PART_DATAREG, datadoc); pagamento.put(PART_DATADOC, datadoc); if (tm == tm_nota_credito) { const long numdoc = recset.get(CGC_NUMDOC).as_int(); if (numdoc > 0) pagamento.put(PART_NUMDOC, numdoc); } else pagamento.put(PART_DATAPAG, datadoc); // Cerca di inizlizzare la riga con una causale appropriata const char tipocf = game.conto().tipo(); const TCausale& caus = causale(tipocf, tm); if (caus.ok()) { pagamento.put(PART_CODCAUS, caus.codice()); pagamento.put(PART_REG, caus.reg().name()); pagamento.put(PART_TIPOMOV, caus.tipomov()); pagamento.put(PART_SEZ, caus.sezione(1)); } else { pagamento.put(PART_TIPOMOV, tm); pagamento.put(PART_SEZ, tipocf == 'F' ? 'D' : 'A'); } set_descr(pagamento); // Ora sono certo del TIPOMOV e posso generare la descrizione // Somma da distribuire sulle rate aperte real importo = recset.get_real(CGC_IMPORTO); pagamento.put(PART_IMPTOTDOC, importo); // Se esiste una fattura cerca di saldare il residuo delle rate aperte const int nriga = game.prima_fattura(); if (nriga > 0) { const TRiga_partite& fattura = game.riga(nriga); // Si assicura che la sezione sia inversa rispetto alla fattura pagamento.put(PART_SEZ, fattura.sezione() == 'D' ? 'A' : 'D'); while (true) { int best_rata = 0, best_score = 0; for (int nrata = 1; nrata <= fattura.rate() && !importo.is_zero(); nrata++) { const TRiga_scadenze& rata = fattura.rata(nrata); const real residuo = rata.residuo(false).valore(); if (!residuo.is_zero()) { const TDate data_scad = rata.get(SCAD_DATASCAD); int score = data_scad == datadoc ? 2 : 0; if (score == 0 && datadoc == data_scad+1L) score++; if (residuo >= importo) { score++; if (residuo == importo) score++; } if (score > best_score) { best_rata = nrata; best_score = score; } } } if (best_rata > 0) { if (is_riba) { const TRiga_scadenze& rata = fattura.rata(best_rata); if (rata.get_int(SCAD_TIPOPAG) == 3) // Per le RIBA precisa la data pagamento pagamento.put(PART_DATAPAG, rata.get(SCAD_DATASCAD)); } paga_rata(game, best_rata, nrigp, importo); } else break; } } // Se ci rimane qualcosa o non e' stata trovata una rata aperta allora crea un pagamento non assegnato if (!importo.is_zero()) { TRectype rpag(LF_PAGSCA); const char* const field[] = { PAGSCA_TIPOC, PAGSCA_SOTTOCONTO, PAGSCA_ANNO, PAGSCA_NUMPART, NULL }; for (int k = 0; field[k]; k++) rpag.put(field[k], pagamento.get(field[k])); rpag.put(PAGSCA_NRIGA, 9999); // Questo 9999 significa "fattura ignota" rpag.put(PAGSCA_NRATA, 9999); // Questo 9999 significa "rata ignota" rpag.put(PAGSCA_NRIGP, nrigp); // Completa la chiave di PAGSCA col numero riga di partita rpag.put(PAGSCA_IMPORTO, importo); rpag.put(PAGSCA_ACCSAL, 'A'); // Gli ancticipi sono sempre in acconto :-) const TValuta euro; game.modifica_pagamento(rpag, euro, true); } } void TImporta_sc::nuova_riba(const TImporta_cogeco_recset& recset, TPartita& game) { nuova_scadenza(recset, game, true); if (game.conto().tipo() == 'C') // Le riba cliente vengono considerate pagate subito! nuovo_pagamento_o_nota(recset, game, tm_pagamento, true); } // Creo una nuova riga partita corrispondente ad una riga pagamento in PAGSCA void TImporta_sc::nuovo_pagamento(const TImporta_cogeco_recset& recset, TPartita& game) { nuovo_pagamento_o_nota(recset, game, tm_pagamento, false); } // Creo una nuova riga partita corrispondente ad una riga nota di credito in PAGSCA void TImporta_sc::nuova_nota_credito(const TImporta_cogeco_recset& recset, TPartita& game) { nuovo_pagamento_o_nota(recset, game, tm_nota_credito, false); } // Creo una nuova riga partita corrispondente ad una riga di insoluto PAGSCA bool TImporta_sc::nuovo_insoluto(const TImporta_cogeco_recset& recset, TPartita& game, TLog_report& log) { const int nriga = game.prima_fattura(); // Cerco la fattura insoluta if (nriga <= 0) // Non e' carino creare un insoluto non assegnato return log_error(log, TR("Impossibile associare insoluto"), recset); const TDate datadoc = recset.get_date(CGC_DATADOC); real importo = recset.get_real(CGC_IMPORTO); // Cerca la miglior rata possibile da mandare insoluta // Per fare cio', si assegna un punteggio ad ogni rata, basato sulla data e sull'importo int best_rata = 0, best_score = 0; const TRiga_partite& fattura = game.riga(nriga); for (int nrata = fattura.rate(); nrata > 0; nrata--) { const TRiga_scadenze& scadenza = fattura.rata(nrata); const real imp = scadenza.importo_pagato(false).valore(); if (!imp.is_zero()) { const TDate data = scadenza.get(SCAD_DATASCAD); int score = datadoc == data ? 2 : 0; if (score == 0 && datadoc == data+1L) score++; if (imp >= importo) { score++; if (imp == importo) score++; } if (score > best_score) { best_rata = nrata; best_score = score; } } } if (best_rata > 0) // Se ho trovato almeno una rata compatibile con l'insoluto... { const TRiga_scadenze& scadenza = fattura.rata(best_rata); TRiga_partite& insoluto = game.new_row(); const int nrigp = insoluto.get_int(PART_NRIGA); insoluto.put(PART_DATAREG, datadoc); insoluto.put(PART_DATADOC, datadoc); insoluto.put(PART_IMPTOTDOC, importo); const char tipocf = game.conto().tipo(); const TCausale& caus = causale(tipocf, tm_insoluto); if (caus.ok()) { insoluto.put(PART_CODCAUS, caus.codice()); insoluto.put(PART_REG, caus.reg().name()); insoluto.put(PART_TIPOMOV, caus.tipomov()); insoluto.put(PART_SEZ, caus.sezione(1)); } else { insoluto.put(PART_TIPOMOV, tm_insoluto); insoluto.put(PART_SEZ, fattura.sezione()); } set_descr(insoluto); paga_rata(game, best_rata, nrigp, importo); } else log_error(log, TR("Impossibile associare insoluto"), recset); return best_rata > 0; } bool TImporta_sc::log_error(TLog_report& log, const char* msg, const TRecordset& recset) { TString message; message << recset.get(CGC_TIPOCF) << recset.get(CGC_CODCF) << '-' << recset.get(CGC_ANNO) << '/' << recset.get(CGC_NUMPART) << '.' << recset.get(CGC_NUMEROREC) << " : " << msg; log.log(2, message); return false; } // Ordina le righe di partita per TIPOCF+CODCF+ANNO+NUMPART+SCADENZA+TIPODOC static int game_sorter(const TObject** o1, const TObject** o2) { TToken_string& r1 = *(TToken_string*)*o1; TToken_string& r2 = *(TToken_string*)*o2; if (r1.get_int(0) != 1) return -1; // Riga testata! if (r2.get_int(0) != 1) return +1; // Riga testata! const char tipocf1 = r1.get_char(CGC_TIPOCF); const char tipocf2 = r2.get_char(CGC_TIPOCF); int cmp = tipocf1 - tipocf2; if (cmp != 0) return cmp; const long codice1 = r1.get_long(CGC_CODCF); const long codice2 = r2.get_long(CGC_CODCF); cmp = codice1 - codice2; if (cmp != 0) return cmp; const int anno1 = r1.get_int(CGC_ANNO); const int anno2 = r2.get_int(CGC_ANNO); cmp = anno1 - anno2; if (cmp != 0) return cmp; const int part1 = r1.get_int(CGC_NUMPART); const int part2 = r2.get_int(CGC_NUMPART); cmp = part1 - part2; if (cmp != 0) return cmp; const TString datadoc1 = r1.get(CGC_DATADOC); if (datadoc1.blank() || datadoc1 == "00/00/0000") return -1; const TString datadoc2 = r2.get(CGC_DATADOC); if (datadoc2.blank() || datadoc2 == "00/00/0000") return +1; cmp = TDate(datadoc1)-TDate(datadoc2); if (cmp != 0) return cmp; const TString data1 = r1.get(CGC_SCADENZA); if (data1.blank() || data1 == "00/00/0000") return -1; const TString data2 = r2.get(CGC_SCADENZA); if (data2.blank() || data2 == "00/00/0000") return +1; cmp = TDate(data1)-TDate(data2); if (cmp != 0) return cmp; // I tipi documento vanno ordinati in base alla sequenza sequente, non in base al valore numerico! TToken_string priority = "1|3|15|2|4|5|6|7|8|9|10|11"; const int tipodoc1 = r1.get_int(CGC_TIPODOC); const int tipodoc2 = r2.get_int(CGC_TIPODOC); int pri1 = priority.get_pos(tipodoc1); if (pri1 < 0) pri1 = 100+tipodoc1; int pri2 = priority.get_pos(tipodoc2); if (pri2 < 0) pri2 = 100+tipodoc2; cmp = pri1 - pri2; return cmp; } void TImporta_sc::salva_partita(TPartita*& game, long nmov) { if (game != NULL) { game->write(); if (_fattsosp > 0 && game->chiusa(true)) { while (_fattsosp-- > 0) { TFilename temp(_msk->get(F_PATHOUT)); temp << '/' << format("%05ld", --nmov); temp.ext("ini"); if (fexist(temp)) remove_file(temp); } } _fattsosp = 0; delete game; game = NULL; } } void TImporta_sc::transfer(const TFilename& file) { TImporta_cogeco_recset recset(file); recset.sort(game_sorter); const TString& caption = main_app().title(); TProgind pi(recset.items(), caption, true, true); TConfig* conf = NULL; int anno = 0; long part = 0; char tipocf = ' '; long sottoconto = 0L; TPartita* game = NULL; TToken_string key; const TString& codcausc = _msk->get(F_CODCAUSC); const TString& codcausf = _msk->get(F_CODCAUSF); long nmov = 1L; _fattsosp = 0; TLog_report log(caption); for (bool ok = recset.move_to(0); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; const int chk = recset.get(CGC_NULL).as_int(); if (chk != 1) // Prende solo righe buone! continue; const char t = recset.get(CGC_TIPOCF).as_string()[0]; const long s = recset.get(CGC_CODCF).as_int(); const int a = recset.get(CGC_ANNO).as_int(); const long p = recset.get(CGC_NUMPART).as_int(); if (tipocf != t || sottoconto != s || anno != a || p != part) { salva_partita(game, nmov); // Salva parita corrente se non nulla TToken_string key; key.format("%c|%ld", t, s); const TRectype& clifo = cache().get(LF_CLIFO, key); if (clifo.empty()) { log_error(log, TR("Codice Cliente/Fornitore non valido"), recset); continue; } if (a < 2000) { log_error(log, TR("Anno partita non valido"), recset); continue; } if (p <= 0) { log_error(log, TR("Numero partita non valido"), recset); continue; } tipocf = t; sottoconto = s; anno = a; part = p; if (game == NULL) { int gruppo = 0, conto = 0; if (find_clifo_bill(tipocf, gruppo, conto, sottoconto)) { const TBill codclifo(gruppo, conto, sottoconto, tipocf); game = new TPartita(codclifo, anno, format("%ld", part)); } else { log_error(log, TR("Impossibile determinare il conto cliente/fornitore"), recset); break; // Esce subito, probabilmente il piano dei conti non e' stato ancora importato } } } if (game != NULL) { const int tipodoc = recset.get(CGC_TIPODOC).as_int(); switch (tipodoc) { case 1: nuova_fattura(recset, *game); break; // Fattura case 2: nuova_nota_credito(recset, *game); break; // Nota di credito case 3: { const TRiga_partite & rigafat = nuova_fattura(recset, *game); nmov = fattura_in_sospensione( recset, rigafat, nmov); break; } // Fattura in sospensione case 4: nuova_nota_credito(recset, *game); break; // Reso su fattura in sospensione case 5: nuovo_pagamento(recset, *game); break; // Pagamento fattura in sospeso case 6: nuovo_insoluto(recset, *game, log); break; // Insoluto case 8: // Tratta case 9: // Ri.Ba. case 10: nuova_riba(recset, *game); break; // Cambiale case 11: nuovo_pagamento(recset, *game); break; // Pagamento case 13: nuova_nota_credito(recset, *game); break; // Nota di credito su RB clienti case 14: nuova_nota_credito(recset, *game); break; // Abbuono case 15: nuova_scadenza(recset, *game, false); break; case 18: nuova_riba(recset, *game); break; // Paghero' case 19: nuova_riba(recset, *game); break; // Avviso di scadenza case 20: nuova_riba(recset, *game); break; // R.I.D. default: log_error(log, TR("Tipo documento non riconosciuto"), recset); break; } } } salva_partita(game, nmov); // Salva ultima partita se non nulla if (nmov > 1 && yesno_box(FR("Si desidera confermare l'importazione di %ld fatture in sospensione"), nmov - 1)) { TString app; app << "cg2 -0 -i" << _msk->get(F_PATHOUT) << "/*.ini"; TExternal_app primanota(app); primanota.run(true); } if (log.recordset()->items() > 0) log.preview(); } bool TImporta_sc::create() { // Determina i conti per clienti e fornitori nel caso non siano in anagrafica TString query; query << "USE PCON SELECT TMCF!=\'\'"; TISAM_recordset pcon(query); for (bool ok = pcon.move_first(); ok; ok = pcon.move_next()) { const TRectype& rec = pcon.cursor()->curr(); const char tmcf = rec.get_char(PCN_TMCF); if (tmcf == 'C' && _clienti.gruppo() == 0) _clienti.get(rec); if (tmcf == 'F' && _fornitori.gruppo() == 0) _fornitori.get(rec); } _msk = new TImporta_sc_mask(); return TSkeleton_application::create(); } bool TImporta_sc::destroy() { delete _msk; return TApplication::destroy(); } void TImporta_sc::main_loop() { if (_msk->run() == K_ENTER) { _cache_causali.init(_msk->get(F_CODCAUSC), _msk->get(F_CODCAUSF)); //genero il nome del file da caricare TFilename name = _msk->get(F_PATH); name.add(_msk->get(F_NAME)); transfer(name); } } int lv4200 (int argc, char* argv[]) { TImporta_sc main_app; main_app.run(argc, argv, TR("Importazione saldaconto COGECO")); return true; }