// gestione files Contabilita' Analitica: COMMESSE
#include <execp.h>
#include <recset.h>
#include <relapp.h>

#include "calib01.h"
#include "ca0600a.h"
#include "commesse.h"
#include "cfcms.h"

////////////////////////////////////////////////////////////////////////
//MASCHERA
////////////////////////////////////////////////////////////////////////
class TCms_anal_msk : public TSimple_anal_msk
{
protected:
  virtual int get_logicnum() const { return LF_COMMESSE; } 

public:
  TCms_anal_msk();
};

TCms_anal_msk::TCms_anal_msk()
{
  read("ca0600a");
  ca_create_fields(*this, 2, LF_CDC, 1, 1, F_CMS_CDC1, F_CMS_CDCDES1, 0x0, COMMESSE_CODCOSTO);

  const bool use_pdcc = ca_config().get_bool("UsePdcc");
	const int nfields = ca_create_fields(*this, 3, use_pdcc ? LF_PCON : LF_PCONANA, 2, 2, F_CMSPDA1, F_CMSDES1, 0x0, COMMESSE_CODCONTO);
	int from = 1;

  for (int i = 0; i < nfields; i++)
	{
		TEdit_field & e = efield(F_CMSPDA1 + i);

    e.check_type(CHECK_NORMAL);
		TFieldref * fr = (TFieldref *) e.field();
		if (fr != NULL)
		{
			fr->set_from(from);
			if (i < 2)
				from += 3;
			else
				from += 6;
			fr->set_to(from - 1);
		}
	}
}

////////////////////////////////////////////////////////////////////////
//APPLICAZIONE
////////////////////////////////////////////////////////////////////////
// applicazione per la gestione delle commesse
class TCms_app : public TAnal_app
{  
	int _maxlev;
  bool _has_filter;

protected:
	void fin2row(const TMask& m);
	void for2row(const TMask& m);
	void row2fin(const TMask& m);
	void row2for(const TMask& m);
  virtual int read(TMask& m);
  virtual int write(const TMask& m);
  virtual int rewrite(const TMask& m);
  virtual bool remove();

  virtual void ini2mask(TConfig& ini, TMask&m, bool query);
  virtual void mask2ini(const TMask& m, TConfig& ini);

	virtual const char * extra_modules() const {return "cm";} //funziona anche con autorizzazione CM

  virtual bool filtered() const;

	virtual void init_modify_mode(TMask& mask);
	virtual void init_insert_mode(TMask& mask);
  virtual bool protected_record(TRectype& record);
  virtual TSimple_anal_msk* create_mask() const { return new TCms_anal_msk; }
  virtual bool user_create();

public:

	TCms_app() {}
};

void TCms_app::fin2row(const TMask& m)
{
	const TRelation * r = get_relation();
	TToken_string key;
	
	key.add(r->curr().get(COMMESSE_CODCMS));
	key.add("C");

	TRecord_array fins(key, LF_CFCMS);
	const int items = fins.rows();
	TSheet_field & s = m.sfield(F_CMS_FINAN);

	s.destroy();
	for (int i = 1; i <= items; i++)
	{
		const TRectype & rec = fins[i];
		TToken_string & str = s.row(i - 1);


		str.add(rec.get(CFCMS_CODCF), s.cid2index(F_CMS_CODFIN));
		str.add(rec.get(CFCMS_NRIGABAN), s.cid2index(F_CMS_NRIGABANFIN));
		str.add(rec.get(CFCMS_CUP), s.cid2index(F_CMS_CUPFIN));
		str.add(rec.get(CFCMS_CIG), s.cid2index(F_CMS_CIGFIN));
		str.add(rec.get(CFCMS_PERCFIN), s.cid2index(F_CMS_PERCFINFIN));
		str.add(rec.get(CFCMS_DESCR), s.cid2index(F_CMS_DESCRFIN));
		s.check_row(i - 1);
	}
	s.force_update();
}

void TCms_app::for2row(const TMask& m)
{
	const TRelation * r = get_relation();
	TToken_string key;
	
	key.add(r->curr().get(COMMESSE_CODCMS));
	key.add("F");

	TRecord_array fors(key, LF_CFCMS);
	const int items = fors.rows();
	TSheet_field & s = m.sfield(F_CMS_FORN);

	s.destroy();
	for (int i = 1; i <= items; i++)
	{
		const TRectype & rec = fors[i];
		TToken_string & str = s.row(i - 1);

		str.add(rec.get(CFCMS_CODCF), s.cid2index(F_CMS_CODFOR));
		str.add(rec.get(CFCMS_NRIGABAN), s.cid2index(F_CMS_NRIGABANFOR));
		str.add(rec.get(CFCMS_CUP), s.cid2index(F_CMS_CUPFOR));
		str.add(rec.get(CFCMS_CIG), s.cid2index(F_CMS_CUPFOR));
		s.check_row(i - 1);
	}
	s.force_update();
}

int TCms_app::read(TMask& m)
{
	int err = TAnal_app::read(m);

	if (err == NOERR)
	{
		fin2row(m);
		for2row(m);
	}
	return err;
}

void TCms_app::row2fin(const TMask& m)
{
	TRelation * r = get_relation();
	TToken_string key;
	
	key.add(r->lfile().get(COMMESSE_CODCMS));
	key.add("C");

	TRecord_array fins(key, LF_CFCMS);
	TSheet_field & s = m.sfield(F_CMS_FINAN);
	const int items = s.items();

	fins.destroy_rows();
	for (int i = 0; i < items; i++)
	{
		TRectype & rec = fins.row(i + 1, true);
		TToken_string & str = s.row(i);

		rec.put(CFCMS_CODCF, str.get(s.cid2index(F_CMS_CODFIN)));
		rec.put(CFCMS_NRIGABAN, str.get(s.cid2index(F_CMS_NRIGABANFIN)));
		rec.put(CFCMS_CUP, str.get(s.cid2index(F_CMS_CUPFIN)));
		rec.put(CFCMS_CIG, str.get(s.cid2index(F_CMS_CIGFIN)));
		rec.put(CFCMS_PERCFIN, str.get(s.cid2index(F_CMS_PERCFINFIN)));
		rec.put(CFCMS_DESCR, str.get(s.cid2index(F_CMS_DESCRFIN)));
	}
	fins.write(true);
}

void TCms_app::row2for(const TMask& m)
{
	TRelation * r = get_relation();
	TToken_string key;
	
	key.add(r->lfile().get(COMMESSE_CODCMS));
	key.add("F");

	TRecord_array fors(key, LF_CFCMS);
	TSheet_field & s = m.sfield(F_CMS_FORN);
	const int items = s.items();

	fors.destroy_rows();
	for (int i = 0; i < items; i++)
	{
		TRectype & rec = fors.row(i + 1, true);
		TToken_string & str = s.row(i);

		rec.put(CFCMS_CODCF, str.get(s.cid2index(F_CMS_CODFOR)));
		rec.put(CFCMS_NRIGABAN, str.get(s.cid2index(F_CMS_NRIGABANFOR)));
		rec.put(CFCMS_CUP, str.get(s.cid2index(F_CMS_CUPFOR)));
		rec.put(CFCMS_CIG, str.get(s.cid2index(F_CMS_CIGFOR)));
	}
	fors.write(true);
}

int TCms_app::write(const TMask& m)
{
	TRelation * r = get_relation();

	m.autosave(*r);
	int err = TAnal_app::write(m);
	if (err == NOERR)
	{
		row2fin(m);
		row2for(m);
	}
	return err;
}

int TCms_app::rewrite(const TMask& m)
{
	TRelation * r = get_relation();

	m.autosave(*r);
	int err = TAnal_app::rewrite(m);
	if (err == NOERR)
	{
		row2fin(m);
		row2for(m);
	}
	return err;
}

bool TCms_app::remove()
{
	int err = TAnal_app::remove();
	if (err == NOERR)
	{
		TRelation * r = get_relation();
		TToken_string key;

		key.add(r->lfile().get(COMMESSE_CODCMS));
		key.add("C");

		TRecord_array fins(key, LF_CFCMS);

		err = fins.remove();
		if (err == NOERR)
		{
			key.cut(0);
			key.add(r->lfile().get(COMMESSE_CODCMS));
			key.add("F");

			TRecord_array fors(key, LF_CFCMS);
			err = fors.remove();
		}
	}
	return err == NOERR;
}

void TCms_app::ini2mask(TConfig& ini, TMask& m, bool query)
{
	TString p;
	const TRelation * r = get_relation();

	TAnal_app::ini2mask(ini, m, query);           
  
  if (!query)
  {
		int i;
		p << LF_CFCMS << ",C";
		TSheet_field & si = m.sfield(F_CMS_FINAN);
		
		for (i = 0; ; i++)
		{
			TString para(p); para << "," << i + 1;
			const long codcf = ini.get_long(CFCMS_CODCF, para);
			if (codcf == 0L)
				break;
			TToken_string & row = si.row(i);

			row.add(codcf, si.cid2index(F_CMS_CODFIN));
			row.add(ini.get(CFCMS_NRIGABAN, para), si.cid2index(F_CMS_NRIGABANFIN));
			row.add(ini.get(CFCMS_CUP, para), si.cid2index(F_CMS_CUPFIN));
			row.add(ini.get(CFCMS_CIG, para), si.cid2index(F_CMS_CIGFIN));
			row.add(ini.get(CFCMS_PERCFIN, para), si.cid2index(F_CMS_PERCFINFIN));
			row.add(ini.get(CFCMS_DESCR, para), si.cid2index(F_CMS_DESCRFIN));
			si.update_mask(i - 1);
		}
		si.force_update();

		p.cut(0);
		p << LF_CFCMS << ",F";

		TSheet_field & so = m.sfield(F_CMS_FORN);

		for (i = 0; ; i++)
		{
			TString para(p); para << "," << i + 1;
			const long codcf = ini.get_long(CFCMS_CODCF, para);
			if (codcf == 0L)
				break;
			TToken_string & row = so.row(i);

			row.add(codcf, so.cid2index(F_CMS_CODFOR));
			row.add(ini.get(CFCMS_NRIGABAN, para), so.cid2index(F_CMS_NRIGABANFOR));
			row.add(ini.get(CFCMS_CUP, para), so.cid2index(F_CMS_CUPFOR));
			row.add(ini.get(CFCMS_CIG, para), so.cid2index(F_CMS_CIGFOR));
			so.update_mask(i - 1);
		}
		so.force_update();
	}
}

void TCms_app::mask2ini(const TMask& m, TConfig& ini)
{
	TString p;
	const TRelation * r = get_relation();

	TAnal_app::mask2ini(m, ini);
	p << LF_CFCMS << ",C";
	TSheet_field & si = m.sfield(F_CMS_FINAN);
	int items = si.items();

	for (int i = 0; i < items; i++)
	{
		TString para(p); para << "," << i + 1;
		TToken_string & row = si.row(i);

		ini.set(CFCMS_CODCF, row.get(si.cid2index(F_CMS_CODFIN)), para);
		ini.set(CFCMS_NRIGABAN, row.get(si.cid2index(F_CMS_NRIGABANFIN)), para);
		ini.set(CFCMS_CUP, row.get(si.cid2index(F_CMS_CUPFIN)), para);
		ini.set(CFCMS_CIG, row.get(si.cid2index(F_CMS_CIGFIN)), para);
		ini.set(CFCMS_PERCFIN, row.get(si.cid2index(F_CMS_PERCFINFIN)), para);
		ini.set(CFCMS_DESCR, row.get(si.cid2index(F_CMS_DESCRFIN)), para);
	}

	p.cut(0);
	p << LF_CFCMS << ",F";

	TSheet_field & so = m.sfield(F_CMS_FORN);
	
	items = so.items();
	for (int i = 0; i < items; i++)
	{
		TString para(p); para << "," << i + 1;
		TToken_string & row = so.row(i);

		ini.set(CFCMS_CODCF, row.get(so.cid2index(F_CMS_CODFOR)), para);
		ini.set(CFCMS_NRIGABAN, row.get(so.cid2index(F_CMS_NRIGABANFOR)), para);
		ini.set(CFCMS_CUP, row.get(so.cid2index(F_CMS_CUPFOR)), para);
		ini.set(CFCMS_CIG, row.get(so.cid2index(F_CMS_CIGFOR)), para);
	}
}

bool TCms_app::filtered() const
{
  if (_has_filter)
    return true;
  return TAnal_app::filtered();
}

//non si pu� eliminare una commessa se essa appare in un saldo analitico dell'anno in corso o dell'anno precedente
bool TCms_app::protected_record(TRectype& record)
{
  TString query;
  query << "USE SALDANA\nSELECT COMMESSA==#COMMESSA\nFROM ANNO=#ANNO\n";
  const TString commessa = record.get(COMMESSE_CODCMS);
  const TDate today(TODAY);
  const long anno = today.year();

  TISAM_recordset saldana_recset(query);
  saldana_recset.set_var("#COMMESSA", TVariant(commessa));
  saldana_recset.set_var("#ANNO", TVariant(anno - 1));
  
  const long items = saldana_recset.items();
  return items > 0;
}

void TCms_app::init_modify_mode(TMask& mask)
{
	const short id = ((TCms_anal_msk &)mask).get_field_id(_maxlev - 1 , 1);
	mask.enable(-1, mask.get(id).not_empty());

  TAnal_app::init_modify_mode(mask);
}

void TCms_app::init_insert_mode(TMask& mask)
{
	const short id = ((TCms_anal_msk &)mask).get_field_id(_maxlev - 1, 1);
	mask.enable(-1, mask.get(id).not_empty());

  TAnal_app::init_insert_mode(mask);
}

bool TCms_app::user_create()
{
  const TMultilevel_code_info& mci = ca_multilevel_code_info(LF_COMMESSE);

	_maxlev = mci.levels();
  if (_maxlev <= 0)
    return error_box(TR("Le commesse non sono state configurate"));

  //eventuali filtri per utente
  _has_filter = cache().get("%AUC", user(), "S0").full();

  return TAnal_app::user_create();
}

int ca0600(int argc, char* argv[])
{
  TCms_app a;
  a.run(argc, argv, TR("Commesse"));
  return 0;
}