#include <applicat.h>
#include <files.h>
#include <prefix.h>
#include <reprint.h>

#include "pl1048100a.h"
#include "../ve/packlist.h"
#include "../ve/velib.h"
#include "../ve/velib07.h"
#include "../lv/lvlib.h"
#include "../lv/lvrcondv.h"

#include <utility.h>

// LV047

#define RIEMPI_C_XS "I0"
#define RIEMPI_C_M  "I1"
#define RIEMPI_C_XL "I2"
#define NORMALE_XS  "I3"
#define NORMALE_M   "I4"
#define NORMALE_XL  "I5"
#define RIEMPI_S_XS "I6"
#define RIEMPI_S_M  "I7"
#define RIEMPI_S_XL "I8"
#define PRECEDENZA  "I9"
#define TPARTICOLO  "I10"
#define DESCR_ETI   "S0"

// LV020

#define TPIMBALLO   "S0"
#define RIEMPIMENTO "S1"
#define DIMENSIONE  "S2"
#define ARTSEP      "B0"

///////////////////////////////////////////////////////////
// TCartellini_report
///////////////////////////////////////////////////////////

class TCartellini_report : public TDocument_report
{
  size_t _first_msg;
	TDocument_cache _cache;
	int _contnum;

protected:
  virtual size_t get_usr_words(TString_array& words) const;
  virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack);
  bool msg_cart_parent_doc(TVariant_stack& stack);
  bool msg_cart_parent_row(TVariant_stack& stack);
	bool msg_currcont(TVariant_stack& stack);
	bool msg_contnum(TVariant_stack& stack);

public:

	TCartellini_report(const char * name, int contnum) : _contnum(contnum) { load(name);}
};

bool TCartellini_report::msg_cart_parent_doc(TVariant_stack& stack)
{
  TReport_field& cf = *curr_field();

	int idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_PACKLIST);

  if (idx < 0)
		return false;

	const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();
	TRectype head(LF_DOC);

	head.put(DOC_PROVV, rec.get_char(PACKLIST_PROVV));
	head.put(DOC_ANNO, rec.get_int(PACKLIST_ANNO));
  head.put(DOC_CODNUM, rec.get(PACKLIST_CODNUM));
  head.put(DOC_NDOC, rec.get_long(PACKLIST_NDOC));

	TDocumento & doc  = _cache.doc(head);
  const TString& values = stack.pop().as_string();

	output_values(doc, values);
  return true;
}

bool TCartellini_report::msg_cart_parent_row(TVariant_stack& stack)
{
	int idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_PACKLIST);

  if (idx < 0)
		return false;

	const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();
	TRectype head(LF_DOC);

	head.put(DOC_PROVV, rec.get_char(PACKLIST_PROVV));
	head.put(DOC_ANNO, rec.get_int(PACKLIST_ANNO));
  head.put(DOC_CODNUM, rec.get(PACKLIST_CODNUM));
  head.put(DOC_NDOC, rec.get_long(PACKLIST_NDOC));

	TDocumento & doc  = _cache.doc(head);
	const int idriga = rec.get_int(PACKLIST_IDRIGA);

	int nrows = doc.physical_rows();
  for (int r = 1; r <= nrows; r++)
		if (doc[r].get_int(RDOC_IDRIGA) == idriga)
		{
		  const TString& values = stack.pop().as_string();
  
			output_values(doc[r], values);
		  return true;
		}
	return false;
}

bool TCartellini_report::msg_currcont(TVariant_stack& stack)
{
	int idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_PACKLIST);

  if (idx < 0)
		return false;

	const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();

	curr_field()->set(rec.get(PACKLIST_CODICE).sright(4));
	return true;
}

bool TCartellini_report::msg_contnum(TVariant_stack& stack)
{
	curr_field()->set(format("%d", _contnum));
	return true;
}

size_t TCartellini_report::get_usr_words(TString_array& words) const
{
  TDocument_report::get_usr_words(words);
  
  const char* const name[] = { "CART_PARENT_DOC", "CART_PARENT_ROW", "CURRCONT", "CONTNUM", NULL };

  ((TCartellini_report*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile
  for (size_t i = 0; name[i] != NULL; i++)
    words.add(name[i]);
  
  return words.items();
}

bool TCartellini_report::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
{
  if (opcode < _first_msg)
    return TDocument_report::execute_usr_word(opcode, stack);
  opcode -= _first_msg;
  switch (opcode)
  {
  case 0 : msg_parent_doc(stack); break;
  case 1 : msg_parent_row(stack); break;
	case 2 : msg_currcont(stack); break;
	case 3 : msg_contnum(stack); break;
  default: break;
  }

  while (!stack.pop().is_null());  // Svuota eventuali parametri variabili inutilizzati

  return true;
}

///////////////////////////////////////////////////////////
// TCartellini_report
///////////////////////////////////////////////////////////

class TCarrello : public TRecord_array
{
	real _perc;
public:
	const real perc() const {return _perc;}
	real & perc() { return _perc;}

	TCarrello(const char * key) : TRecord_array(key, LF_PACKLIST) { }
};

static TLaundry_contract * __contract = NULL;

class TCrea_cartellini : public TSkeleton_application
{
	TDocumento * _doc;
	int _contnum;

private:
    
protected:
  virtual const char * extra_modules() const { return "ba"; }
	const TDocumento & doc() const { return *_doc;}
  virtual void main_loop();
	void crea_precedenze(ofstream & outfile, TArray & precs);
	void crea_carrelli(TArray & precs);
	void riempi_max(TArray & carrelli, TArray & precs);
	void resto_max(TArray & carrelli, TArray & precs);
	void riempi_normale(TArray & carrelli, TArray & precs, int level);
	void riempi_resti(TArray & carrelli, TArray & precs);

public:
	const TDocumento & doc() { return *_doc; }
	void ottimizza(const char * dir);
	void stampa();
	bool set_params();
	bool set_params(const TMask & m);
};

// restituisce un riferimento all' applicazione
inline TCrea_cartellini & app() { return (TCrea_cartellini &) main_app();}

class TPrecedenza : public TObject
{
	int _tipoart;
	int _prec;
	TString _codart;
	int _anno;
	char _provv;
	TString4 _codnum;
	long _ndoc;
	int _idriga;
	int _nrow;
	real _qta;
	real _pacchi;
	char _tipocf;
	long _codcf;

protected:
public:
	const int tipoart() const { return _tipoart; }
	const int prec() const { return _prec; }
	const TString & codart() const { return _codart; }
	const int anno() const { return _anno; }
	const char provv() const { return _provv; }
	const TString & codnum() const { return _codnum; }
	const long ndoc()  const { return _ndoc; }
	const int idriga()  const { return _idriga; }
	const int nrow()  const { return _nrow; }
	const real qta()  const { return _qta; }
	const real pacchi()  const { return _pacchi; }
	real & qta()  { return _qta; }
	real & pacchi() { return _pacchi; }
	const char tipocf()  const { return _tipocf; }
	const long codcf()  const { return _codcf; }
	const char * key_carrello(int num)const ;
	real get_qta_max() const;
	real get_pacchi_max() const;
	real get_qta_nor() const;
	real get_pacchi_nor() const;
	const TString & tipo_contenitore() const;
	const TString & dimensione() const;
	const char * contr_field_max() const;
	const char * field_max() const;
	const char * contr_field_nor() const;
	const char * field_nor() const;
	void prec2rec(TRectype & rec) const;
  static const real pezzixpacco(const char *codart);
  const real pezzixpacco() const { return pezzixpacco(_codart);}

  virtual void print_on(ostream& out) const;

	TPrecedenza(const char * codart, int anno, char provv, const char * codnum, long ndoc, int idriga, int nrow, real & qta, real & pacchi, char tipocf, long codcf);
};

const char * TPrecedenza::key_carrello(int num) const
{
	TString & key = get_tmp_string(25);
	TString4 codnum(_codnum); codnum.left_just(4, '_');

	key.format("%s|%c%04d%s%06ld%04d", (const char *) tipo_contenitore(), _provv, _anno, (const char *) codnum, _ndoc, num);
	return key;
}

const real TPrecedenza::pezzixpacco(const char * codart)
{
  real pppacco = cached_article(codart).get_real(ANAMAG_PPCOLLO);

  if (pppacco == ZERO)
    pppacco = cached_article(codart).get_real(ANAMAG_PPCONF);

  return pppacco == ZERO ? UNO : pppacco;
}

TPrecedenza::TPrecedenza(const char * codart, int anno, char provv, const char * codnum, long ndoc, int idriga, int nrow, real & qta, real & pacchi, char tipocf, long codcf) :
							_codart(codart), _anno(anno), _provv(provv), _codnum(codnum), _ndoc(ndoc), _idriga(idriga), _nrow(nrow), _qta(qta), _pacchi(pacchi), _tipocf(tipocf), _codcf(codcf)
{
	TString8 key; key << tipocf << codcf; // verificare
	const bool separa_articoli = cache().get("&LV020", key).get_bool(ARTSEP);
	const bool sacchi = cache().get("&LV020", key, TPIMBALLO) == "S";


	_tipoart = separa_articoli ? atoi(cache().get("&LV047", codart, TPARTICOLO)) : 0;
	if (__contract == NULL)
	{
		TString key; key.format("%c|%d|%s|%ld", _provv, _anno, (const char *) _codnum, _ndoc);
		__contract = new TLaundry_contract(_codcf, 0, TDate(cache().get(LF_DOC, key, DOC_DATADOC)));
	}
	const TRectype & rec = __contract->row(_codart);
	
	_prec = 0;
	_prec = rec.get_int(LVRCONDV_PRECEDENZA);
	if (_prec == 0)
		_prec = sacchi ? 10  : atoi(cache().get("&LV047", _codart, PRECEDENZA));
}

const char * TPrecedenza::contr_field_max() const
{
	const TString & dim = dimensione();
	
	if (dim == "XS")
		return LVRCONDV_QTAMAXXS;
	else
		if (dim == "M")
			return LVRCONDV_QTAMAXM;
		else
			if (dim == "XL")
				return LVRCONDV_QTAMAXXL;
	return LVRCONDV_QTAMAXXS;
}

const char * TPrecedenza::field_max() const
{
	const TString4 tipo = tipo_contenitore();
	const TString & dim = dimensione();

	if (tipo == "C")
	{
		if (dim == "XS")
			return RIEMPI_C_XS;
		else
			if (dim == "M")
				return RIEMPI_C_M;
			else
				if (dim == "XL")
					return RIEMPI_C_XL;
		return RIEMPI_C_XS;
	}
	else
	{
		if (dim == "XS")
			return RIEMPI_S_XS;
		else
			if (dim == "M")
				return RIEMPI_S_M;
			else
				if (dim == "XL")
					return RIEMPI_S_XL;
	}
	return RIEMPI_S_XS;
}

const char * TPrecedenza::contr_field_nor() const
{
	const TString & dim = dimensione();
	if (dim == "XS")
		return LVRCONDV_QTANORMXS;
	else
		if (dim == "M")
			return LVRCONDV_QTANORMM;
		else
			if (dim == "XL")
				return LVRCONDV_QTANORMXL;
	return LVRCONDV_QTANORMXS;
}

const char * TPrecedenza::field_nor() const
{
	const TString4 tipo = tipo_contenitore();
	const TString & dim = dimensione();

	if (tipo == "C")
	{
		if (dim == "XS")
			return NORMALE_XS;
		else
			if (dim == "M")
				return NORMALE_M;
			else
				if (dim == "XL")
					return NORMALE_XL;
		return NORMALE_XS;
	}
	else
	{
		if (dim == "XS")
			return RIEMPI_S_XS;
		else
			if (dim == "M")
				return RIEMPI_S_M;
			else
				if (dim == "XL")
					return RIEMPI_S_XL;
	}
	return RIEMPI_S_XS;
}

real TPrecedenza::get_qta_max() const
{
	const TRectype & rec = __contract->row(_codart);
	real qta;
	
	qta = rec.get_int(contr_field_max());
	if (qta == 0)
		qta = real(cache().get("&LV047", _codart, field_max()));
	return qta;
}

real TPrecedenza::get_pacchi_max() const
{
	real pacchi = get_qta_max();
	real pppacco = pezzixpacco();
	
  pacchi /= pppacco;
	pacchi.floor();
	return pacchi;
}

real TPrecedenza::get_qta_nor() const
{
	const TRectype & rec = __contract->row(_codart);
	real qta;
	
	qta = rec.get_int(contr_field_nor());
	if (qta == 0)
		qta = real(cache().get("&LV047", _codart, field_nor()));
	return qta;
}

real TPrecedenza::get_pacchi_nor() const
{
	real pacchi = get_qta_nor();
	real pppacco = pezzixpacco();
	
	pacchi /= pppacco;
	pacchi.floor();
	return pacchi;
}

const TString & TPrecedenza::tipo_contenitore() const
{
	TString key; key << _tipocf << _codcf; // verificare
	
	return cache().get("&LV020", key, TPIMBALLO);
}

const TString & TPrecedenza::dimensione() const
{
	TString key; key << _tipocf  << _codcf; // verificare
	
	return cache().get("&LV020", key, DIMENSIONE);
}

void TPrecedenza::prec2rec(TRectype & rec) const
{

	TToken_string key;

	rec.put(PACKLIST_DATA, TDate(TODAY));
	rec.put(PACKLIST_CODART, _codart);
	rec.put(PACKLIST_TIPOCF, _tipocf);
	rec.put(PACKLIST_CODCF, _codcf);
	rec.put(PACKLIST_CODNUM, _codnum);
	rec.put(PACKLIST_ANNO, _anno);
	rec.put(PACKLIST_PROVV, _provv);
	rec.put(PACKLIST_NDOC, _ndoc);
	rec.put(PACKLIST_IDRIGA, _idriga);
	rec.put(PACKLIST_NRIGADOC, _nrow);
	rec.put(PACKLIST_DATADOC, app().doc().get(DOC_DATADOC));
}

void TPrecedenza::print_on(ostream& out) const
{
	out << _tipoart << ';' << _prec << ';' << _codart << ';' << _anno << ';' << _provv << ';' << _codnum << ';' << _ndoc << ';' << _idriga << ';' << _nrow << ';' << _qta << ';' << _pacchi << ';' << _tipocf << ';' << _codcf;
}

int sort_prec(const TObject** o1, const TObject** o2)
{
	const TPrecedenza & p1 = (const TPrecedenza &) **o1;
	const TPrecedenza & p2 = (const TPrecedenza &) **o2;

	if (p1.tipoart() != p2.tipoart())
		return p1.tipoart() - p2.tipoart();
	if (p1.prec() != p2.prec())
		return p1.prec() - p2.prec();
	return strcmp(p1.codart(), p2.codart());
}

void TCrea_cartellini::crea_precedenze(ofstream & outfile, TArray & precs)
{
	const TDocumento & d = doc();
	const int rows = d.physical_rows();
	const char provv = d.get_char(DOC_PROVV);
	const int anno = d.get_int(DOC_ANNO);
	const char tipocf = d.get_char(DOC_TIPOCF);
	const long codcf = d.get_long(DOC_CODCF);
	const TString4 codnum = d.get(DOC_CODNUM);
	const long ndoc = d.get_long(DOC_NDOC);

	for(int r = 1; r <= rows; r++)
  {
		const TRiga_documento row = d[r];
		real qta = row.get_real(RDOC_QTA); qta.floor();
		const TString codart = row.get(RDOC_CODART);
		const TString caus = row.get(RDOC_CODAGG1);
		real pacchi = qta; // se non 
    real pppacco = TPrecedenza::pezzixpacco(codart);
	
		pacchi /= pppacco;
    real intpacchi = pacchi; 
		if (intpacchi.floor() != pacchi)
      pacchi.ceil();
		int nrow = row.get_int(RDOC_NRIGA);
		int idriga = row.get_int(RDOC_IDRIGA);

		precs.add(new TPrecedenza(codart, anno, provv, codnum, ndoc, idriga, nrow, qta, pacchi, tipocf, codcf));
  }

	precs.sort(sort_prec);
	const int prec_nrows = precs.items();

	outfile << "Precedenze\nTipo;Precedenza;Articolo;Anno;;Numerazione;Numero;ID Riga;Numero riga;Quantit�;Pacchi;Cliente\n";
	for (int r = 0; r < prec_nrows; r++)
		outfile << precs[r] << '\n';
}

void TCrea_cartellini::riempi_max(TArray & carrelli, TArray & precs)
{
	const int items = precs.items();
	
	for(int r = 0; r < items; r++)
	{
		TPrecedenza & p = (TPrecedenza &) precs[r];
		const real max_qta = p.get_qta_max();
		const real max_pacchi = p.get_pacchi_max();

		if (max_pacchi <= ZERO)
			break;

		while (p.pacchi() > max_pacchi)
		{
			TCarrello * c = new TCarrello(p.key_carrello(carrelli.items() + 1));

			c->destroy_rows();
			carrelli.add(c);

			TRectype & rec = c->row(c->rows() + 1, true);

			p.prec2rec(rec);
			rec.put(PACKLIST_QTA, max_qta);
			rec.put(PACKLIST_CONF, max_pacchi);
			c->perc() = UNO;
			rec.put(PACKLIST_PERCOCC, CENTO);
			p.qta() -= max_qta;
			p.pacchi() -= max_pacchi;
		}
	}
}

void TCrea_cartellini::resto_max(TArray & carrelli, TArray & precs)
{
	const int items = precs.items();
	TString key; key << doc().get(DOC_TIPOCF) << doc().get_long(DOC_CODCF); // verificare
	const bool separa_articoli = cache().get("&LV020", key).get_bool(ARTSEP);

	for (int r = 0; r < items; r++)
	{
		TPrecedenza &p = (TPrecedenza &) precs[r];

		if (p.pacchi() > ZERO)
		{
			TCarrello * c = NULL;
			const real max_qta = p.get_qta_max();
			const real max_pacchi = p.get_pacchi_max();
			const int ncarrelli = carrelli.items();
			const int tipoart = separa_articoli ? atoi(cache().get("&LV047", p.codart(), TPARTICOLO)) : 0;

			if (max_pacchi <= ZERO)
				break;

			real perc = p.pacchi() / max_pacchi;

			perc.round(4);
			for (int i = 0; i < ncarrelli; i++)
			{
				TCarrello * cc = (TCarrello *) carrelli.objptr(i);
				real cperc = cc->perc();
				const int tipoartcc = separa_articoli ? atoi(cache().get("&LV047", cc->row(1).get(PACKLIST_CODART), TPARTICOLO)) : 0;

				if (tipoart == tipoartcc && UNO - cperc >= perc)
				{
				  c = (TCarrello *) carrelli.objptr(i);
					break;
				}
			}
			if (c == NULL)
			{
				c = new TCarrello(p.key_carrello(carrelli.items() + 1));

				c->destroy_rows();
				carrelli.add(c);
			}

			TRectype & rec = c->row(c->rows() + 1, true);

			p.prec2rec(rec);
			rec.put(PACKLIST_QTA, p.qta());
			rec.put(PACKLIST_CONF, p.pacchi());
			real pr = perc * CENTO; pr.round(2);
			rec.put(PACKLIST_PERCOCC, pr);
			c->perc() += perc;
			p.qta() = ZERO;
			p.pacchi() = ZERO;
		}
	}
}

void TCrea_cartellini::riempi_normale(TArray & carrelli, TArray & precs, int level)
{
	const int items = precs.items();
	int ncarrello = 0;
	TString key; key << doc().get(DOC_TIPOCF) << doc().get_long(DOC_CODCF); // verificare
	const bool separa_articoli = cache().get("&LV020", key).get_bool(ARTSEP);
	
	for(int r = 0; r < items; r++)
	{
		TPrecedenza & p = (TPrecedenza &) precs[r];

		if (p.prec() <= level && p.pacchi() > ZERO)
		{
	    int ncarrelli = carrelli.items();
			if (level > 1)
				ncarrello = 0;
			const real qta = p.get_qta_nor();
			const real pacchi = p.get_pacchi_nor();
			const real max_pacchi = p.get_pacchi_max();
			const int tipoart = separa_articoli ? atoi(cache().get("&LV047", p.codart(), TPARTICOLO)) : 0;

			if (pacchi <= ZERO || max_pacchi <= ZERO)
				break;

			real perc = pacchi / max_pacchi;

			perc.round(4);
			if (level == 1 || p.pacchi() >= pacchi)
			{
				if (level > 1)
				{
					for (ncarrello = 0; ncarrello < ncarrelli; ncarrello++)
					{
						TCarrello * cc = (TCarrello *) carrelli.objptr(ncarrello);
						real cperc = cc->perc();
						const int tipoartcc = separa_articoli ? atoi(cache().get("&LV047", cc->row(1).get(PACKLIST_CODART), TPARTICOLO)) : 0;

						if (tipoart == tipoartcc && UNO - cperc >= perc)
							break;
					}
				}
				while (p.pacchi() > pacchi)
				{
					TCarrello * c = (TCarrello *) carrelli.objptr(ncarrello++);
					
					if (c == NULL)
					{
						c = new TCarrello(p.key_carrello(ncarrello));
						carrelli.add(c);
						c->destroy_rows();
					}
	
					TRectype & rec = c->row(c->rows() + 1, true);

					p.prec2rec(rec);
					rec.put(PACKLIST_QTA, qta);
					rec.put(PACKLIST_CONF, pacchi);
					real pr = perc * CENTO; pr.round(2);
					rec.put(PACKLIST_PERCOCC, pr);
					c->perc() += perc;
					p.qta() -= qta;
					p.pacchi() -= pacchi;
				}

				TCarrello * c = (TCarrello *) carrelli.objptr(ncarrello++);
				
				if (c == NULL)
				{
					c = new TCarrello(p.key_carrello(ncarrello));
					carrelli.add(c);
					c->destroy_rows();
				}

  			const real pppacco =  p.pezzixpacco();
        real resto = ZERO;

        if (p.pacchi() > UNO && p.qta() != p.pacchi() * pppacco)
        {
          p.pacchi() -= UNO;
          resto = p.qta() - p.pacchi() * pppacco;
          p.qta() = p.pacchi() * pppacco;
        }
				TRectype & rec = c->row(c->rows() + 1, true);

				p.prec2rec(rec);
				rec.put(PACKLIST_QTA,	p.qta());
				rec.put(PACKLIST_CONF, p.pacchi());
				perc = p.pacchi() / max_pacchi;
				c->perc() += perc;
				real pr = perc * CENTO; pr.round(2);
				rec.put(PACKLIST_PERCOCC, pr);
				p.qta() = ZERO;
				p.pacchi() = ZERO;
        if (resto != ZERO)
        {
			    TRectype & rec = c->row(c->rows() + 1, true);

			    p.prec2rec(rec);
			    rec.put(PACKLIST_QTA, resto);
			    rec.put(PACKLIST_CONF, UNO);
      		real pr = CENTO / max_pacchi ; pr.round(2);
	  		  rec.put(PACKLIST_PERCOCC, pr);
        }
			}
		}
	}
}

void TCrea_cartellini::riempi_resti(TArray & carrelli, TArray & precs)
{
	const int items = precs.items();
	TString key; key << doc().get(DOC_TIPOCF) << doc().get_long(DOC_CODCF); // verificare
	const bool separa_articoli = cache().get("&LV020", key).get_bool(ARTSEP);

	for(int r = 0; r < items; r++)
	{
		TPrecedenza &p = (TPrecedenza &) precs[r];

		while (p.pacchi() > ZERO)
		{
			const real max_qta = p.get_qta_max();
			const real max_pacchi = p.get_pacchi_max();
			const int ncarrelli = carrelli.items();
			real qta = p.qta();
			real pacchi = p.pacchi();
			const int tipoart = separa_articoli ? atoi(cache().get("&LV047", p.codart(), TPARTICOLO)) : 0;

			if (pacchi <= ZERO || max_pacchi <= ZERO)
				break;

			real perc = pacchi / max_pacchi;
			TCarrello * c = NULL;
			
			perc.round(4);
			for (int i = 0; i < ncarrelli; i++)
			{
				TCarrello * cc = (TCarrello *) carrelli.objptr(i);
				real cperc = cc->perc();
				const int tipoartcc = separa_articoli ? atoi(cache().get("&LV047", cc->row(1).get(PACKLIST_CODART), TPARTICOLO)) : 0;

				if (tipoart == tipoartcc && UNO - cperc >= UNO / max_pacchi)
				{
				  c = (TCarrello *) carrelli.objptr(i);
					break;
				}
			}

			if (c == NULL)
			{
				c = new TCarrello(p.key_carrello(carrelli.items() + 1));

				c->destroy_rows();
				carrelli.add(c);
			}

			const real pppacco =  p.pezzixpacco();
      real resto = ZERO;

      if (UNO - c->perc() < perc)
			{
				perc = UNO - c->perc();
				pacchi = perc * max_pacchi; pacchi.floor();
				perc = pacchi / max_pacchi;
				perc.round(4);
				qta = pacchi;
	
				qta *= pppacco;
			}
      else
        if (pacchi > UNO && qta != pacchi * pppacco)
        {
          pacchi -= UNO;
          resto = qta - pacchi * pppacco;
          qta = pacchi * pppacco;
        }
			TRectype & rec = c->row(c->rows() + 1, true);

			p.prec2rec(rec);
			rec.put(PACKLIST_QTA, qta);
			rec.put(PACKLIST_CONF, pacchi);
			real pr = perc * CENTO; pr.round(2);
			rec.put(PACKLIST_PERCOCC, pr);
			c->perc() += perc;
			p.qta() -= qta;
			p.pacchi() -= pacchi;
      if (resto != ZERO)
      {
			  TRectype & rec = c->row(c->rows() + 1, true);

			  p.prec2rec(rec);
			  rec.put(PACKLIST_QTA, resto);
			  rec.put(PACKLIST_CONF, UNO);
    		real pr = CENTO / max_pacchi ; pr.round(2);
			  rec.put(PACKLIST_PERCOCC, pr);
  			p.qta() = ZERO;
	  		p.pacchi() = ZERO;
      }
		}
	}
}

void TCrea_cartellini::crea_carrelli(TArray & precs)
{
	TString key; key << doc().get(DOC_TIPOCF) << doc().get_long(DOC_CODCF); // verificare
	const bool cli_max = cache().get("&LV020", key, RIEMPIMENTO) == "A";
	TArray carrelli;
	
	if (cli_max)
	{
		riempi_max(carrelli, precs);
		resto_max(carrelli, precs);
	}
	else
	{
		for (int pr = 1; pr < 10; pr++)
			riempi_normale(carrelli, precs, pr);
		riempi_resti(carrelli, precs);
	}

	_contnum = carrelli.items();

	for (int c = 0; c < _contnum; c++)
	{
		TCarrello & carrello = (TCarrello &) carrelli[c];

		carrello.write(true);
	}

	for (int c = _contnum + 1 ; ; c++)
	{
		TCarrello carrello(((TPrecedenza &) precs[0]).key_carrello(c));


		if (carrello.read(carrello.key()) == NOERR)
		{
			if (carrello.rows() == 0)
				break;
			carrello.remove();
		}
		else
			break;
	}
}

void TCrea_cartellini::stampa()
{
	TString key; key << _doc->get(DOC_TIPOCF) << _doc->get_long(DOC_CODCF);
	const TString4 tpimballo = cache().get("&LV020", key, TPIMBALLO);
	TFilename name("pl1048100"); name << tpimballo; name.trim(); name.ext("rep");

	if (!name.custom_path())
		name = "pl1048100";
	TCartellini_report rep(name, _contnum);
	TRecordset * pset = rep.recordset();

  if (pset != NULL)
  {
		TTrec docs(LF_DOC);
		const int nfield = docs.fields();

		for (int i = 0; i < nfield; i++)
		{
			TToken_string fieldname(docs.fielddef(i));

			fieldname = fieldname.get(0);
			TVariant var(_doc->get(DOC_PROVV));
			fieldname.insert("#");
			pset->set_var(fieldname, var);
		}
		
		pset->set_var("#CONT", tpimballo);
	}

	TReport_book book;

	for (int c = 1; c <= _contnum; c++)
	{
		if (pset != NULL)
		{
			TString4 codnum(_doc->get(DOC_CODNUM)); codnum.left_just(4, '_');

			pset->set_var("#KEY", format("%c%04d%-4s%06ld%04d", _doc->get_char(DOC_PROVV), _doc->get_int(DOC_ANNO), (const char *) codnum, _doc->get_long(DOC_NDOC), c));
		}

		book.add(rep);
	}
	book.print_or_preview();
}

void TCrea_cartellini::ottimizza(const char * dir)
{
	TString outname;

	outname.format("%s/bo%s%06ld.xls", dir, (const char *) doc().get(RDOC_CODNUM), doc().get_long(RDOC_NDOC));
	TString_array  prec_rows;
	{
		ofstream outfile(outname);

		crea_precedenze(outfile, prec_rows);
	}
	crea_carrelli(prec_rows);
}

bool TCrea_cartellini::set_params(const TMask & m)
{
	const char provv = m.get(F_PROVV)[0];
	const int anno = m.get_int(F_ANNO);
	const TString4 codnum = m.get(F_CODNUM);
	const long ndoc = m.get_long(F_NDOC);

	_doc = new TDocumento(provv, anno, codnum,ndoc);
	return _doc != NULL && _doc->physical_rows() > 0;
}

bool TCrea_cartellini::set_params()
{   
	const TFixed_string arg = argv(2);
  if ((arg[0] != '-' && arg[0] != '/') || (arg[1] != 'i' && arg[1] != 'I'))
    return false;
    
  TString ini_name = arg.mid(2);

	//controlla che il file su cui deve scrivere ci sia; se non c'� d� una segnalazione di errore
  if (!fexist(ini_name))
		return false;

  TString4 para;  para.format("%d", LF_DOC);
	TConfig ini(ini_name, para);

	const char provv = ini.get(DOC_PROVV)[0];
	const int anno = ini.get_int(DOC_ANNO);
	const TString4 codnum = ini.get(DOC_CODNUM);
	const long ndoc = ini.get_long(DOC_NDOC);

	_doc = new TDocumento(provv, anno, codnum,ndoc);
	return _doc != NULL && _doc->physical_rows() > 0;
}

void TCrea_cartellini::main_loop() //definizione della member function main_loop, della classe TCrea_cartellini
{
	TString outdir(firm2dir(prefix().firm().codice())); // ditta
	
	outdir << "/golem/ps1048"; 
	if (!fexist(outdir))
		make_dir(outdir);
	if (argc() <= 2)
	{
		TMask m("pl1048100a");

		m.set(F_CODNUM, ini_get_string(CONFIG_DITTA, "lv", "NUM_GEN"));
		m.first_focus(F_NDOC);
		
		while (m.run() == K_ENTER && set_params(m))
		{
			ottimizza(outdir);
			stampa();
			delete _doc;
			_doc = NULL;
			m.first_focus(F_NDOC);
		}
	}
	else
		if (set_params())
		{
			ottimizza(outdir);
			stampa();
		}
}

//////  Esecuzione del programma  ///////////

int pl1048100(int argc, char* argv[])
{
  TCrea_cartellini app;
  app.run(argc,argv,"Generazione etichette");
  return 0;
}