From 47f8d9a67b3edab9625b144ce884761970d6102c Mon Sep 17 00:00:00 2001 From: guy Date: Thu, 27 Jan 2011 11:22:59 +0000 Subject: [PATCH] =?UTF-8?q?Patch=20level=20=20=20=20=20=20=20=20=20:=20910?= =?UTF-8?q?=20Files=20correlati=20=20=20=20=20:=20sc1.exe=20sc1400a.msk=20?= =?UTF-8?q?scmenu.men=20Ricompilazione=20Demo=20:=20[=20]=20Commento=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20:=20E'=20stato=20creato=20un=20nu?= =?UTF-8?q?ovo=20programma=20nel=20menu=20di=20servizio=20del=20saldaconto?= =?UTF-8?q?.=20Esso=20richiede=20un=20importo=20minimo=20e=20la=20sua=20ev?= =?UTF-8?q?entuale=20divisa=20e=20cambio.=20Dopo=20aver=20selezionato=20un?= =?UTF-8?q?a=20opportuna=20causale=20contabile,=20viene=20mostrata=20la=20?= =?UTF-8?q?lista=20tutte=20le=20scadenze=20(non=20partite!)=20con=20residu?= =?UTF-8?q?o=20inferiore=20a=20quello=20specificato=20per=20ogni=20cliente?= =?UTF-8?q?/fornitore.=20Una=20volta=20selezionate=20una=20o=20pi=C3=B9=20?= =?UTF-8?q?scadenze=20viene=20generato=20un=20movimento=20contabile=20coll?= =?UTF-8?q?egato=20al=20saldaconto=20che=20le=20chiude=20con=20abbuoni=20e?= =?UTF-8?q?d=20eventuali=20differenze=20cambi.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://10.65.10.50/branches/R_10_00@21525 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- sc/sc1.cpp | 8 +- sc/sc1.h | 1 + sc/sc1400.cpp | 414 ++++++++++++++++++++++++++++++++++++++++++++++++- sc/sc1400.h | 12 ++ sc/sc1400a.uml | 110 ++++++++++++- sc/sc2100.cpp | 5 +- sc/scmenu.men | 1 + 7 files changed, 539 insertions(+), 12 deletions(-) diff --git a/sc/sc1.cpp b/sc/sc1.cpp index 4bf5a59e3..333bef7e1 100755 --- a/sc/sc1.cpp +++ b/sc/sc1.cpp @@ -7,10 +7,10 @@ int main(int argc,char** argv) const int n = (argc > 1) ? (atoi(&argv[1][1])) : 0; switch(n) { - case 1: sc1200(argc,argv); break; - case 2: sc1300(argc,argv); break; - case 3: sc1400(argc,argv); break; - default: sc1100(argc,argv); break; + case 1: sc1200(argc,argv); break; // Apertura scadenze da saldi + case 2: sc1300(argc,argv); break; // Allineamento partite + case 3: sc1400(argc,argv); break; // Abbuoni automatici + default: sc1100(argc,argv); break; // Archiviazione partite pareggiate } return 0; } diff --git a/sc/sc1.h b/sc/sc1.h index 9cd7bebcc..7a0a28906 100755 --- a/sc/sc1.h +++ b/sc/sc1.h @@ -2,3 +2,4 @@ int sc1100(int argc, char** argv); int sc1200(int argc, char** argv); int sc1300(int argc, char** argv); int sc1400(int argc, char** argv); + diff --git a/sc/sc1400.cpp b/sc/sc1400.cpp index 3b639c429..a2c5fe964 100755 --- a/sc/sc1400.cpp +++ b/sc/sc1400.cpp @@ -1,28 +1,437 @@ #include #include +#include #include #include #include #include #include - #include "sc1400.h" +#include "../cg/cg2101.h" +#include "../cg/cg2103.h" #include "../cg/cgsaldac.h" +#include + +/////////////////////////////////////////////////////////// +// TAbbuona_sheet +/////////////////////////////////////////////////////////// + +enum { C_CHECKED, C_GRUPPO, C_CONTO, C_CODCF, C_RAGSOC, C_IMPORTO, C_RESIDUO, C_CODVAL, C_DATASCAD, C_ANNO, C_PARTITA, C_RIGA, C_RATA }; + +class TAbbuona_sheet : public TArray_sheet +{ + virtual bool get_cell_colors(int row, int col, COLOR& fore, COLOR& back) const; + +public: + TAbbuona_sheet(); +}; + +bool TAbbuona_sheet::get_cell_colors(int /*row*/, int col, COLOR& fore, COLOR& back) const +{ + if (col == C_RESIDUO) // Evidenzia la colonna del residuo + { + fore = NORMAL_COLOR; + back = REQUIRED_BACK_COLOR; + return true; + } + return false; +} + +TAbbuona_sheet::TAbbuona_sheet() : TArray_sheet(0, 0, 0, 0, TR("Scadenze aperte"), + HR("@1C|Grp.@3|Cnt.@3|Codice@R|Ragione Sociale@50|Importo@10R|Residuo@10R|Val.|Data@10|Anno@R|Partita@8R|Riga@R|Rata@R"), + 0x1, 1) +{} + +/////////////////////////////////////////////////////////// +// TAbbuona_mask +/////////////////////////////////////////////////////////// + +class TAbbuona_mask : public TAutomask +{ +protected: + virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + + void auto_proponi(short id, bool last); // Propone il primo/ultimo record del cursore associato al campo id + +public: + TAbbuona_mask() : TAutomask("sc1400a") {} +}; + +void TAbbuona_mask::auto_proponi(short id, bool last) +{ + TEdit_field& e =efield(id); + TBrowse& b = *e.browse(); + TCursor& c = *b.cursor(); + b.do_input(true); // Reimposta filtri + const TRecnotype items = c.items(); + if (items > 0) + { + c = last ? (items-1): 0L; // Si posiziona sul primo buono + if (c.ok()) + { + b.do_output(); // Lo propone automaticamente + e.set_dirty(); + } + } +} + +bool TAbbuona_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) +{ + switch (o.dlg()) + { + case F_TIPOCF: + case F_INVALUTA: + if (e == fe_modify) + auto_proponi(F_CAUSALE, false); + break; + case F_CODVAL: + if (e == fe_modify) + { + if (is_true_value(o.get())) + auto_proponi(F_DATACAMBIO, true); + else + set(F_INVALUTA, "", 0x1); + } + break; + case F_IMPORTO: + if (e == fe_init && o.empty()) + o.set(50); + break; + case F_CAUSALE: + if (e == fe_init) + auto_proponi(F_CAUSALE, false); + if (e == fe_modify || e == fe_close) + { + const TCausale caus(o.get()); + const int riga_abb = get(F_TIPOCF) == "C" ? RIGA_ABBUONI_PASSIVI : RIGA_ABBUONI_ATTIVI; + TBill conto_abbuoni; caus.bill(riga_abb, conto_abbuoni); + if (!conto_abbuoni.find()) + return error_box(TR("Il conto per gli abbuoni alla riga %d della causale non è valido"), riga_abb); + if (get_bool(F_INVALUTA)) + { + TBill conto_diffcam; caus.bill(RIGA_DIFFCAM, conto_diffcam); + if (!conto_diffcam.find()) + return error_box(TR("Il conto per le differenze cambi della causale non è valido")); + } + } + break; + case F_DATACOMP: + if (e == fe_close) + { + const TDate datareg = get(F_DATAREG); + TDate datacomp = o.get(); + if (!datacomp.ok() || datacomp > datareg) + { + datacomp = datareg; + o.set(datacomp.string()); + } + } + break; + default: + break; + } + return true; +} + +/////////////////////////////////////////////////////////// +// TAbbuona_partite +/////////////////////////////////////////////////////////// + class TAbbuona_partite : public TSkeleton_application { protected: // Applicat virtual void main_loop(); + bool genera_abbuono(TPartita& game, int nriga, int nrata, + const TMovimentoPN& mov, TLog_report& log) const; public: + void fill_sheet(const char tipocf, const TCurrency& impmin, TAbbuona_sheet& sheet); + bool elabora(const TMask& msk, TAbbuona_sheet& sheet) const; }; +void TAbbuona_partite::fill_sheet(const char tipocf, const TCurrency& imp_min, TAbbuona_sheet& sheet) +{ + const bool in_valuta = !imp_min.is_firm_value(); + const TString4 cod_val = in_valuta ? imp_min.get_value() : EMPTY_STRING; + const TCurrency zero_val(ZERO, cod_val); + + TString query; // Selezione delle scadenze aperte + query << "USE SCAD\n" + << "SELECT (PAGATA!=\"X\")&&(BLOCCATA!=\"X\")\n" + << "FROM TIPOC=" << tipocf << "\nTO TIPOC=" << tipocf; + + TISAM_recordset scadenze(query); + const TRectype& scad = scadenze.cursor()->curr(); + + TString msg; + msg << TR("Elaborazione scadenze aperte per meno di ") << imp_min.string(true) << ' '; + msg << (in_valuta ? cod_val : TCurrency::get_firm_val()); + TProgind pi(scadenze.items(), msg); + TToken_string row; // Riga di lavoro sullo sheet + for (bool ok = scadenze.move_first(); ok; ok = scadenze.move_next()) + { + if (!pi.addstatus(1)) + break; + + row.cut(0) << tipocf; + row.add(0); + row.add(0); + row.add(scad.get(SCAD_SOTTOCONTO)); + row.add(scad.get(SCAD_ANNO)); + row.add(scad.get(SCAD_NUMPART)); + row.add(scad.get(SCAD_NRIGA)); + const TRectype& game_rec = cache().get(LF_PARTITE, row); + + // Ignora partite con la valuta incompatibile + const TString& game_val = game_rec.get(PART_CODVAL); + if (in_valuta) + { + if (game_val != cod_val) + continue; + } + else + { + if (is_true_value(game_val)) + continue; + } + + TPartita partita(game_rec); + const int nriga = scad.get_int(SCAD_NRIGA); + const int nrata = scad.get_int(SCAD_NRATA); + TRiga_scadenze& rata = partita.riga(nriga).rata(nrata); + TImporto imp_res = rata.residuo(in_valuta); + imp_res.normalize(tipocf == 'C' ? 'D' : 'A'); + const TCurrency residuo(imp_res.valore(), cod_val); + if (residuo > zero_val && residuo <= imp_min) + { + TImporto imp_val = rata.importo(in_valuta); + imp_val.normalize(imp_res.sezione()); + const TCurrency importo(imp_val.valore(), cod_val); + const TBill& conto = partita.conto(); + row = "X"; + row.add(game_rec.get(PART_GRUPPOCL)); + row.add(game_rec.get(PART_CONTOCL)); + row.add(conto.codclifo()); + row.add(conto.descrizione()); + row.add(importo.string(true)); + row.add(residuo.string(true)); + row.add(cod_val); + row.add(scad.get(SCAD_DATASCAD)); + row.add(scad.get(SCAD_ANNO)); + row.add(scad.get(SCAD_NUMPART)); + row.add(nriga); + row.add(nrata); + sheet.add(row); + } + } +} + +bool TAbbuona_partite::genera_abbuono(TPartita& game, int nriga, int nrata, + const TMovimentoPN& mov, TLog_report& log) const +{ + TString msg; + msg.format(FR(" %d della riga %d della partita %d/%s"), + nrata, nriga, game.anno(), (const char*)game.numero()); + + if (!game.esiste(nriga, nrata)) // Non si sa mai col saldaconto! + { + msg.insert(TR("Non esiste la rata")); + log.log(1, msg); + return false; + } + + const TRectype& head = mov.curr(); + const TValuta valuta(head); + + // Creo una riga di partita di tipo pagamento e ci copio i dati della testata del movimento + TRiga_partite& riga = game.new_row(); + const int nrigp = riga.get_int(PART_NRIGA); + riga.put(PART_TIPOMOV, tm_pagamento); + riga.put(PART_SEZ, game.conto().tipo() == 'F' ? 'D' : 'A'); + riga.put(PART_NREG, head.get(MOV_NUMREG)); + riga.put(PART_NUMRIG, mov.cg_items()); + riga.put(PART_DATAREG, head.get(MOV_DATAREG)); + riga.put(PART_DATAPAG, head.get(MOV_DATACOMP)); + riga.put(PART_CODCAUS, head.get(MOV_CODCAUS)); + riga.put(PART_NUMDOC, head.get(MOV_NUMDOC)); + riga.put(PART_DATADOC, head.get(MOV_DATADOC)); + riga.put(PART_DESCR, head.get(MOV_DESCR)); + if (valuta.in_valuta()) + valuta.put(riga); + + // Creo una nuova riga di pagamento assegnado il flag di saldo + TRiga_scadenze& scad = game.rata(nriga, nrata); + TRectype new_pag = scad.new_row(nrigp); // Creo nuova riga e la duplico + new_pag.put(PAGSCA_ACCSAL, 'S'); // Pongo pagamento a saldo + const bool empty = game.modifica_pagamento(new_pag, valuta, true); + + if (empty) + { + msg.insert(TR("Errore di chiusura della rata")); + log.log(2, msg); + } + else + { + msg.insert(TR("Chiusa rata")); + log.log(0, msg); + } + return !empty; +} + +bool TAbbuona_partite::elabora(const TMask& msk, TAbbuona_sheet& scad_sheet) const +{ + // La validità di tutti questi campi è già garantita dai controlli di msk + const char tipo_cf = msk.get(F_TIPOCF)[0]; + const TDate datareg = msk.get(F_DATAREG); + const TDate datacomp = msk.get(F_DATACOMP); + const TValuta valuta(msk, F_CODVAL, F_DATACAMBIO, F_CAMBIO); + + const TCausale caus(msk.get(F_CAUSALE), datareg.year()); + const int riga_abb = tipo_cf == 'C' ? RIGA_ABBUONI_PASSIVI : RIGA_ABBUONI_ATTIVI; + TBill conto_abbuoni; caus.bill(riga_abb, conto_abbuoni); + + TBill conto_diffcam; + if (valuta.in_valuta()) + caus.bill(RIGA_DIFFCAM, conto_diffcam); + + TMovimentoPN mov; + TRectype& head = mov.curr(); + head.put(MOV_CODCAUS, msk.get(F_CAUSALE)); + head.put(MOV_DATAREG, datareg); + head.put(MOV_DATACOMP, datacomp); + head.put(MOV_DESCR, TR("Abbuoni automatici")); + if (valuta.in_valuta()) + valuta.put(head); + + if (mov.write() != NOERR) + return error_box(TR("Impossibile creare il movimento di prima nota")); + + const long numreg = head.get_long(MOV_NUMREG); // Numero registrazione per saldaconto + TLog_report log; + TString msg; + + msg << TR("Creazione della testata del movimento n.") << numreg; + log.log(1, msg); + + TPartite_array partite; + bool can_write = true; + + TBill last_clifo; + + FOR_EACH_CHECKED_ROW(scad_sheet, r, row) + { + const TBill bill(row->get_int(C_GRUPPO), row->get_int(C_CONTO), row->get_long(C_CODCF), tipo_cf); + const int anno = row->get_int(C_ANNO); + const TString8 numpart = row->get(C_PARTITA); + const int nriga = row->get_int(C_RIGA); + const int nrata = row->get_int(C_RATA); + TPartita& game = partite.partita(bill, anno, numpart); + + if (bill != last_clifo) + { + log.log(0, msg.cut(0)); + msg << TR("Elaborazione scadenze ") << bill.descrizione(); + log.log(1, msg); + TRectype& new_rmov = mov.cg(-1); + bill.put(new_rmov); + new_rmov.put(RMV_ROWTYPE, 'K'); + last_clifo = bill; + } + if (!genera_abbuono(game, nriga, nrata, mov, log)) + can_write = false; + } + + TImporto abbuoni, diffcam; + for (int i = 0; i < mov.cg_items(); i++) + { + // Calcola importo speso sul saldaconto per ogni riga contabile + TImporto abb = partite.importo_speso(numreg, i+1, false, 0x2); + abbuoni -= abb; // Aggiungi abbuono al relativo totalizzatore + + TImporto imp = abb; + + TImporto dic; + if (valuta.in_valuta()) + { + dic = partite.importo_speso(numreg, i+1, false, 0x4); + diffcam -= dic; // Aggiungi differenza cambi al relativo totalizzatore + + imp += dic; + imp.normalize(); + } + + TRectype& rmov = mov.cg(i); + rmov.put(RMV_SEZIONE, imp.sezione()); + rmov.put(RMV_IMPORTO, imp.valore()); + } + if (abbuoni.is_zero()) + { + log.log(2, TR("Il totale degli abbuoni è nullo.")); + can_write = false; + } + else + { + abbuoni.normalize(); + + TRectype& rmov = mov.cg(-1); + rmov.put(RMV_ROWTYPE, tipo_cf == 'F' ? 'A' : 'P'); // Abbuoni attivi o passivi? + rmov.put(RMV_SEZIONE, abbuoni.sezione()); + rmov.put(RMV_IMPORTO, abbuoni.valore()); + conto_abbuoni.put(rmov); + } + + if (!diffcam.is_zero()) + { + diffcam.normalize(); + + TRectype& rmov = mov.cg(-1); + rmov.put(RMV_ROWTYPE, 'C'); // Differenze cambio + rmov.put(RMV_SEZIONE, diffcam.sezione()); + rmov.put(RMV_IMPORTO, diffcam.valore()); + conto_diffcam.put(rmov); + } + + if (can_write) + { + if (mov.rewrite() == NOERR) + { + partite.write(true); + + log.log(0, msg.cut(0)); + msg << TR("Aggiornato saldaconto legato al movimento n.") << numreg; + log.log(1, msg); + } + else + { + log.log(2, "Impossibile aggiornare il saldaconto"); + can_write = false; + } + } + if (!can_write) + { + const int err = mov.remove(); + msg = err == NOERR ? TR("Eliminato") : TR("Impossibile eliminare"); + msg << TR(" il movimento n.") << numreg; + log.log(1, msg); + } + log.preview(); + return can_write; +} + + void TAbbuona_partite::main_loop() { - TMask msk("sc1400a"); + TAbbuona_mask msk; while (msk.run() == K_ENTER) { + const char tipo_cf = msk.get(F_TIPOCF)[0]; + TCurrency imp_min; msk.get_currency(F_IMPORTO, imp_min); + TAbbuona_sheet scad_sheet; + fill_sheet(tipo_cf, imp_min, scad_sheet); + if (scad_sheet.run() == K_ENTER && scad_sheet.one_checked()) + elabora(msk, scad_sheet); } } @@ -32,3 +441,4 @@ int sc1400(int argc, char** argv) a.run(argc, argv, TR("Abbuoni automatici")); return 0; } + diff --git a/sc/sc1400.h b/sc/sc1400.h index e69de29bb..f18aed15c 100755 --- a/sc/sc1400.h +++ b/sc/sc1400.h @@ -0,0 +1,12 @@ +#define F_TIPOCF 101 +#define F_IMPORTO 102 + +#define F_INVALUTA 151 +#define F_CODVAL 152 +#define F_DATACAMBIO 153 +#define F_CAMBIO 154 + +#define F_CAUSALE 201 +#define F_DESCAUS 202 +#define F_DATAREG 203 +#define F_DATACOMP 204 diff --git a/sc/sc1400a.uml b/sc/sc1400a.uml index aaed0a436..dfaf19a00 100755 --- a/sc/sc1400a.uml +++ b/sc/sc1400a.uml @@ -1,11 +1,113 @@ #include "sc1400.h" -PAGE "Abbuoni automatici" -1 -1 50 6 - -ENDPAGE - TOOLBAR "" 0 0 0 2 #include ENDPAGE +PAGE "Abbuoni automatici" 0 2 0 0 + +LIST F_TIPOCF 1 10 +BEGIN + PROMPT 1 1 "Chiusura automatica delle scadenze dei " + IT "C|Clienti" + IT "F|Fornitori" +END + +CURRENCY F_IMPORTO 12 +BEGIN + PROMPT 1 2 "il cui residuo non superi l'importo di " + DRIVENBY F_CODVAL + CHECKTYPE REQUIRED + WARNING "E' necessario specificare un importo massimo" +END + +BOOLEAN F_INVALUTA +BEGIN + PROMPT 1 3 "in valuta " + MESSAGE FALSE HIDE,3@ + MESSAGE TRUE SHOW,3@ +END + +STRING F_CODVAL 3 +BEGIN + PROMPT 16 3 "" + USE %VAL + INPUT CODTAB F_CODVAL + DISPLAY "Codice" CODTAB + DISPLAY "Descrizione@50" S0 + OUTPUT F_CODVAL CODTAB + CHECKTYPE REQUIRED + GROUP 3 + FLAGS "U" +END + +DATE F_DATACAMBIO +BEGIN + PROMPT 25 3 "al cambio del " + FIELD DATACAM + USE CAM + JOIN %VAL ALIAS 104 INTO CODTAB[1,3]==CODTAB[1,3] + INPUT CODTAB[1,3] F_CODVAL SELECT + INPUT CODTAB[4,11] F_DATACAMBIO + DISPLAY "Cod" CODTAB[1,3] + DISPLAY "Data@10" D0 + DISPLAY "Cambio@16R" S4 + DISPLAY "Valuta@50" 104@->S0 + OUTPUT F_DATACAMBIO D0 + OUTPUT F_CAMBIO S4 + GROUP 3 + CHECKTYPE SEARCH +END + +NUMBER F_CAMBIO 16 6 +BEGIN + PROMPT 55 3 "di " + FLAGS "RU" + GROUP 3 + PICTURE ".6" + CHECKTYPE REQUIRED + WARNING "Inserire il cambio o eliminare il codice valuta" +END + +GROUP DLG_NULL 78 4 +BEGIN + PROMPT 1 4 "Parametri movimento contabile" +END + +STRING F_CAUSALE 3 +BEGIN + PROMPT 2 5 "Causale " + USE LF_CAUSALI SELECT (TIPOMOV="3")&&(TRIM(MOVVAL)=#F_INVALUTA)&&(LF_RCAUSALI->TIPOCF=#F_TIPOCF) + JOIN LF_RCAUSALI INTO CODCAUS==CODCAUS + INPUT CODCAUS F_CAUSALE + DISPLAY "Codice" CODCAUS + DISPLAY "Descrizione@50" DESCR + OUTPUT F_CAUSALE CODCAUS + OUTPUT F_DESCAUS DESCR + CHECKTYPE REQUIRED + FLAGS "U" + ADD RUN cg0 -4 +END + +STRING F_DESCAUS 50 +BEGIN + PROMPT 24 5 "" + FLAGS "D" +END + +DATE F_DATAREG +BEGIN + PROMPT 2 6 "Data di registrazione " + FLAGS "A" + CHECKTYPE REQUIRED +END + +DATE F_DATACOMP +BEGIN + PROMPT 44 6 "Data di competenza " + VALIDATE DATE_CMP_FUNC <= F_DATAREG +END + +ENDPAGE + ENDMASK diff --git a/sc/sc2100.cpp b/sc/sc2100.cpp index b4772c192..ca96587f0 100755 --- a/sc/sc2100.cpp +++ b/sc/sc2100.cpp @@ -12,8 +12,9 @@ #include "sc2100a.h" #include "sc21pec.h" -#include "../cg/cgsaldac.h" #include "../ca/calib01.h" +#include "../ca/movana.h" +#include "../cg/cgsaldac.h" #include "../pr/agenti.h" #include @@ -769,7 +770,7 @@ void TEC_array::arrange_scaduto(const TPartita& game) } TEC_array::TEC_array(const TPartita& game, const TEC_form* f) - : _form(f), _anal(LF_MOVANA, "NUMREG", 3) + : _form(f), _anal(LF_MOVANA, MOVANA_NUMREG, 3) { int r; for (r = game.last(); r > 0; r = game.pred(r)) diff --git a/sc/scmenu.men b/sc/scmenu.men index 8d0591b31..a199fd063 100755 --- a/sc/scmenu.men +++ b/sc/scmenu.men @@ -19,4 +19,5 @@ Flags = "" Item_01 = "Stampa controllo saldi", "sc2 -4", "" Item_02 = "Creazione saldaconto da saldi", "sc1 -1", "" Item_03 = "Allineamento Partite", "sc1 -2", "F" +Item_04 = "Abbuoni automatici", "sc1 -3", "F"