//--------------------------------------------------------------------------- #include #include #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; } //---------------------------------------------------------------------------