#include #include #include #include #include #include #include #include #include "../ca/calib01.h" #include "cilib.h" #include "ci2.h" #include "ci2400a.h" #include #include "../ca/commesse.h" #include "../ca/cfcms.h" #include "../ca/movana.h" #include "../ca/rmovana.h" #include "rilore.h" #include /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// static void advanced_draw_justified_text_line(WINDOW w, const char* text, short x, short y, short dx) { TString256 txt(text); txt.rtrim(); int spaces = 0; for (int s = 0; txt[s]; s++) if (isspace(txt[s])) spaces++; // Il testo e' giustificabile se ha degli spazi ed occupa meno della riga if (spaces > 0) { const int tw = xvt_dwin_get_text_width(w, txt, -1); if (tw < dx) { txt << ' '; // Aggiunge spazio finale const double kspc = double(dx - tw) / spaces; int start = 0; double kx = x; for (int i = 0; txt[i]; i++) if (isspace(txt[i])) { const bool last_word = txt[i+1] == '\0'; const TString& parola = txt.sub(start, i + (last_word ? 0 : 1)); const int lw = xvt_dwin_get_text_width(w, parola, -1); if (last_word) // ultima parola ("vedova") kx = x+dx-lw; xvt_dwin_draw_text(w, int(kx+0.5), y, parola, -1); kx += lw + kspc; start = i+1; } } else xvt_dwin_draw_text(w, x, y, txt, -1); // Stringa che deborda dalla riga } else xvt_dwin_draw_text(w, x, y, txt, -1); // Stringa senza spazi } static void advanced_draw_text_line(WINDOW w, const char* text, const RCT& r, char halign, char valign) { const short dx = r.right-r.left; const short dy = r.bottom-r.top; short x = r.left; short y = r.bottom; if (halign != 'L') { const int tw = xvt_dwin_get_text_width(w, text, -1); switch (halign) { case 'C': x += (dx - tw)/2; break; case 'R': x = r.right-tw-1; break; default : break; } } // Text Height int leading, ascent, descent; xvt_dwin_get_font_metrics(w, &leading, &ascent, &descent); switch (valign) { case 'C': y -= (dy - ascent-descent)/2; break; case 'T': y = r.top + ascent; break; default : y -= descent+leading; break; } bool can_draw = true; RCT orig; xvt_dwin_get_clip(w, &orig); bool restore_clip = !xvt_rect_is_empty(&orig); if (restore_clip) { RCT clipper; can_draw = xvt_rect_intersect(&clipper, &orig, &r) != 0; if (can_draw) xvt_dwin_set_clip(w, &clipper); else restore_clip = false; } else xvt_dwin_set_clip(w, &r); if (can_draw) { if (halign == 'J') advanced_draw_justified_text_line(w, text, x, y, dx); else xvt_dwin_draw_text(w, x, y, text, -1); if (restore_clip) xvt_dwin_set_clip(w, &orig); } } /////////////////////////////////////////////////////////// // TConsuntivazione_field /////////////////////////////////////////////////////////// class TConsuntivazione_window : public TField_window { int _rows, _cols; TDate _date; protected: virtual void update(); virtual long handler(WINDOW win, EVENT* ep); void cell2rct(int c, RCT& rct) const; void query(TString& month) const; void set_font(int nHeight); COLOR day2color(const TDate& d) const; public: void set_date(const TDate& d); TConsuntivazione_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner); }; void TConsuntivazione_window::cell2rct(int c, RCT& r) const { const int row = c / _cols; const int col = c % _cols; RCT rct; xvt_vobj_get_client_rect(win(), &rct); r.left = col * rct.right / _cols; r.top = row * rct.bottom / _rows; r.right = (col+1) * rct.right / _cols; r.bottom = (row+1) * rct.bottom / _rows; } void TConsuntivazione_window::set_date(const TDate& d) { if (d.ok()) { const int old_month = _date.month(); const int new_month = d.month(); _date = d; if (new_month != old_month) force_update(); } } void TConsuntivazione_window::query(TString& busy) const { TDate dal = _date; dal.set_day(1); TDate al = _date; al.set_end_month(); busy.fill(' ', 31); TString query; query << "USE RILORE KEY 2"; query << "\nFROM TIPO=C DADATA=" << dal.string() << "\nTO TIPO=C DADATA=" << al.string(); TISAM_recordset def(query); for (bool ok = def.move_first(); ok; ok = def.move_next()) { const TDate d = def.get("DADATA").as_date(); if (d >= dal && d <= al) busy.overwrite("W", d.day()-1); } } void TConsuntivazione_window::set_font(int nHeight) { XVT_FNTID fontid = xvt_font_create(); xvt_font_set_family(fontid, XVT_FFN_HELVETICA); xvt_font_set_style(fontid, nHeight > 8 ? XVT_FS_BOLD : XVT_FS_BOLD); xvt_font_set_size(fontid, nHeight); xvt_dwin_set_font(win(), fontid); xvt_font_destroy(fontid); } inline bool is_red_day(const TDate& d) { return d.wday() >= 6 || d.is_holiday(); } COLOR TConsuntivazione_window::day2color(const TDate& d) const { const COLOR festivo = COLOR_RED; const COLOR feriale = COLOR_BLUE; const COLOR ponte = blend_colors(festivo, feriale); if (is_red_day(d)) return festivo; if (d.month() == 12 && (d.day() == 24 || d.day() == 31)) return ponte; TDate yesterday = d; --yesterday; TDate tomorrow = d; ++tomorrow; if (is_red_day(yesterday) && is_red_day(tomorrow)) return ponte; return feriale; } void TConsuntivazione_window::update() { WINDOW dc = win(); RCT rct; xvt_vobj_get_client_rect(dc, &rct); xvt_dwin_draw_gradient_linear(dc, &rct, blend_colors(NORMAL_BACK_COLOR, REQUIRED_BACK_COLOR), NORMAL_BACK_COLOR, 90); int lato = int(sqrt(rct.right * rct.bottom / 32.0)); do { _rows = rct.bottom / lato; _cols = rct.right / lato; lato--; } while (_rows * _cols < 32); TDate dend = _date; dend.set_end_month(); CBRUSH cbrush = { PAT_HOLLOW, 0 }; set_font(xvt_rect_get_height(&rct)/(2*_rows)); TString16 text; const int cells = _rows * _cols; TString80 busy; query(busy); for (int i = 0; i < cells; i++) { RCT r; cell2rct(i, r); if (busy[i] > ' ' && i < dend.day()) { cbrush.pat = PAT_SOLID; cbrush.color = FOCUS_BACK_COLOR; } else { cbrush.pat = PAT_HOLLOW; cbrush.color = NORMAL_BACK_COLOR; } xvt_dwin_set_cbrush(dc, &cbrush); xvt_dwin_draw_rect(dc, &r); if (i < dend.day()) { set_color(NORMAL_COLOR, cbrush.color); text.format("%d", i+1); advanced_draw_text_line(dc, text, r, 'C', 'B'); } } for (int i = 0; i < dend.day(); i++) { const TDate d(i+1, dend.month(), dend.year()); RCT rc; cell2rct(i, rc); const int h = xvt_rect_get_height(&rc); rc.bottom = rc.top + h/3; xvt_rect_deflate(&rc, 2, 2); if (i == 0) set_font(h/6); cbrush.pat = PAT_SOLID; cbrush.color = day2color(d); xvt_dwin_set_cbrush(dc, &cbrush); const int r = h/16; xvt_dwin_draw_roundrect(dc, &rc, r, r); set_color(NORMAL_BACK_COLOR, cbrush.color); text = itow(d.wday()); text.cut(3); rc.top--; // Better text position advanced_draw_text_line(dc, text, rc, 'C', 'T'); } if (cells > 31) { RCT rc; cell2rct(cells-1, rc); cbrush.pat = PAT_SOLID; cbrush.color = REQUIRED_BACK_COLOR; xvt_dwin_set_cbrush(dc, &cbrush); xvt_dwin_draw_rect(dc, &rc); set_font(xvt_rect_get_height(&rc)/4); set_color(NORMAL_COLOR, cbrush.color); text = itom(_date.month()); text.cut(3); advanced_draw_text_line(dc, text, rc, 'C', 'T'); text.format("%d", _date.year()); advanced_draw_text_line(dc, text, rc, 'C', 'B'); } } long TConsuntivazione_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_MOUSE_DOWN: { RCT rct; xvt_vobj_get_client_rect(win, &rct); const int cx = ep->v.mouse.where.h * _cols / rct.right; const int cy = ep->v.mouse.where.v * _rows / rct.bottom; const int day = cy * _cols + cx; TDate d = _date; d.set_end_month(); if (day >= 0 && day < d.day()) { TMask& m = owner().mask(); d.set_day(day+1); m.set(F_GIORNO, d.string(), 0x3); m.send_key(K_CTRL+'+', F_SHEET, &owner()); } } break; default: break; } return TField_window::handler(win, ep); } TConsuntivazione_window::TConsuntivazione_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : TField_window( x, y, dx, dy, parent, NULL), _date(TODAY) { create(x, y, dx, dy, "", 0, W_PLAIN, parent); set_owner(owner); } class TConsuntivazione_field : public TWindowed_field { protected: TField_window* TConsuntivazione_field::create_window(int x, int y, int dx, int dy, WINDOW parent); public: virtual void set(const char* s); TConsuntivazione_field(TMask* m); }; TField_window* TConsuntivazione_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TConsuntivazione_window(x, y, dx, dy, parent, this); } void TConsuntivazione_field::set(const char* s) { TDate d(TODAY); if (TDate::isdate(s)) { d = TDate(s); } else { if (real::is_natural(s)) { const int y = atoi(s); if (y >= 2000 && y < 10000) d.set_year(y); } } if (d.ok()) { TConsuntivazione_window& cw = (TConsuntivazione_window&)win(); cw.set_date(d); } } TConsuntivazione_field::TConsuntivazione_field(TMask* m) : TWindowed_field(m) { } /////////////////////////////////////////////////////////// // TConsuntivazione_msk /////////////////////////////////////////////////////////// class TConsuntivazione_msk : public TAutomask { short _cdc_sid, _cdc_lid, _cms_sid, _cms_lid, _fase_sid, _fase_lid; short _scdc_sid, _scdc_lid, _scms_sid, _scms_lid, _sfase_sid, _sfase_lid; bool _sheet_dirty, _recontabilize, _locked; protected: virtual TMask_field* parse_field(TScanner& scanner); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); protected: bool cerca_disponibilita(int riga) const; real proponi_costo(TMask& msk) const; void riempi_nuova_riga(int r); bool add_ril_to_doc(TRectype& rilore, TDocumento& doc, TLog_report& log) const; bool add_ril_to_mov(TRectype& rilore, TAnal_mov& mov, TLog_report& log) const; void get_anal_fields(TString & cdc, TString & cms, TString & fase) const; void get_row_anal_fields(TToken_string & row, TString & cdc, TString & cms, TString & fase) const; void put_row_anal_fields(TToken_string & row, const TString & cdc, const TString & cms, const TString & fase); long save_docs(TAssoc_array& docs, TAssoc_array& movs, TLog_report& log) const; const TString& good_umart(const TString& codart, const TString& um) const; public: bool save_sheet(); bool save_dirty_sheet(); bool load_sheet(); bool contabilizza(); TConsuntivazione_msk(); }; TMask_field* TConsuntivazione_msk::parse_field(TScanner& scanner) { if (scanner.key() == "CA") { set_full_screen_interface(page_win(0), true); return new TConsuntivazione_field(this); } return TAutomask::parse_field(scanner); } void TConsuntivazione_msk::get_anal_fields(TString & cdc, TString & cms, TString & fase) const { TString val; cdc.cut(0); if (_cdc_sid >= 0) for ( short id = _cdc_sid; id <= _cdc_lid; id++) { val = get(id); val.rpad(field(id).size()); cdc << val; } cdc.trim(); cms.cut(0); if (_cms_sid >= 0) for ( short id = _cms_sid; id <= _cms_lid; id++) { val = get(id); val.rpad(field(id).size()); cms << val; } cms.trim(); fase.cut(0); if (_fase_sid >= 0) for ( short id = _fase_sid; id <= _fase_lid; id++) { val = get(id); val.rpad(field(id).size()); fase << val; } fase.trim(); } void TConsuntivazione_msk::get_row_anal_fields(TToken_string & row, TString & cdc, TString & cms, TString & fase) const { TSheet_field & s = sfield(F_SHEET); TMask & m = s.sheet_mask(); TString val; cdc.cut(0); if (_scdc_sid >= 0) for ( short id = _scdc_sid; id <= _scdc_lid; id++) { val = row.get(s.cid2index(id)); val.rpad(m.field(id).size()); cdc << val; } cdc.trim(); cms.cut(0); if (_scms_sid >= 0) for ( short id = _scms_sid; id <= _scms_lid; id++) { val = row.get(s.cid2index(id)); val.rpad(m.field(id).size()); cms << val; } cms.trim(); fase.cut(0); if (_sfase_sid >= 0) for ( short id = _sfase_sid; id <= _sfase_lid; id++) { val = row.get(s.cid2index(id)); val.rpad(m.field(id).size()); fase << val; } fase.trim(); } void TConsuntivazione_msk::put_row_anal_fields(TToken_string & row, const TString & cdc, const TString & cms, const TString & fase) { TSheet_field & s = sfield(F_SHEET); TMask & m = s.sheet_mask(); int pos = 0; if (_scdc_sid >= 0) for (short id = _scdc_sid; id <= _scdc_lid; id++) { const int len = m.field(id).size(); row.add(cdc.mid(pos, len), s.cid2index(id)); pos += len; } pos = 0; if (_scms_sid >= 0) for (short id = _scms_sid; id <= _scms_lid; id++) { const int len = m.field(id).size(); row.add(cms.mid(pos, len), s.cid2index(id)); pos += len; } pos = 0; if (_sfase_sid >= 0) for (short id = _sfase_sid; id <= _sfase_lid; id++) { const int len = m.field(id).size(); row.add(fase.mid(pos, len), s.cid2index(id)); pos += len; } } bool TConsuntivazione_msk::save_sheet() { TFast_isamfile rilore(LF_RILORE); long lastid = 0; { TISAM_recordset def("USE RILORE\nFROM TIPO=C\nTO TIPO=C"); if (def.move_last()) lastid = def.get("ID").as_int(); } TSheet_field& sheet = sfield(F_SHEET); const int posid = sheet.cid2index(S_ID); TRectype& rec = rilore.curr(); FOR_EACH_SHEET_ROW(sheet, r, row) { long id = row->get_long(posid); const bool is_new = id <= 0; if (is_new) { id = ++lastid; row->add(id, posid); } rec.zero(); rec.put("TIPO", "C"); rec.put("ID", id); if (!is_new) rilore.read(); sheet.autosave_line(r+1, rec); rec.put(RILORE_ADATA, rec.get(RILORE_DADATA)); // copia datata in adata if (id == lastid) rilore.write_rewrite(); else rilore.rewrite_write(); } enable(DLG_SAVEREC, _sheet_dirty = false); TConsuntivazione_field& f = (TConsuntivazione_field&)field(F_CALENDAR); f.win().force_update(); return !sheet.empty(); } bool TConsuntivazione_msk::save_dirty_sheet() { bool done = !_sheet_dirty; if (_sheet_dirty && yesno_box(TR("Salvare le righe modificate?"))) done = save_sheet(); return done; } bool TConsuntivazione_msk::load_sheet() { save_dirty_sheet(); TString select; if (get_bool(C_RISOATT)) { const TString& risoatt = get(F_RISOATT); select << "&&(TIPORA==\"" << risoatt << "\")"; if (get_bool(C_CODICE)) { const TString& codice = get(risoatt == "A" ? F_CODATT : F_CODRIS); if (codice.full()) select << "&&(CODICE==\"" << codice << "\")"; } } if (get_bool(C_TPORA)) { const TString& tpora = get(F_TPORA); if (tpora.full()) select << "&&(TPORA==\"" << tpora << "\")"; } TString codcosto, codcms, codfase; get_anal_fields(codcosto, codcms, codfase); if (codcosto.full()) select << "&&(CODCOSTO==\"" << codcosto << "\")"; if (codcms.full()) select << "&&(CODCMS==\"" << codcms << "\")"; if (codfase.full()) select << "&&(CODFASE==\"" << codfase << "\")"; TString query; query << "USE RILORE KEY 2"; if (select.full()) query << "\nSELECT " << select.mid(2) << "\n"; const TDate oggi(TODAY); int y = get_int(F_ANNO); if (y < 2000) y = oggi.year(); TDate da_data(1,1,y), a_data(31,12,y); const TDate d = get(F_GIORNO); if (d.ok() && get_bool(C_GIORNO)) da_data = a_data = d; else if (get_bool(C_MESE)) { const int m = get_int(F_MESE); da_data.set_month(m); a_data.set_month(m); a_data.set_end_month(); } query << "\nFROM TIPO=C DADATA=" << da_data.string() << "\nTO TIPO=C DADATA=" << a_data.string(); TISAM_recordset def(query); const TRectype& rec = def.cursor()->curr(); TDate last_date = da_data; TSheet_field& sheet = sfield(F_SHEET); sheet.destroy(); _locked = true; TProgress_monitor mon(def.items(), TR("Caricamento ore..."), true); int r = 0; for (bool ok = def.move_first(); ok; ok = def.move_next()) { sheet.autoload_line(++r, rec); if (!mon.add_status()) break; if (rec.get_long(RILORE_NDOC) > 0) { TToken_string& row = sheet.row(r-1); row.add(5, sheet.cid2index(S_STATO)); } last_date = rec.get(RILORE_DADATA); if (r >= 9999) break; } sheet.force_update(); set(F_CALENDAR, last_date.string()); enable(DLG_SAVEREC, _sheet_dirty = false); _locked = false; return !sheet.empty(); } real TConsuntivazione_msk::proponi_costo(TMask& msk) const { const TString& codlist = msk.get(S_CODLIST); if (codlist.empty()) { TString80 cdc, cms, fase; get_anal_fields(cdc, cms, fase); if (cms.full()) { const TString& lis = cache().get(LF_COMMESSE, cms, COMMESSE_LISRILCN); msk.set(S_CODLIST, lis); } } const char tipo = msk.get(S_RISOATT)[0]; const TString& codice = msk.get(tipo=='A' ? S_CODATT : S_CODRIS); const TString& tpora = msk.get(S_TPORA); real costo; if (codlist.full() && codice.full() && tpora.full()) { const TDate dal = msk.get(S_DATA); TString80 filtro = codlist; filtro.left_just(4); filtro << tipo << codice; TString query; query << "USE &ROA SELECT CODTAB[22,29]<=\"" << dal.date2ansi() << '"' << "\nFROM CODTAB=" << filtro << "\nTO CODTAB=" << filtro; TISAM_recordset roa(query); for (bool ok = roa.move_last(); ok; ok = roa.move_prev()) { const TString& codtab = roa.get("CODTAB").as_string(); const TDate data = codtab.mid(21, 8); const TString& to = codtab.mid(29); if (to == tpora && data <= dal) { costo = roa.get("R1").as_real(); if (!costo.is_zero()) break; } } } const TRectype& roa = cache().get(tipo == 'A' ? "ATR" : "RSS", codice); if (costo.is_zero()) { const char* fld_price = "R10"; // Costo standard risorsa o attrezzatura if (tipo =='A' && tpora == roa.get("S9") && !roa.get_real("R11").is_zero()) fld_price = "R11"; // costo disponibilità attrezzatura costo = roa.get_real(fld_price); } if (costo > ZERO && costo < 10000) { msk.set(S_COSTO, costo); msk.set(S_CODIVA, roa.get("S3").left(4)); } return costo; } void TConsuntivazione_msk::riempi_nuova_riga(int r) { TSheet_field& sheet = sfield(F_SHEET); TToken_string& riga = sheet.row(r); //guardo il tipo risorsa / attrezzatura che sto ricercando const TString& tipo = get(F_RISOATT); riga.add(get(F_GIORNO), sheet.cid2index(S_DATA)); riga.add(tipo, sheet.cid2index(S_RISOATT)); riga.add(get(tipo=="R" ? F_CODRIS : F_CODATT), sheet.cid2index(S_CODRIS)); riga.add(get(F_TPORA), sheet.cid2index(S_TPORA)); TString codcosto, codcms, codfase; get_anal_fields(codcosto, codcms, codfase); put_row_anal_fields(riga, codcosto, codcms, codfase); sheet.update_mask(r); TMask& msk = sheet.sheet_row_mask(r); proponi_costo(msk); sheet.check_row(r); sheet.force_update(r); } const TString& TConsuntivazione_msk::good_umart(const TString& codart, const TString& um) const { // Reperisce unità di misura standard per codart TString80 key; key << codart << "|1"; const TString& defum = cache().get(LF_UMART, key, UMART_UM); // Controlla unità di misura fuori standard if (um.full() && um != defum) { TLocalisamfile umart(LF_UMART); umart.setkey(2); umart.put(UMART_CODART, codart); umart.put(UMART_UM, um); if (umart.read() == NOERR) return um; } return defum; } bool TConsuntivazione_msk::add_ril_to_doc(TRectype& rilore, TDocumento& doc, TLog_report& log) const { const char tipo_roa = rilore.get_char(RILORE_TIPORA); // 'R'isorsa o 'A'ttrezzatura const TString& codice_roa = rilore.get(RILORE_CODICE); const TRectype& roa = cache().get(tipo_roa == 'A' ? "ATR" : "RSS", codice_roa); const TString& tipo_ora = rilore.get(RILORE_TPORA); const bool disponibilita = tipo_ora == roa.get("S9"); TString80 codart = roa.get("S2"); if (disponibilita) codart.ltrim(20); else codart.cut(20); codart.trim(); if (codart.blank()) { TString msg; msg << (tipo_roa == 'R' ? TR("Impossibile associare un articolo alla risorsa ") : TR("Impossibile associare un articolo all'attrezzatura ")); msg << codice_roa; log.log(2, msg); return false; } const real ore = rilore.get(RILORE_QTAORE); const real prezzo = rilore.get(RILORE_COSTO); const TString80 cms = rilore.get(RILORE_CODCMS); const TString16 fas = rilore.get(RILORE_CODFASE); int found = 0; if (!ore.is_zero() && !prezzo.is_zero()) { FOR_EACH_PHYSICAL_RDOC(doc, r, rdoc) { if (rdoc->get(RDOC_CODARTMAG) == codart && rdoc->get_real(RDOC_PREZZO) == prezzo && rdoc->get(RDOC_CODCMS) == cms && rdoc->get(RDOC_FASCMS) == fas) { found = r; break; } } if (!found) { const TRectype& anamag = cache().get(LF_ANAMAG, codart); TRiga_documento& riga = doc.new_row("01"); riga.put(RDOC_CODART, codart); riga.put(RDOC_CODARTMAG, codart); riga.put(RDOC_CODCMS, cms); riga.put(RDOC_FASCMS, fas); riga.put(RDOC_CHECKED, "X"); riga.put(RDOC_DESCR, anamag.get(ANAMAG_DESCR)); riga.put(RDOC_PREZZO, prezzo); riga.put(RDOC_DATACONS, doc.get(DOC_DATADOC)); TString4 codiva = roa.get("S3").left(4); if (codiva.blank()) codiva = anamag.get(ANAMAG_CODIVA); riga.put(RDOC_CODIVA, codiva); // Controllo unità di misura TString4 um = roa.get("S7"); if (disponibilita) um = good_umart(codart, EMPTY_STRING); else um = good_umart(codart, um); riga.put(RDOC_UMQTA, um); found = riga.get_int(RDOC_NRIGA); } TRiga_documento& riga = doc[found]; riga.add(RDOC_QTA, ore); rilore.put(RILORE_PROVV, riga.get(RDOC_PROVV)); rilore.put(RILORE_ANNOD, riga.get(RDOC_ANNO)); rilore.put(RILORE_CODNUM, riga.get(RDOC_CODNUM)); rilore.put(RILORE_NDOC, riga.get(RDOC_NDOC)); rilore.put(RILORE_IDRIGA, found); // IDRIGA is null right now! } return found > 0; } bool TConsuntivazione_msk::add_ril_to_mov(TRectype& rilore, TAnal_mov& mov, TLog_report& log) const { const char tipo_roa = rilore.get_char(RILORE_TIPORA); const TString& codice_roa = rilore.get(RILORE_CODICE); const TRectype& roa = cache().get(tipo_roa == 'A' ? "ATR" : "RSS", codice_roa); const TString80 conto = roa.get("S1"); if (conto.blank()) { TString msg; msg << TR("Impossibile associare un conto analitico a ") << codice_roa; log.log(2, msg); return false; } const real ore = rilore.get(RILORE_QTAORE); const real prezzo = rilore.get(RILORE_COSTO); const TString80 cms = rilore.get(RILORE_CODCMS); const TString16 fas = rilore.get(RILORE_CODFASE); bool done = !ore.is_zero() && !prezzo.is_zero(); if (done) { // Cerca eventuale riga compatibile int i = 0; for (i = mov.rows(); i > 0; i--) { const TRectype& row = mov.body()[i]; if (row.get(RMOVANA_CODCONTO) == conto && row.get(RMOVANA_CODCMS) == cms && row.get(RMOVANA_CODFASE) == fas) break; } // Crea nuova riga se necessario if (i <= 0) { TRectype& row = mov.new_row(); row.put(RMOVANA_CODCONTO, conto); row.put(RMOVANA_CODCMS, cms); row.put(RMOVANA_CODFASE, fas); i = row.get_int(RMOVANA_NUMRIG); } // Incrementa importo TRectype& row = mov.body()[i]; row.put(RMOVANA_SEZIONE, 'D'); row.add(RMOVANA_IMPORTO, ore*prezzo); } return done; } static void doc2msg(const TRectype& doc, TString& msg) { msg.cut(0) << doc.get(DOC_CODNUM) << ' ' << doc.get(DOC_ANNO) << '/' << doc.get(DOC_NDOC) << TR(" del ") << doc.get(DOC_DATADOC); } long TConsuntivazione_msk::save_docs(TAssoc_array& docs, TAssoc_array& movs, TLog_report& log) const { long ndocs = 0; log.log(0, ""); TString msg = TR("Aggiornamento contabilità industriale"); if (!movs.empty()) msg << TR(" ed analitica"); log.log(0, msg); TProgind pi(docs.items() + movs.items(), msg); FOR_EACH_ASSOC_OBJECT(docs, h, k, o) { if (!pi.addstatus(1)) break; TDocumento* doc = (TDocumento*)o; doc2msg(*doc, msg); int err = NOERR; if (doc->rows() > 0) { ndocs++; err = doc->write(); } else { err = doc->remove(); } if (err != NOERR) { msg << TR(" Errore di scrittura ") << err; log.log(2, msg); } else log.log(0, msg); } if (!movs.empty()) { TFast_isamfile movana(LF_MOVANA); FOR_EACH_ASSOC_OBJECT(movs, h, k, o) { if (!pi.addstatus(1)) break; TAnal_mov* mov = (TAnal_mov*)o; msg.cut(0) << TR("Movimento analitico ") << mov->get(MOVANA_NUMREG); int err = NOERR; if (mov->rows() > 0) err = mov->write(movana); else err = mov->remove(movana); if (err != NOERR) { msg << TR(" Errore di scrittura ") << err; log.log(2, msg); } else log.log(0, msg); } } return ndocs; } bool TConsuntivazione_msk::contabilizza() { if (!save_dirty_sheet()) return false; const int anno = get_int(F_ANNO); if (anno < 2010) return field(F_ANNO).on_hit(); const TString4 numcn = ini_get_string(CONFIG_DITTA, "ci", "CODNUMCN"); const TString4 tipocn = ini_get_string(CONFIG_DITTA, "ci", "TIPODOCCN"); if (numcn.blank() || tipocn.blank()) return error_box(TR("Non sono stati impostati numerazione e/o tipo documento per consuntivazione ore")); // Calcolo il range di date delle ore da consuntivare TDate dal, al; bool daily = false; const char dett = ini_get_string(CONFIG_DITTA, "ci", "DETTCONS")[0]; switch (dett) { case 'A': dal = TDate( 1, 1, anno); al = TDate(31,12, anno); break; case 'M': dal = TDate( 1, get_int(F_MESE), anno); al = dal; al.set_end_month(); break; default: dal = al = get_date(F_GIORNO); daily = true; break; } TMask m(TR("Parametri contabilizzazione"), 1, 28, 7); m.add_button_tool(DLG_OK, "", TOOL_OK); m.add_button_tool(DLG_CANCEL, "", TOOL_CANCEL); m.add_button_tool(DLG_INFO, "", TOOL_INFO); m.add_date(101, 0, PR("Dal giorno "), 1, 1, daily ? "" : "D").check_type(CHECK_REQUIRED); m.add_date(102, 0, PR("Al giorno "), 1, 2, daily ? "" : "D").check_type(CHECK_REQUIRED); m.add_boolean(103, 0, TR("Generazione analitica"), 1, 3, "D"); m.set(101, dal); m.set(102, al); if (ca_config().get_int("Authorizations") > 1) { m.enable(103); m.set(103, "X"); } if (m.run() != K_ENTER) return false; const bool do_anal = m.get_bool(103); const TString4 causcn = ini_get_string(CONFIG_DITTA, "ci", "CODCAUSCN"); if (do_anal && causcn.blank()) return error_box(TR("Impostare la causale contabile per i consuntivi in configurazione")); if (daily) { dal = m.get(101); al = m.get(102); if (al.year() > dal.year()) al = TDate(31, 12, dal.year()); } TString msg; msg << TR("Si desidera contabilizzare il periodo dal ") << dal << TR(" al ") << al << " ?"; if (!yesno_box(msg)) return false; TLog_report log; msg = TR("Caricamento contabilità industriale"); log.log(0, msg); TAssoc_array docs, movs; if (numcn.full() && al >= dal) // dummy bracketing test { TString query; query << "USE DOC SELECT BETWEEN(DATADOC," << dal.date2ansi() << ',' << al.date2ansi() << ')' << "\nFROM PROVV=D ANNO=" << dal.year() << " CODNUM=" << numcn << " NDOC=" << date2ndoc(dal) << "\nTO PROVV=D ANNO=" << al.year() << " CODNUM=" << numcn << " NDOC=" << date2ndoc(al); TISAM_recordset docset(query); TProgind pi(docset.items(), msg); for (bool ok = docset.move_first(); ok; ok = docset.move_next()) { if (!pi.addstatus(1)) break; TDocumento* doc = new TDocumento(docset.cursor()->curr()); const TDoc_key key(doc->get_int(DOC_ANNO), numcn, doc->get_long(DOC_NDOC)); doc->destroy_rows(); docs.add(key, doc); doc2msg(*doc, msg); const long numreg = doc->get_long(DOC_NUMREGCA); if (do_anal && numreg > 0) { TAnal_mov* m = new TAnal_mov(numreg); if (m->rows() > 0) { m->destroy_rows(); movs.add(key, m); msg << TR(" + analitica ") << numreg; } else delete m; } log.log(0, msg); } } if (numcn.full() && al >= dal) // dummy bracketing test { log.log(0, ""); msg = TR("Caricamento ore consuntivate"); log.log(0, msg); TFast_isamfile file_ore(LF_RILORE); TFast_isamfile file_ana(LF_MOVANA); long last_numregca = 0; if (do_anal && file_ana.last() == NOERR) last_numregca = file_ana.get_long(MOVANA_NUMREG); TString query; query << "USE RILORE KEY 2" << "\nFROM TIPO=C DADATA=" << dal << "\nTO TIPO=C DADATA=" << al; TISAM_recordset recset(query); TProgress_monitor pi(recset.items(), msg); TRectype& rilore = recset.cursor()->curr(); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { TDate d = rilore.get("DADATA"); switch (dett) { case 'A': d.set_month(12); d.set_day(31); break; case 'M': d.set_end_month(); break; default: break; } const TDoc_key key(d.year(), numcn, date2ndoc(d)); TDocumento* doc = (TDocumento*)docs.objptr(key); if (doc == NULL) { doc = new TDocumento('D', key.anno(), key.codnum(), key.ndoc()); doc->put(DOC_TIPODOC, tipocn); doc->put(DOC_DATADOC, d); doc->put(DOC_STATO, 1); docs.add(key, doc); doc2msg(*doc, msg); msg.insert(TR("Creazione ")); log.log(0, msg); } if (add_ril_to_doc(rilore, *doc, log)) { rilore.rewrite(file_ore); if (do_anal) { TAnal_mov* mov = (TAnal_mov*)movs.objptr(key); if (mov == NULL) { mov = new TAnal_mov(++last_numregca); movs.add(key, mov); doc->put(DOC_NUMREGCA, last_numregca); } if (mov->rows() == 0) { mov->put(MOVANA_DATAREG, TDate(TODAY)); if (daily) { mov->put(MOVANA_DATACOMP, doc->get(DOC_DATADOC)); mov->head().zero(MOVANA_DATAFCOMP); } else { mov->put(MOVANA_DATACOMP, dal); mov->put(MOVANA_DATAFCOMP, al); } mov->put(MOVANA_DATADOC, doc->get(DOC_DATADOC)); mov->put(MOVANA_ANNOES, doc->get(DOC_ANNO)); mov->put(MOVANA_NUMDOC, doc->get(DOC_NDOC)); mov->put(MOVANA_CODCAUS, causcn); mov->put(MOVANA_TIPODOC, cache().get(LF_CAUSALI, causcn, CAU_TIPODOC)); mov->put(MOVANA_DPROVV, doc->get(DOC_PROVV)); mov->put(MOVANA_DANNO, doc->get(DOC_ANNO)); mov->put(MOVANA_DCODNUM, doc->get(DOC_CODNUM)); mov->put(MOVANA_DNDOC, doc->get(DOC_NDOC)); msg = TR("Consuntivazione ore "); if (daily) msg << TR("del ") << rilore.get(RILORE_DADATA); else msg << TR("dal ") << dal << TR(" al ") << al; mov->put(MOVANA_DESCR, msg); msg.cut(0) << TR("Creazione movimento analitico ") << last_numregca; log.log(0, msg); } add_ril_to_mov(rilore, *mov, log); } } } } const long ndocs = save_docs(docs, movs, log); log.log(0, ""); if (ndocs > 0) { msg.format(FR("Sono stati generati %ld documenti"), ndocs); log.log(0, msg); } else log.log(1, TR("Nono sono stati generati documenti")); log.preview(); _recontabilize = false; return true; } bool TConsuntivazione_msk::cerca_disponibilita(int riga) const { TSheet_field& s = sfield(F_SHEET); const int col_att = s.cid2index(S_CODATT); const int col_ora = s.cid2index(S_TPORA); const int col_cms = s.cid2index(S_CDC1); const TToken_string& r = s.row(riga); TString80 cod_att; r.get(col_att, cod_att); cod_att.trim(); TString4 tipo_ora; r.get(col_ora, tipo_ora); tipo_ora.trim(); TString80 cod_cms; r.get(col_cms, cod_cms); cod_cms.trim(); for (int i = riga-1; i <= riga+1; i+=2) { if (i >= 0 && i < s.items()) { const TToken_string& ri = s.row(i); TString80 ca; ri.get(col_att, ca); ca.trim(); TString4 to; ri.get(col_ora, to); to.trim(); TString80 cc; ri.get(col_cms, cc); cc.trim(); if (ca == cod_att && cc == cod_cms && to != tipo_ora) return true; } } return false; } bool TConsuntivazione_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_FINDREC: if (e == fe_button) load_sheet(); break; case DLG_SAVEREC: if (e == fe_button) { save_sheet(); // Salva le righe modificate load_sheet(); // Carica le righe ordinate per data } break; case DLG_ELABORA: if (e == fe_button && save_dirty_sheet()) { if (contabilizza()) load_sheet(); } break; case DLG_QUIT: if (e == fe_button && !check_fields()) return false; break; case F_ANNO: if (e == fe_modify && !o.empty()) { int y = atoi(o.get()); if (y < 2000) { y = TDate(TODAY).year(); o.set(y); } TDate d = get(F_GIORNO); if (!d.ok()) d = TODAY; if (y % 4 && d.month() == 2 && d.day() > 28) --d; d.set_year(y); set(F_GIORNO, d, 0x3); load_sheet(); } break; case F_MESE: if (e == fe_modify) { const int m = atoi(o.get()); int y = get_int(F_ANNO); if (y < 2000) { y = TDate(TODAY).year(); set(F_ANNO, y); } const TDate d(1, m, y); set(F_GIORNO, d, 0x3); if (get_bool(C_MESE)) load_sheet(); } break; case F_GIORNO: if (e == fe_modify && !o.empty()) { if (get_bool(C_GIORNO)) load_sheet(); set(F_CALENDAR, o.get()); } break; case C_MESE: case C_GIORNO: case C_TPORA: case F_RISOATT: if (e == fe_modify) load_sheet(); break; case F_SHEET: switch (e) { case fe_close: save_dirty_sheet(); if (_recontabilize && yesno_box(TR("Avendo modificato ore già contabilizzate,\nsi desidera ricontabilizzarle ora?"))) contabilizza(); break; case se_query_del: { TSheet_field& sheet = (TSheet_field&)o; TToken_string& row = sheet.row(jolly); const int posid = sheet.cid2index(S_ID); const long id = row.get_long(posid); if (id > 0) { TLocalisamfile rilore(LF_RILORE); rilore.put("TIPO", "C"); rilore.put("ID", id); if (rilore.remove() != NOERR) return error_box(FR("Impossibile eliminare la riga %d"), jolly); else set(F_CALENDAR, get(F_GIORNO)); } } break; case se_enter: { TSheet_field& sheet = (TSheet_field&)o; TToken_string& row = sheet.row(jolly); const TDate d = row.get(0); if (d.ok()) set(F_CALENDAR, d.string()); } break; case se_notify_modify: enable(DLG_SAVEREC, _sheet_dirty = true); if (_sheet_dirty) { TSheet_field& sheet = (TSheet_field&)o; const char stato = sheet.cell(jolly, S_STATO)[0]; if (stato > '1') _recontabilize = _sheet_dirty; TToken_string& row = sheet.row(jolly); const char tipo = row.get_char(1); const TString80 cod = row.get(2); const TString4 ora = row.get(4); if (tipo == 'A' && cod.full() && ora.full()) { const TRectype& atr = cache().get("ATR", cod); const TString& codartdisp = atr.get("S2").mid(20); // Previsto articolo per disponibilità? const TString4 orad = atr.get("S9"); // Previsto tipo ora per disponibilità? if (codartdisp.full() && orad.full() && ora != orad) // Attrezzatura con ora normale { if (!cerca_disponibilita(jolly)) { const int nr = sheet.insert(jolly+1); TToken_string& rowd = sheet.row(nr); rowd = row; rowd.add(orad, 4); if (atr.get_int("I13") != 2) // Se non è un'attrezzatura forza le ore a 1 rowd.add(1, 5); // altrimenti lascia la stessa quantità della riga collegata rowd.add(atr.get("R11"), 6); sheet.force_update(nr); } } } } break; case se_notify_add: riempi_nuova_riga(jolly); break; default : break; } break; case S_DATA: if (e == fe_modify && !o.empty() && is_running()) set(F_CALENDAR, o.get()); else break; // intentionally fall down case S_CODRIS: case S_CODATT: case S_TPORA: if (e == fe_modify && !o.empty() && !_locked) proponi_costo(o.mask()); break; default: break; } if ((e == fe_modify || e == fe_init) && o.dlg() == _scms_lid) { const TRectype& curr = ((TEdit_field&)o).browse()->cursor()->curr(); const TString codcms = curr.get(COMMESSE_CODCMS); TMask& m = o.mask(); m.set(S_CMSH, codcms); const TRectype& commesse = cache().get(LF_COMMESSE, codcms); m.set(S_CODLIST, commesse.get(COMMESSE_LISRILCN), 0x3); if (e == fe_modify) { if (codcms.full()) { TDate inizio, fine; ca_durata_commessa(commesse, inizio, fine); const TDate data = m.get(S_DATA); if (data < inizio) return error_box(FR("Commessa %s non iniziata"), (const char *) codcms); if (data > fine) return error_box(FR("Commessa %s terminata"), (const char *) codcms); } if (main_app().has_module(CTAUT)) { TToken_string key; key.add(codcms); key.add("C"); key.add(1); const TRectype & cfcms = cache().get(LF_CFCMS, key); m.set(S_CUP, cfcms.get(CFCMS_CUP), 3); m.set(S_CIG, cfcms.get(CFCMS_CIG), 3); } } } return true; } TConsuntivazione_msk::TConsuntivazione_msk() : _locked(false) { read_mask("ci2400a", 0, 1); const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); TConfig& ini = ca_config(); TSheet_field & s = sfield(F_SHEET); TMask & sm = s.sheet_mask(); int y = 3; int sy = 4; short dlg = F_ANAL; // id del primo codice da generare in testata short sdlg = S_CDC1 + 100; // id del primo codice da generare nello sheet _cdc_sid = _cdc_lid = _cms_sid = _cms_lid = _fase_sid = _fase_lid = -1; _scdc_sid = _scdc_lid = _scms_sid = _scms_lid = _sfase_sid = _sfase_lid = -1; for (int i = 0; i < 2; i++) { const TString& level = ini.get("Level", NULL, i+1); // Legge il livello 1 o 2 if (level == "CDC") // Crea centro di costo { if (fasinfo.parent() == LF_CDC) { int h = ca_multilevel_code_info(LF_CDC).levels(); const int h1 = ca_create_fields_compact(*this, 0, LF_FASI, 2, y, dlg, dlg + 100); y += 2; _cdc_sid = dlg; _cdc_lid = dlg + h - 1; _fase_sid = _cdc_lid + 1; _fase_lid = dlg + h1 - 1; dlg += h1; const int sh = ca_create_fields_compact(sm, 0, LF_FASI, 1, sy, sdlg, sdlg + 50); sy += 2; _scdc_sid = sdlg; _scdc_lid = sdlg + h - 1; _sfase_sid = _scdc_lid + 1; _sfase_lid = sdlg + sh - 1; sdlg += sh; } else { const int h = ca_create_fields_compact(*this, 0, LF_CDC, 2, y++, dlg, dlg + 100); _cdc_sid = dlg; _cdc_lid = dlg + h - 1; dlg += h; const int sh = ca_create_fields_compact(sm, 0, LF_CDC, 1, sy++, sdlg, sdlg + 50); _scdc_sid = sdlg; _scdc_lid = sdlg + sh - 1; sdlg += h; } } else if (level == "CMS") // Crea commessa { if (fasinfo.parent() == LF_COMMESSE) { // Commessa in testata per filtro / proposta int h = ca_multilevel_code_info(LF_COMMESSE).levels(); const int h1 = ca_create_fields_compact(*this, 0, LF_FASI, 2, y, dlg, dlg + 100); y += 2; _cms_sid = dlg; _cms_lid = dlg + h - 1; _fase_sid = _cms_lid + 1; _fase_lid = dlg + h1 - 1; dlg += h1; // Commessa nelle righe const int sh = ca_create_fields_compact(sm, 0, LF_FASI, 1, sy, sdlg, sdlg + 50); sy += 2; _scms_sid = sdlg; _scms_lid = sdlg + h - 1; _sfase_sid = _scms_lid + 1; _sfase_lid = sdlg + sh - 1; sdlg += sh; } else { const int h = ca_create_fields_compact(*this, 0, LF_COMMESSE, 2, y++, dlg, dlg + 100); _cms_sid = dlg; _cms_lid = dlg + h - 1; dlg += h; const int sh = ca_create_fields_compact(sm, 0, LF_COMMESSE, 1, sy++, sdlg, sdlg + 50); _scms_sid = sdlg; _scms_lid = sdlg + sh - 1; sdlg += sh; } } } if (fasinfo.levels() > 0 && fasinfo.parent() <= 0) { const int h = ca_create_fields_compact(*this, 0, LF_FASI, 2, y++, dlg, dlg + 100); _fase_sid = dlg; _fase_lid = dlg + h - 1; dlg += h; const int sh = ca_create_fields_compact(sm, 0, LF_FASI, 1, sy++, sdlg, sdlg + 50); _sfase_sid = sdlg; _sfase_lid = sdlg + sh - 1; sdlg += h; } // Sistema nome del campo CODCMS for (short id = _scms_lid; id >= _scms_sid; id--) { TEdit_field& ef = sm.efield(id); TFieldref* fr = (TFieldref*)ef.field(); if (fr != NULL) fr->set_name(RILORE_CODCMS); } for (short id = S_CDC12 + 100; id >= S_CDC1 + 100; id--) { const int pos = sm.id2pos(id); if (pos >= 0) { TMask_field& f = sm.fld(pos); const int size = f.size(); TString80 prompt = f.prompt(); prompt.trim(); if (prompt.blank()) { TToken_string ts(((TEditable_field &)f).get_warning(), ' '); prompt = ts.get(0); } s.set_column_header(id, prompt); s.set_column_justify(id, f.is_kind_of(CLASS_REAL_FIELD)); s.set_column_width(id, (max(3+size, prompt.len()+1)) * CHARX); s.update_column_width(id); s.enable_column(id); } else s.delete_column(id); } set_handlers(); // Fondamentale dopo una read_mask e la generazione dinamica di campi enable(DLG_SAVEREC, _sheet_dirty = false); _recontabilize = false; set(C_MESE, "X"); load_sheet(); } /////////////////////////////////////////////////////////// // TConsuntivazione_app /////////////////////////////////////////////////////////// class TConsuntivazione_app : public TSkeleton_application { public: virtual void main_loop(); }; void TConsuntivazione_app::main_loop() { TSheet_field::set_line_number_width(4); TConsuntivazione_msk msk; while (msk.run() == K_ENTER); } int ci2400(int argc, char *argv[]) { TConsuntivazione_app a; a.run(argc, argv, TR("Consuntivazione Ore")); return 0; }