TPVwin/TpvStockActual1.cpp
2021-09-12 22:19:30 +02:00

457 lines
15 KiB
C++

//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#include <stdio.h>
#pragma hdrstop
#include "TpvStockActual1.h"
#include "TDlgBuscar.h"
#include "TpvStockQR.h"
//---------------------------------------------------------------------------
#pragma link "Grids"
#pragma link "ElastFrm"
#pragma resource "*.dfm"
TStockActual *StockActual;
//---------------------------------------------------------------------------
__fastcall TStockActual::TStockActual(TComponent* Owner)
: TForm(Owner)
{
TbProductos -> Active = true;
TbSeguimiento -> Active = true;
// Cargar el dialogo, buscar Productos
TDlgBuscar *DlgBuscar;
DlgBuscar = new TDlgBuscar(this);
DlgBuscar -> TbBusquedas -> TableName = "Tb_Ref";
DlgBuscar -> TbBusquedas -> Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::DBGrid1DrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column, TGridDrawState State)
{
// Etiquetas
if ( TbProductosEsNodo -> Value == -1 ||
( TbProductos -> FieldByName("I.V.A") -> AsInteger == 100 &&
TbProductos -> FieldByName("Precio Costo") -> AsFloat == 0 ) )
{
DBGrid1 -> Canvas -> Brush -> Color = clRed;
DBGrid1 -> DefaultDrawColumnCell( Rect, DataCol, Column, State );
} else {
// Stock bajo mínimos
if ( TbProductos -> FieldByName("Stock Actual")->AsInteger < TbProductos -> FieldByName("StockMinimo")->AsInteger )
{
DBGrid1->Canvas -> Font -> Color = clRed;
DBGrid1->DefaultDrawColumnCell( Rect, DataCol, Column, State );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::BuscarFichaClick(TObject *Sender)
{
Indices -> Selected = Indices -> Items -> GetFirstNode();
TbProductos->Filtered = false;
if ( DlgBuscar->Buscar( NEW, TbProductos ) )
{
BusqSig -> Enabled = true;
BusqAnt -> Enabled = true;
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::BusqAntClick(TObject *Sender)
{
if ( DlgBuscar->Buscar( PRIOR, TbProductos ) )
BusqSig -> Enabled = true;
else
BusqAnt -> Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::BusqSigClick(TObject *Sender)
{
if ( DlgBuscar->Buscar( NEXT, TbProductos ) )
BusqAnt -> Enabled = true;
else
BusqSig -> Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::DataSource1DataChange(TObject *Sender,
TField *Field)
{
char BarraEstado[80];
// Indicador de FichaActual / Num.Fichas
if ( DataSource1 -> DataSet -> RecNo > 0 )
sprintf( BarraEstado, "%d / %d", DataSource1 -> DataSet -> RecNo, DataSource1 -> DataSet -> RecordCount );
else
sprintf( BarraEstado, "¿Nuevo? / %d", DataSource1 -> DataSet -> RecordCount );
StatusBar1->Panels->Items[1]->Text = BarraEstado;
if ( PageControl1->ActivePage == TabSheet2 )
DBChart1->RefreshData();
PaintBox1Paint( Sender );
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::BackMainClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::PaintBox1Paint(TObject *Sender)
{
// Dibujamos una barra donde representamos el coste frente al beneficio
TRect Rect;
Rect.Left = 0;
Rect.Right = PaintBox1 -> Width;
Rect.Top = 0;
Rect.Bottom = PaintBox1 -> Height;
// Si el Beneficio es negativo, todo es perdida
if ( TbProductosBeneficioStock -> Value > 0 )
{
// Lo pintamos todo de VERDE == BENEFICIO
PaintBox1 -> Canvas -> Brush -> Color = clGreen;
PaintBox1 -> Canvas -> FillRect( Rect );
// Ancho de la franja de COSTES == ROJO
Rect.Right = (int)(( PaintBox1 -> Width * TbProductos -> FieldByName("Precio Costo") -> AsCurrency ) / TbProductos -> FieldByName("Precio Venta 1") -> AsCurrency);
PaintBox1 -> Canvas -> Brush -> Color = clRed;
PaintBox1 -> Canvas -> FillRect( Rect );
} else {
// Lo pintamos todo de ROJO == COSTES
PaintBox1 -> Canvas -> Brush -> Color = clRed;
PaintBox1 -> Canvas -> FillRect( Rect );
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::DBGrid1KeyPress(TObject *Sender, char &Key)
{
switch( Key )
{
case VK_RETURN:
if ( TbProductos->State == dsEdit || TbProductos->State == dsInsert )
TbProductos->Post();
Key = 0;
if ( DBGrid1 -> Fields[DBGrid1 -> SelectedField -> Index] == NULL )
{
DBGrid1 -> SelectedField = DBGrid1 -> Fields[0];
} else
DBGrid1 -> SelectedField = DBGrid1 -> Fields[DBGrid1 -> SelectedField -> Index];
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::FormClose(TObject *Sender,
TCloseAction &Action)
{
// Destruimos el dialogo de busquedas...
delete DlgBuscar;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::RegAntClick(TObject *Sender)
{
TbProductos -> Prior();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::RegSigClick(TObject *Sender)
{
TbProductos -> Next();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::TbProductosAfterOpen(TDataSet *DataSet)
{
TTreeNode * NuevoNodo;
union
{
int Familia; // 0x01020304
char Fam[4]; // 0 1 2 3
} FamC;
int N, MascaraComp;
// Deshabilitamos los controles...
TbProductos -> DisableControls();
// Reconstrucción del arbol...
TbProductos -> First();
while ( ! TbProductos -> Eof )
{
// Si es parte del arbol...
if ( TbProductosEsNodo -> Value == -1 )
{
FamC . Familia = TbProductos -> FieldByName("Familia") -> AsInteger;
// Si es raiz, lo creamos directamente
if ( FamC . Fam[3-1] != 0 )
{
// De lo contrario, buscamos su posición NATURAL dentro del arbol.
//////////////////////////////////////////////////////////////////
// Contruimos la mascara de comparación...
if ( FamC . Fam[3-2] == 0 )
MascaraComp = FamC . Familia & 0xFF000000;
else
if ( FamC . Fam[3-3] == 0 )
MascaraComp = FamC . Familia & 0xFFFF0000;
else
MascaraComp = FamC . Familia & 0xFFFFFF00;
N = 2;
while ( N < Indices -> Items -> Count )
{
if ( ((int *)Indices -> Items -> Item[N] -> Data ) [0] == MascaraComp )
{
// Añadimos un nuevo nodo al primer nivel en que nos quedamos
NuevoNodo = Indices->Items->AddChild( Indices -> Items -> Item[N], TbProductos -> FieldByName("Nombre del Producto") -> Value );
NuevoNodo -> Data = new int [3];
((int *)NuevoNodo -> Data)[0] = FamC . Familia;
((int *)NuevoNodo -> Data)[1] = 0;
((int *)NuevoNodo -> Data)[2] = TbProductos -> FieldByName("ForcedIndex") -> AsInteger;
break;
} else
N++;
}
} else {
// Añadimos un nuevo nodo al primer nivel en que nos quedamos
NuevoNodo = Indices->Items->Add( Indices -> Items -> Item[0], TbProductos -> FieldByName("Nombre del Producto") -> Value );
NuevoNodo -> Data = new int [3];
((int *)NuevoNodo -> Data)[0] = FamC . Familia;
((int *)NuevoNodo -> Data)[1] = 0;
((int *)NuevoNodo -> Data)[2] = TbProductos -> FieldByName("ForcedIndex") -> AsInteger;
}
}
// Avanzamos al siguiente registro
TbProductos -> Next();
}
N = 2;
while ( N < Indices -> Items -> Count )
{
// Establecemos las imágenes (Por defecto es documento final)
if ( Indices -> Items -> Item[N] -> HasChildren )
{
Indices -> Items -> Item[N]->ImageIndex = 0;
Indices -> Items -> Item[N]->SelectedIndex = 0;
} else {
Indices -> Items -> Item[N]->ImageIndex = 2;
Indices -> Items -> Item[N]->SelectedIndex = 2;
}
N++;
}
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// ATENCIÖN, LA SIGUIENTE LINEA ES POR UN BUG DETECTADO EN EL TREEVIEW //
/////////////////////////////////////////////////////////////////////////
NuevoNodo = Indices->Items->AddChild( Indices -> Items -> Item[0], "Bug TTreeView 1.1 Fixed" );
Indices -> Items -> Delete( NuevoNodo );
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
Indices -> Selected = Indices -> Items -> Item[1];
// Indices -> Items -> Item[0] -> Selected = true;
// Rehabilitamos los controles...
TbProductos -> EnableControls();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::IndicesExpanding(TObject *Sender,
TTreeNode *Node, bool &AllowExpansion)
{
// Si el nodo es padre
if ( Node -> HasChildren )
{
// Usamos las imágenes de los libros abiertos
Node->ImageIndex = 1;
Node->SelectedIndex = 1;
} else {
// Usamos las imágenes de los documentos
Node->ImageIndex = 2;
Node->SelectedIndex = 2;
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::IndicesCollapsing(TObject *Sender,
TTreeNode *Node, bool &AllowCollapse)
{
// Si el nodo es padre
if ( Node -> HasChildren )
{
// Restauramos las imágenes originales
Node->ImageIndex = 0;
Node->SelectedIndex = 0;
} else {
// Un nodo no padre NO puede ser CONTRAIDO
// Usamos las imágenes de los documentos
Node->ImageIndex = 2;
Node->SelectedIndex = 2;
}
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::IndicesChange(TObject *Sender,
TTreeNode *Node)
{
union
{
long Familia;
char Fam[4];
} FamL, FamH;
// Reajustamos el filtro, acuerdo a la nueva familia
switch ( Indices -> Selected -> AbsoluteIndex )
{
case 0:
// TbProductos -> Filtered = false;
// return;
if ( Indices -> Selected -> Text == "Ver Todos" )
{
TbProductos->Filter = "";
TbProductos -> Filtered = true;//false;
return;
} else {
FamL . Familia = 0x00000000;
FamH . Familia = 0x01000000;
}
break;
case 1:
// El filtro es para la familia 0000
FamL . Familia = 0x00000000;
FamH . Familia = 0x01000000;
break;
default:
// Contruimos los limites del filtro ( >= AND < )
FamL . Familia = ( (int *) Indices -> Selected -> Data ) [0];
FamH . Familia = FamL . Familia;
if ( !FamH . Fam[3-1] )
FamH . Fam[3-0] ++;
else
if ( !FamH . Fam[3-2] )
FamH . Fam[3-1] ++;
else
if ( !FamH . Fam[3-3] )
FamH . Fam[3-2] ++;
else
FamH . Fam[3-3] ++;
break;
};
// Filtramos según los rangos construidos antes...
TbProductos->FilterOptions = TbProductos->FilterOptions << foCaseInsensitive;
TbProductos->Filter = "([Familia] >= '" + AnsiString( (int)( FamL . Familia ) ) + "' AND [Familia] < '" + AnsiString( (int)( FamH . Familia ) ) + "')";
TbProductos -> Filtered = true;
//************************************************************************
// BEGIN -- Suma Stock-TOTAL
//************************************************************************
Currency ValorStock, BeneficioStock;
Currency StockCant; AnsiString Buffer;
// recorremos toda la base de datos, para estimar el valor total
// del stock y su benefico aproximado...
ValorStock = 0; BeneficioStock = 0;
TbProductos -> First();
while ( ! TbProductos -> Eof )
{
StockCant = Currency( TbProductos -> FieldByName("Stock Actual") -> AsFloat * TbProductos -> FieldByName("CantUnitaria") -> AsFloat );
ValorStock += StockCant * TbProductos -> FieldByName("Precio Costo") -> AsCurrency ;
BeneficioStock += StockCant * TbProductos -> FieldByName("Precio Venta 1") -> AsCurrency ;
TbProductos -> Next();
}
BeneficioStock -= ValorStock;
Buffer = "Valor total: " + FormatCurr("###,###,###.#0", ValorStock );//CurrToStrF(ValorStock, 4, 2);
Label2 -> Caption = Buffer.c_str();
Buffer = "Beneficio aprox.: " + FormatCurr("###,###,###.#0", BeneficioStock );//CurrToStrF(BeneficioStock, 4, 2);
Label3 -> Caption = Buffer.c_str();
TbProductos -> First();
//************************************************************************
// END -- Suma Stock-TOTAL
//************************************************************************
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::TabSheet2Show(TObject *Sender)
{
#ifdef DEM001
ShowMessage( "El seguimiento estadístico de productos\n no esta incluido en esta versión.");
ShowMessage( "Esta función ha sido deshabilitada para esta versión.\nPongase en contacto con el autor, si desea\nel módulo correspondiente: Jose-David.Guillen@cs.us.es" );
#endif
DBChart1->RefreshData();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::BajoMinimosClick(TObject *Sender)
{
IndicesChange( 0, 0 );
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::TbProductosFilterRecord(TDataSet *DataSet,
bool &Accept)
{
if ( BajoMinimos->Checked )
Accept = (DataSet->FieldByName("Stock Actual")->AsInteger <= DataSet->FieldByName("StockMinimo")->AsInteger);
else
Accept = 1;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::TbProductosBeforeInsert(TDataSet *DataSet)
{
ShowMessage( "No esta autorizado a insertar nuevos registros.\nAl menos en este módulo del programa.");
Abort();
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::ImprimirStockClick(TObject *Sender)
{
// Debemos distinguir entre: NORMAL / MINIMOS
TStockQR *StockQR;
Visible = false;
StockQR = new TStockQR(this);
#ifdef DEBUG
StockQR -> QuickRep1 -> Preview();
#else
StockQR -> QuickRep1 -> Print();
#endif
Visible = true;
delete StockQR;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::TbProductosCalcFields(TDataSet *DataSet)
{
// Valor Stock
TbProductos->FieldByName("ValorStock")->AsCurrency = TbProductos->FieldByName("Stock Actual")->AsFloat * TbProductos->FieldByName("Precio Costo")->AsCurrency;
// Beneficio Stock
TbProductosBeneficioStock->AsCurrency = ( TbProductos->FieldByName("Precio Venta 1")->AsCurrency - TbProductos->FieldByName("Precio Costo")->AsCurrency ) * TbProductos->FieldByName("Stock Actual")->AsFloat;
}
//---------------------------------------------------------------------------
void __fastcall TStockActual::FormResize(TObject *Sender)
{
// BajoMinimos->Left = PageControl1->Width - 105;
}
//---------------------------------------------------------------------------