Ir al contenido



Foto

Programa de gestión desde 0 (Activo)


  • Por favor identifícate para responder
156 respuestas en este tema

#41 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 07 julio 2013 - 04:01

ahora la tabla detalle

CREATE TABLE DETALLE (
    ID                  INTEGER NOT NULL,
    IDENTIFICADOR       INTEGER NOT NULL,  //............................................. FOREIGN KEY con el id de documentos 
    TIPODOCUMENTO        T20 NOT NULL /* T20 = VARCHAR(20) */,    //............................................. tipo de documento (XPAF)
    NUMERODOCUMENTO      T20 NOT NULL /* T20 = VARCHAR(20) */,  //............................................. código del documento (XPAF)
    SERIE                T3 NOT NULL /* T3 = VARCHAR(3) */,  //............................................. Serie del documento (XPAF)
    CODIGOARTICULO      T20 NOT NULL /* T20 = VARCHAR(20) */,  //............................................. Código del artículo (XPAF)
    DESCRIPCIONARTICULO  T80 /* T80 = VARCHAR(80) */,  //............................................. 1 (ver en post anterior) (XPAF)
    CANTIDAD            INTEGER NOT NULL,  //............................................. Cantidad o unidades del artículo (XPAF)
    PRECIOUNIDAD        POR NOT NULL /* POR = NUMERIC(15,4) */,  //.............................................  Precio de la unidad (XPAF)
    IMPUESTO            POR NOT NULL /* POR = NUMERIC(15,4) */,  //............................................. Porcentaje del impuesto (XPAF)
    DESCUENTO            POR NOT NULL /* POR = NUMERIC(15,4) */,  //............................................. Porcentaje del descuento (XPAF)
    COMISION            POR NOT NULL /* POR = NUMERIC(15,4) */,  //............................................. Porcentaje de la comisión (XPAF)
    PESOUNIDAD          POR /* POR = NUMERIC(15,4) */,  //............................................. peso de cada unidad (XPAF)
    MININOTA             VARCHAR(150),  //............................................. Campo texto de 150 caracteres, para ampliar detalles (XPAF)
    CAMPOLIBRE          T80 /* T80 = VARCHAR(80) */,  //............................................. Campo libre ya que la ley va cambiando o podemos necesitar (XPAF)
    MODIFICADO           INTEGER NOT NULL,  //............................................. Número de veces que se ha modificado (XPAF)
    SERVICIO            LOG /* LOG = CHAR(1) */,  //............................................. Es un servicio (XPAF)
    IDPRECIOESPECIAL    INTEGER,  //............................................. Número del ID, si el precio tomado es precio especial para el cliente (1) (XPAF)
    ALMACEN              T20 /* T20 = VARCHAR(20) */,  //............................................. Almacén del que sale la mercancía (XPAF)
    NUMEROPRESUPUESTO    T20 /* T20 = VARCHAR(20) */,  //.............................................  Número (Código) del presupuesto que viene (2) (PAF)
    NUMEROPEDIDO        T20 /* T20 = VARCHAR(20) */,  //.............................................  Número (Código) del pedido que viene (2) (AF)
    FECHAPEDIDO          DATE,  //............................................. Fecha del pedido del que viene (2) (AF)
    NUMEROALABARAN      T20 /* T20 = VARCHAR(20) */,  //.............................................  Número (Código) del albarán que viene (2) (A)
    FECHAALBARAN        T20 /* T20 = VARCHAR(20) */  //............................................. Fecha del albarán del que viene (2) (A)
);

/******************************************************************************/
/*                                Foreign Keys                                */
/******************************************************************************/

//  ALTER TABLE DETALLE ADD CONSTRAINT FK_DETALLE_1 FOREIGN KEY (IDENTIFICADOR) REFERENCES DOCUMENTOS (ID) ON DELETE CASCADE ON UPDATE CASCADE;


1) si tiene precio especial, no le afecta ni rapel, ni otros

2) El cliente normalmente quiere que en el documento de unión (albarán o factura) aparezca reflejado por documentos para el poder revisarlos y comprobar, por ello debemos crear un registro que
  especifique según sea el caso de manera que si es un albarán sería  'Pedido 120001 fecha 07/072012' y si fuera una factura sería 'Albarán 120025 fecha 30/07/2012', detallando despues de 
  cada linea del pedido o albarán.
  Este no sería el caso si el cliente tiene un rapel o escandallo con cierre final, ya que para ello debemos unir todos los campos con el mismo código de articulo, para obtener la cantidad de
  unidades y ver que precio se le asigna, por lo que el precio del albarán o de la factura difieren, pero aún así debemos  registrar  de que albaranes o pedido bien, pero lo haríamos al pie del 
  documento dentro de sus notas.
  • 0

#42 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 07 julio 2013 - 04:16

Ahora la última de las tres la tabla lotes de documentos (LOTESDOCUMENTOS)

CREATE TABLE LOTESDOCUMENTOS (
    ID              INTEGER NOT NULL,
    IDENTIFICADOR  INTEGER NOT NULL, //............................................. FOREIGN KEY con el id de documentos
    TIPODOCUMENTO  T20 NOT NULL /* T20 = VARCHAR(20) */, //............................................. tipo de documento
    NUMERODOCUMETO  T20 NOT NULL /* T20 = VARCHAR(20) */, //............................................. código del documento
    SERIE          T3 NOT NULL /* T3 = VARCHAR(3) */, //............................................. Serie del documento
    LOTE            T20 NOT NULL /* T20 = VARCHAR(20) */, //............................................. número de lote
    CANTIDAD        INTEGER NOT NULL, //............................................. Cantidad de este artículo con este lote
    CODIGOARTICULO  T20 NOT NULL /* T20 = VARCHAR(20) */, //............................................. código del artículo
    ADR            T80 /* T80 = VARCHAR(80) */, //............................................. Descripción y texto ADR
    EXCEPCION      INTEGER, //............................................. Cantidad exceptuada del ADR
    LIMITE          INTEGER, //............................................. limite de carga en vehículo con medidas mínimas según el ADR
    CADUCIDAD      DATE, //.............................................  fecha de caducidad de este lote
    CAMPOLIBRE      T80 /* T80 = VARCHAR(80) */ //............................................. Campo libre ya que la ley va cambiando o podemos necesitar 
);


//******************************************************************************/
//*                                Foreign Keys                                */
//******************************************************************************/

//ALTER TABLE LOTESDOCUMENTOS ADD CONSTRAINT FK_LOTESDOCUMENTOS_1 FOREIGN KEY (IDENTIFICADOR) REFERENCES DETALLE (ID) ON DELETE CASCADE ON UPDATE CASCADE;


Como podemos ver tenemos una relación entre las tablas siendo de la siguiente manera

DOCUMENTOS.ID------>DETALLES.IDENTIFICADOR  y
                                    DETALLES.ID ------------------ LOTESDOCUMENTOS.IDENTIFICADOR

También contamos con los campos TIPODOCUMENTO, NUMERODOCUMETO y SERIE, para poder hacer sus búsquedas y relaciones en SQL.

Podríamos hacerlo creando un juego de tablas por tipo de documentos, que sería la manera más simple y rápida de hacer, pero esta manera, nos permite reducir consumo de recursos, ya que muchos campos son repetitivo,  e incluso eliminar la tabla de LOTESDOCUMENTOS y unir sus campos a los de DETALLES, pero de esta manera es más clara.

Como siempre espero este clara la explicación actual y si hay dudas, comentarios, o consejos, rectificaciones, etc, ya sabéis, aquí estoy.
  • 0

#43 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 09 julio 2013 - 04:45

Para que valláis abriendo boca una imagen del visor de documentos, sin estar activo aún muchos campos

Imagen Enviada

en el apartado 1 veréis un DBtext, con el fondo en verde, realmente va en transparente, pero como no contiene datos aún, para controlar se u ancho

El código en https://gist.github....onymous/5956364


Para que este sistema funcione debemos usar en su llamada el siguiente sistema

[DELPHI]procedure TFMenu.act_V_FacturasExecute(Sender: TObject);
//------------------------------------------------------------------------------
//**************************************************************[ Facturas ]****
// Gestión de Proveedores apto desde nivel 6
//------------------------------------------------------------------------------
begin
    VarSTipoDocumento:='FACTURA';
    FXPAF.PC.ActivePageIndex:=0;
    FXPAF.PC2.ActivePageIndex:=0;
    Acceso(6,FXPAF);
end;[/DELPHI]

Y el procedimiento acceso
[DELPHI]function TFMenu.Acceso(NivelAc:Integer;MForm:TForm):Boolean;
//------------------------------------------------------------------------------
//*****************************************************[ funcion de acceso ]****
//------------------------------------------------------------------------------
begin
  if Nivel>=NivelAc then
  begin
MForm.Show;
      Result:=true;
  end else
  begin
      ShowMessage('Debe tener nivel '+IntToStr(NivelAc)+' para poder acceder a este apartado');
      Result:=False;
  end;
end;[/DELPHI]

En algunos casos, deberemos confirmar con la clave de acceso al programa, la entrada en un apartado esto lo haremos de la siguiente manera

[DELPHI]procedure TFMenu.ACT_Esp_RegularStockExecute(Sender: TObject);
//------------------------------------------------------------------------------
//*********************************************************[ REgular Stock ]****
// Regulación de Stock apto desde nivel 8 + clave de usuario
//------------------------------------------------------------------------------
begin
    if Acceso(8,FRegulaStock) then
    begin
      FRegulaStock.Hide;
      PostMessage(Handle, InputBoxMessage, 0, 0); // Para imputboxt con password chard
      if InputBox('Comprobando seguridad', 'Por favor indroduzca su clave de usuario', '')= VarSClaveUSuario then
        FRegulaStock.Show
      else
      begin
        ShowMessage('La clave de seguridad no es la adecuada,' + #13 +
            'no tiene permiso, para acceder a este apartado');
        FRegulaStock.Close;
      end;
    end;
end;[/DELPHI]


Para ello necesitamos estos cambios en nuestro programa

[DELPHI]procedure TFMenu.InputBoxSetPasswordChar(var Msg: TMessage);
// Para imputboxt con password chard
// ------------------------------------------------------------------------------
// *****************[ Para convertir los caracteres en *  de un imput box]*******
// ------------------------------------------------------------------------------
var HInputForm, HEdit, HButton: HWND;
begin
  HInputForm := Screen.Forms[0].Handle;
  if (HInputForm <> 0) then
  begin
    HEdit := FindWindowEx(HInputForm, 0, 'TEdit', nil);
    SendMessage(HEdit, EM_SETPASSWORDCHAR, Ord('*'), 0);
  end;
  // ------------------------------------------------------------------------------
  // ****************************[ Otras partes importantes de este código ]*******
  // {Despues del uses}
  // const
  // InputBoxMessage = WM_USER + 200;    //Para imputboxt con password chard
  // {En el Type}
  // procedure InputBoxSetPasswordChar(var Msg: TMessage); message InputBoxMessage;
  // {USO CON LAS DOS LINEAS}
  // PostMessage(Handle, InputBoxMessage, 0, 0);    //Para imputboxt con password chard
  // if InputBox('Comprobando seguridad', 'Porfavor indroduzca su clave de usuario', '')  = VarClaveUSusario then
  // ------------------------------------------------------------------------------
end;[/DELPHI]

Espero os sea útil y como siempre espero vuestros comentarios.

Por cierto, que nadie se anima a valorar el trabajo, es una buena manera de saber, donde tengo que mejorar y todos podéis hacerlo, ni me ofende, ni me molesta y es un buen ejercicio, para ver con la perspectiva de los compañeros el trabajo que estoy realizando os recuerdo como pido que me valoréis el trabajo.

í Si no es molestia, podrían hacerme el favor de valorar el trabajo hasta este momento, lo más sinceramente posible, el motivo, es que como siempre he dicho y he mantenido, yo no soy un experto y necesito saber cuales son mis puntos fuertes, para intentar mejorar.

Me gustaría que lo valorarais de la siguiente manera, del 1 al 10, siendo 1 la menor valoración claro, cada una de las siguientes facetas, y si se os ocurre alguna, ya sabéis.

Explicaciones
Claridad
Código
Tablas
Descripciones
Diseño
Conceptos
forma de aplicar los conceptos
y utilidad

Esto me permitirá, en cuanto al tutorial, intentar corregir y mejorarlo , si puedo y ha nivel personal, seguir aprendiendo y como no autoestima, que me la podéis hundir más    o nivelar


No se si es la época o qué, pero parece que los compañeros, no están muy animados a participar, como hace un par de años, claro esta es mi opinión, humildemente
  • 0

#44 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 09 julio 2013 - 05:02

Ya he explicado, esto en post anteriores, pero creo que es importante para el tutorial, así que nuevamente, expongo mi sistema de acceso a las diferentes partes del programa, si recordáis en la tabla usuarios (que por cierto, se me colo una S de más y se quedo como ususarios :p) tenemos la estructura

CREATE TABLE USUSARIOS (
    ID      INTEGER NOT NULL,
    CLAVE    T20 /* T20 = VARCHAR(20) */,
    USUARIO  T20 /* T20 = VARCHAR(20) */,
    NIVEL    INTEGER,
    NOMBRE  T80 /* T80 = VARCHAR(80) */
);


en ella existen dos apartados fundamentales, para el acceso, ojo todos son importantes, pero estos dos fundamentales, que son CLAVE y NIVEL, como es lógico, solicito el usuario y la clave, en un form de acceso, compruebo y si esta ok, cargo una serie de variables locales, con el usuario, la clave y el nivel, después la llamada a los diferentes apartados la hago con la función ACCESO, donde comprobamos e, nivel, con el que ponemos al apartado, todo desde un ActionList, para no tener que estar repitiendo código., si tenemos que volver a solicitar la clave uso un inputbox con la peculiaridad, de poner los caracteres como asteriscos, para ello uso las instrucciones que a parece en el procedure TFMenu.InputBoxSetPasswordChar(var Msg: TMessage);

De esta manera, si nos vamos a tomar un café y un compañero quiere acceder a un apartado, al que no tiene nivel y es delicado, aunque este activo el nivel de usuario, le solicitara la clave para acceder, con lo que se quedara con las ganas, creo que unas de las ventajas de este sistema es el ahorro de código, en apartados de seguridad.

Yo suelo usar el siguiente sistema para valorar el nivel de usuario

0...5 los valoro como acceso de visitante
6...7 Introductor de datos
8  Persona de mucha confianza
9  Acceso total

Claro esta que si tienes nivel 7 en vez de 6 puedes acceder a más apartados, o ver partes dentro de un apartado, que de otra manera no aparecen. Los apartados, que por tema de datos, o seguridad, siempre solicito clave de acceso e incluso en algún programa he usado la clave de acceso con un sistema de clave por fecha o clave diferencial.

Espero no haberos liado.
  • 0

#45 tuni

tuni

    Member

  • Miembros
  • PipPip
  • 37 mensajes

Escrito 10 julio 2013 - 02:40

Muy bueno el tutorial,  lo sigo desde el principio, es muy completo, seguramente se podría mejorar la estética y resumir algo mas, pero como muy bien dices , y estoy totalmente de  acuerdo, el realizar programas para alguien siempre es distinto que para uno mismo y hay varía la complejidad del trabajo/tutorial que estas realizando.Te felicito.  Te sigo tanto por este foro como por el del clubdelphi, solamente que en este último no he podido realizarte  ninguna respuesta.  Espero que cuando lo acabes lo cuenges completo con la fuentes.  Mis conocimientos de delphi y bases de datos son muy básicos pero me encanta lo que estas realizando, se comprende  y asimila bien tus explicaciones  y la forma en que lo realizas.  Gracias y saludos.   
  • 0

#46 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 10 julio 2013 - 04:07

Muchas gracias Tuni, pero  si no te importa usa el sistema de valoración que e puesto, para saber el nivel que crees en que estoy en cada apartado, y así con el resto de compañeros, cuando evalúen, me podéis indicar,  en que tengo que mejorar o cambiar.
  • 0

#47 tuni

tuni

    Member

  • Miembros
  • PipPip
  • 37 mensajes

Escrito 10 julio 2013 - 07:38

De acuerdo, perdona:   

[table]
[tr][td]CATEGORÍA[/td][td]    [/td][td]CALIFICACIÓN[/td][/tr]
[tr][td][/td][td][/td][td][/td][/tr]
[tr][td]Explicaciones[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Claridad[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Código[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Tablas[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Descripciones[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Diseño[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Conceptos[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Forma de aplicar los conceptos[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Utilidad[/td][td]    [/td][td]10[/td][/tr]
[/table]

Espero que ahora te valga mi puntuación y haber sido lo mas correcto valorando tu trabajo.    Saludos. 


  • 0

#48 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.812 mensajes
  • LocationMéxico

Escrito 10 julio 2013 - 08:40

Hola

Me tomé el atrevimiento de modificar la respuesta de tuni para colocar una tabla con las calificaciones que le ha dado a nuestro amigo José Luis.

Saludos
  • 0

#49 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 10 julio 2013 - 08:42

A mi al igual que tuni me parece que el diseño puede mejorarse más. No digo claro que se vea mal, al contrario me gusta, pero si considero que puede mejorarse. Allí si aplica lo de que cada quién pinta y adorna sus casas a su gusto por lo que eso queda bastante ligado al gusto de cada quíén.

En cuanto al código, las explicaciones y las entregas me parecen muy bien explicas. Aquí va mi puntuación:

CATEGORÍA      CALIFICACIÓN
 
Explicaciones      9
Claridad      9
Código      9
Tablas      9
Descripciones      9
Diseño      7
Conceptos      9
Forma de aplicar los conceptos      9
Utilidad      10



  • 0

#50 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 10 julio 2013 - 09:38

Después de unas cuantas horas buenas os pongo el código de dos componentes que se usaran en el módulo que estamos, son iguales, uno para integer y otro para double, son Spinedit para tablas

[DELPHI]//Este componente deriva de los componentes NewDbedit,´JanbuttonEdit y DbSpinEdit  y nuevas propiedades añadidas

unit NewDBSpinEdit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, DBneweditjl , mask,  DbTables, DB, DBCtrls;

type
  TNewDBSpinEdit = class(TDBNewEditJL)
  private
    FButtonUp : TBitBtn;
    FButtonDown : TBitBtn;
    FWidthButton : Integer;
    FCaptionUp : String;
    FCaptionDown : String;
    FProportional : Boolean;
    FMinValue : LongInt;
    FMaxValue : LongInt;
    FIncrement : LongInt;
    FEditorEnabled: Boolean;
    FFontButtons : TFont;
    procedure SetGlyph(const Value: TBitmap);
    function  GetGlyph:TBitmap;
    procedure SetGlyphDown(const Value: TBitmap);
    function  GetGlyphDown:TBitmap;
    procedure autofit;
    procedure TextChanged(sender: TObject);
    procedure setCaptionUp(const Value:String);
    procedure setCaptionDown(const Value:String);
    procedure setWidthButton(const Value:Integer);
    procedure setProportional(const Value:Boolean);
    function  GetValue: LongInt;
    procedure SetValue (NewValue: LongInt);
    function  CheckValue (NewValue: LongInt): LongInt;
    procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
    procedure CMExit(var Message: TCMExit);  message CM_EXIT;
    procedure WMPaste(var Message: TWMPaste);  message WM_PASTE;
    procedure WMCut(var Message: TWMCut);  message WM_CUT;
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure CreateWnd;override;
    function GetOnButtonUpClick: TNotifyEvent;
    function GetOnButtonDownClick: TNotifyEvent;
    procedure SetOnButtonUpClick(Value: TNotifyEvent);
    procedure SetOnButtonDownClick(Value: TNotifyEvent);
    procedure KeyPress(var Key: Char); override;
    function IsValidChar(Key: Char): Boolean; virtual;
    procedure UpClick (Sender: TObject); virtual;
    procedure DownClick (Sender: TObject); virtual;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
  published
    property OnButtonUpClick: TNotifyEvent read GetOnButtonUpClick write SetOnButtonUpClick;
    property OnButtonDownClick: TNotifyEvent read GetOnButtonDownClick write SetOnButtonDownClick;
    property GlyphUP :TBitmap read GetGlyph write SetGlyph;
    property GlyphDown :TBitmap read GetGlyphDown write SetGlyphDown;
    property CaptionUp :String  read FCaptionUp write SetCaptionUp;
    property CaptionDown :String read FCaptionDown write SetCaptionDown;
    property WidthButton :Integer read FWidthButton write SetWidthButton default 15;
    property Proportional :Boolean read FProportional write SetProportional default True;
    property MaxValue :LongInt read FMaxValue    write FMaxValue;
    property MinValue :LongInt read FMinValue write FMinValue;
    property Value :LongInt read GetValue write SetValue;
    property Increment :LongInt read FIncrement  write FIncrement default 1;
    property FontButtons  :TFont  read FFontButtons write FFontButtons;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Data Controls', [TNewDBSpinEdit]);
end;

procedure TNewDBSpinEdit.WMCut(var Message: TWMCut);
begin
  if not FEditorEnabled or ReadOnly then Exit;
  inherited;
end;

procedure TNewDBSpinEdit.WMPaste(var Message: TWMPaste);
begin
  if not FEditorEnabled or ReadOnly then Exit;
  inherited;
end;

procedure TNewDBSpinEdit.WMSize(var Message: TWMSize);
begin
  inherited;
  autofit;
end;

function TNewDBSpinEdit.CheckValue(NewValue: Integer): LongInt;
begin
  Result := NewValue;
  if (FMaxValue <> FMinValue) then
  begin
    if NewValue < FMinValue then Result := FMinValue
    else if NewValue > FMaxValue then Result := FMaxValue;
  end;
end;

procedure TNewDBSpinEdit.CMEnter(var Message: TCMGotFocus);
begin
  if AutoSelect and not (csLButtonDown in ControlState) then
    SelectAll;
  inherited;
end;

procedure TNewDBSpinEdit.CMExit(var Message: TCMExit);
begin
  inherited;
  if CheckValue (Value) <> Value then
    SetValue (Value);
end;

constructor TNewDBSpinEdit.Create(AOwner: TComponent);
begin
  inherited;
  width :=121;
  height :=24;
  FCaptionDown :='q';
  FCaptionUp :='p';
  FWidthButton :=15;
  FontButtons :=TFont.Create;
  with FFontButtons do
  begin
    Name :='wingdings 3';
    Size :=7;
  end;
  FButtonUP :=TBitbtn.Create (self);
  with FButtonUP do
  begin
    width :=FWidthButton;
    height :=15;
    Font :=FFontButtons;
    top :=1;
    parent :=Self;
    Caption :=FCaptionUp;
    OnClick :=UpClick;
  end;
  FButtonDown :=TBitbtn.Create (self);
  with FButtonDown do
  begin
    width :=FWidthButton;
    height :=15;
    Font :=FFontButtons;
    top :=1;
    parent :=Self;
    Caption :=FCaptionDown;
    OnClick :=DownClick;
  end;
  FProportional :=True;
  ControlStyle := ControlStyle - [csSetCaption];
  FIncrement := 1;
  Text :='0';
end;

destructor  TNewDBSpinEdit.Destroy;
begin
  FButtonUP.Free;
  FbuttonDown.Free;
  inherited Destroy;
end;

procedure TNewDBSpinEdit.DownClick(Sender: TObject);
begin
  if ReadOnly then MessageBeep(0) else Value := Value - FIncrement;
  EditCanModify;
end;

procedure TNewDBSpinEdit.setCaptionDown(const Value: String);
begin
  if FCaptionDown<>value then FCaptionDown:=Value;
  FButtonDown.Caption:=FCaptionDown;
end;

procedure TNewDBSpinEdit.setCaptionUp(const Value: String);
begin
  if FCaptionUp<>value then FCaptionUp:=Value;
  FButtonUp.Caption:=FCaptionUp;
end;

procedure TNewDBSpinEdit.setProportional(const Value: Boolean);
begin
  if FProportional<>value then FProportional:=Value;
end;

procedure TNewDBSpinEdit.SetValue(NewValue: Integer);
begin
  Text := IntToStr (CheckValue (NewValue));
  EditText := Text; { força update }
end;

procedure TNewDBSpinEdit.setWidthButton(const Value: Integer);
begin
  if FWidthButton<>value then FWidthButton:=Value;
  autofit;
end;

function TNewDBSpinEdit.GetOnButtonDownClick: TNotifyEvent;
begin
  Result := FButtonDown.OnClick;
end;

function TNewDBSpinEdit.GetOnButtonUpClick: TNotifyEvent;
begin
  Result := FButtonUP.OnClick;
end;

function TNewDBSpinEdit.GetValue: LongInt;
begin
  try
    Result := StrToInt (Text);
  except
    Result := FMinValue;
  end;
end;

function TNewDBSpinEdit.IsValidChar(Key: Char): Boolean;
begin
  Result := (Key in ['+', '-', '0'..'9']) or ((Key < #32) and (Key <> Chr(VK_RETURN)));
  if not FEditorEnabled and Result and ((Key >= #32) or (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then Result := False;
end;

procedure TNewDBSpinEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if Key = VK_UP then UpClick (Self) else if Key = VK_DOWN then DownClick (Self);
  inherited KeyDown(Key, Shift);
end;

procedure TNewDBSpinEdit.KeyPress(var Key: Char);
begin
  if not IsValidChar(Key) then
  begin
    Key := #0;
    MessageBeep(0)
  end;
  if Key <> #0 then inherited KeyPress(Key);
end;

procedure TNewDBSpinEdit.SetOnButtonDownClick(Value: TNotifyEvent);
begin
  FButtonDown.onClick := Value;
end;

procedure TNewDBSpinEdit.SetOnButtonUpClick(Value: TNotifyEvent);
begin
  FButtonUP.onClick := Value;
end;

procedure TNewDBSpinEdit.SetGlyph(const Value: TBitmap);
begin
  FButtonUp.Glyph.assign(Value);
end;

procedure TNewDBSpinEdit.SetGlyphDown(const Value: TBitmap);
begin
  FButtonDown.Glyph.assign(Value);
end;

function TNewDBSpinEdit.GetGlyph: TBitmap;
begin
  result:=FButtonUp.Glyph;
end;

function TNewDBSpinEdit.GetGlyphDown: TBitmap;
begin
  result:=FButtonDown.Glyph;
end;

procedure TNewDBSpinEdit.CreateWnd;
begin
  inherited;
  autofit;
end;

procedure TNewDBSpinEdit.autofit;
begin
  FbuttonUP.top:=1;
  FbuttonUP.Height :=height-6;
  FButtonUp.Font:=FFontButtons;
  if FProportional then FButtonUp.Width:=FbuttonUP.Height
                  else FButtonUp.Width:=FWidthButton;
  FbuttonUP.Left := Width-FButtonUP.width-5;
  FbuttonDown.top:=1;
  FButtonDown.Font:=FFontButtons;
  FbuttonDown.Height :=height-6;
  if FProportional then FButtonDown.Width:=FButtonDown.Height
                  else FButtonDown.Width:=FWidthButton;
  FbuttonDown.Left := 1;
  Self.Perform(EM_SETMARGINS,EC_LEFTMARGIN,(FButtonDown.Width+4));
  Self.Perform(EM_SETMARGINS,EC_RIGHTMARGIN,(FButtonUP.Width+4)*$10000);
  Self.Repaint;
end;

procedure TNewDBSpinEdit.TextChanged(sender: TObject);
begin
  Autofit;
end;

procedure TNewDBSpinEdit.UpClick(Sender: TObject);
begin
  if ReadOnly then MessageBeep(0) else
  Value := Value + FIncrement;
  EditCanModify;
end;

end.[/DELPHI]


El otro

[DELPHI]//Este componente deriva de los componentes NewDbedit,´JanbuttonEdit y DbSpinEdit

unit NewDBSpinEditDouble;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, DBneweditjl , mask,  DbTables, DB, DBCtrls;

type
  TNewDBSpinEditDouble = class(TDBNewEditJL)
    private
    FButtonUp : TBitBtn;
    FButtonDown : TBitBtn;
    FWidthButton : Integer;
    FCaptionUp : String;
    FCaptionDown : String;
    FProportional : Boolean;
    FMinValue : Double;
    FMaxValue : Double;
    FIncrement : Double;
    FEditorEnabled: Boolean;
    FFontButtons : TFont;
    FDecimals  :  Integer;
    procedure SetGlyph(const Value: TBitmap);
    function  GetGlyph:TBitmap;
    procedure SetGlyphDown(const Value: TBitmap);
    function  GetGlyphDown:TBitmap;
    procedure autofit;
    procedure TextChanged(sender: TObject);
    procedure setCaptionUp(const Value:String);
    procedure setCaptionDown(const Value:String);
    procedure setWidthButton(const Value:Integer);
    procedure setProportional(const Value:Boolean);
    function  GetValue: Double;
    procedure SetValue (NewValue: Double);
    function  CheckValue (NewValue: Double): Double;
    procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
    procedure CMExit(var Message: TCMExit);  message CM_EXIT;
    procedure WMPaste(var Message: TWMPaste);  message WM_PASTE;
    procedure WMCut(var Message: TWMCut);  message WM_CUT;
    procedure setDecimals(const Value:Integer);
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure CreateWnd;override;
    function GetOnButtonUpClick: TNotifyEvent;
    function GetOnButtonDownClick: TNotifyEvent;
    procedure SetOnButtonUpClick(Value: TNotifyEvent);
    procedure SetOnButtonDownClick(Value: TNotifyEvent);
    procedure KeyPress(var Key: Char); override;
    function IsValidChar(Key: Char): Boolean; virtual;
    procedure UpClick (Sender: TObject); virtual;
    procedure DownClick (Sender: TObject); virtual;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
  published
    property OnButtonUpClick: TNotifyEvent read GetOnButtonUpClick write SetOnButtonUpClick;
    property OnButtonDownClick: TNotifyEvent read GetOnButtonDownClick write SetOnButtonDownClick;
    property GlyphUP :TBitmap read GetGlyph write SetGlyph;
    property GlyphDown :TBitmap read GetGlyphDown write SetGlyphDown;
    property CaptionUp :String  read FCaptionUp write SetCaptionUp;
    property CaptionDown :String read FCaptionDown write SetCaptionDown;
    property WidthButton :Integer read FWidthButton write SetWidthButton default 15;
    property Proportional :Boolean read FProportional write SetProportional default True;
    property MaxValue :Double  read FMaxValue    write FMaxValue;
    property MinValue :Double  read FMinValue write FMinValue;
    property Value :Double  read GetValue write SetValue;
    property Increment :Double  read FIncrement  write FIncrement;
    property FontButtons  :TFont  read FFontButtons write FFontButtons;
    property Decimals   :Integer read FDecimals   write SetDecimals;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Data Controls', [TNewDBSpinEditDouble]);
end;

procedure TNewDBSpinEditDouble.WMCut(var Message: TWMCut);
begin
  if not FEditorEnabled or ReadOnly then Exit;
  inherited;
end;
//
procedure TNewDBSpinEditDouble.WMPaste(var Message: TWMPaste);
begin
  if not FEditorEnabled or ReadOnly then Exit;
  inherited;
end;
//
procedure TNewDBSpinEditDouble.WMSize(var Message: TWMSize);
begin
  inherited;
  autofit;
end;
//
function TNewDBSpinEditDouble.CheckValue(NewValue: Double): Double;
begin
  Result := NewValue;
  if (FMaxValue <> FMinValue) then
  begin
    if NewValue < FMinValue then Result := FMinValue
    else if NewValue > FMaxValue then Result := FMaxValue;
  end;
end;
//
procedure TNewDBSpinEditDouble.CMEnter(var Message: TCMGotFocus);
begin
  if AutoSelect and not (csLButtonDown in ControlState) then
    SelectAll;
  inherited;
end;
//
procedure TNewDBSpinEditDouble.CMExit(var Message: TCMExit);
begin
  inherited;
  if CheckValue (Value) <> Value then
    SetValue (Value);
end;

constructor TNewDBSpinEditDouble.Create(AOwner: TComponent);
begin
  inherited;
  width :=121;
  height :=24;
  FCaptionDown :='q';
  FCaptionUp :='p';
  FWidthButton :=15;
  FontButtons :=TFont.Create;
  with FFontButtons do
  begin
    Name :='wingdings 3';
    Size :=7;
  end;
  FButtonUP :=TBitbtn.Create (self);
  with FButtonUP do
  begin
    width :=FWidthButton;
    height :=15;
    Font :=FFontButtons;
    top :=1;
    parent :=Self;
    Caption :=FCaptionUp;
    OnClick :=UpClick;
  end;
  FButtonDown :=TBitbtn.Create (self);
  with FButtonDown do
  begin
    width :=FWidthButton;
    height :=15;
    Font :=FFontButtons;
    top :=1;
    parent :=Self;
    Caption :=FCaptionDown;
    OnClick :=DownClick;
  end;
  FProportional :=True;
  ControlStyle := ControlStyle - [csSetCaption];
  FIncrement := 0.01;
  Text :='0,00';
  FDecimals   :=2;
end;

destructor  TNewDBSpinEditDouble.Destroy;
begin
  FButtonUP.Free;
  FbuttonDown.Free;
  FFontButtons.Free;
  inherited Destroy;
end;

procedure TNewDBSpinEditDouble.DownClick(Sender: TObject);
begin  //para bd
  if ReadOnly then MessageBeep(0)
  else
  Value := Value - FIncrement;
  EditCanModify;
end;

procedure TNewDBSpinEditDouble.setCaptionDown(const Value: String);
begin
  if FCaptionDown<>value then FCaptionDown:=Value;
  FButtonDown.Caption:=FCaptionDown;
end;

procedure TNewDBSpinEditDouble.setCaptionUp(const Value: String);
begin
  if FCaptionUp<>value then FCaptionUp:=Value;
  FButtonUp.Caption:=FCaptionUp;
end;

procedure TNewDBSpinEditDouble.setDecimals(const Value: Integer);
begin
  if (value>4) or (Value<0)  then
  begin
      MessageBeep(1000);
      ShowMessage('Los valores de este apartado estan entre 0 y 4 decimales');
  end else  if FDecimals<>value then FDecimals:=Value;
end;
//
procedure TNewDBSpinEditDouble.setProportional(const Value: Boolean);
begin
  if FProportional<>value then FProportional:=Value;
end;
//
procedure TNewDBSpinEditDouble.SetValue(NewValue: Double);
begin
  Text := FloatToStr (CheckValue (NewValue));
  EditText := Text; { força update }
  case FDecimals of
    0:Self.Text:=FormatFloat('#0',Self.Value);
    1:Self.Text:=FormatFloat('#0.0',Self.Value);
    2:Self.Text:=FormatFloat('#0.#0',Self.Value);
    3:Self.Text:=FormatFloat('#0.##0',Self.Value);
    4:Self.Text:=FormatFloat('#0.###0',Self.Value);
  end;
end;

procedure TNewDBSpinEditDouble.setWidthButton(const Value: Integer);
begin
  if FWidthButton<>value then FWidthButton:=Value;
  autofit;
end;

function TNewDBSpinEditDouble.GetOnButtonDownClick: TNotifyEvent;
begin
  Result := FButtonDown.OnClick;
end;
//
function TNewDBSpinEditDouble.GetOnButtonUpClick: TNotifyEvent;
begin
  Result := FButtonUP.OnClick;
end;
//
function TNewDBSpinEditDouble.GetValue: Double;
begin
  try
    Result := StrToFloat (Text);
  except
    Result := FMinValue;
  end;
end;
//
function TNewDBSpinEditDouble.IsValidChar(Key: Char): Boolean;
begin
  Result := (Key in [DecimalSeparator, '+', '-', '0'..'9']) or ((Key < #32) and (Key <> Chr(VK_RETURN)));
  if not FEditorEnabled and Result and ((Key >= #32) or (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then Result := False;
end;
//
procedure TNewDBSpinEditDouble.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if Key = VK_UP then UpClick (Self) else if Key = VK_DOWN then DownClick (Self);
  inherited KeyDown(Key, Shift);
end;
//
procedure TNewDBSpinEditDouble.KeyPress(var Key: Char);
begin
  if not IsValidChar(Key) then
  begin
    Key := #0;
    MessageBeep(0)
  end;
  if Key <> #0 then inherited KeyPress(Key);
end;
//
procedure TNewDBSpinEditDouble.SetOnButtonDownClick(Value: TNotifyEvent);
begin
  FButtonDown.onClick := Value;
end;
//
procedure TNewDBSpinEditDouble.SetOnButtonUpClick(Value: TNotifyEvent);
begin
  FButtonUP.onClick := Value;
end;
//
procedure TNewDBSpinEditDouble.SetGlyph(const Value: TBitmap);
begin
  FButtonUp.Glyph.assign(Value);
end;
//
procedure TNewDBSpinEditDouble.SetGlyphDown(const Value: TBitmap);
begin
  FButtonDown.Glyph.assign(Value);
end;
//
function TNewDBSpinEditDouble.GetGlyph: TBitmap;
begin
  result:=FButtonUp.Glyph;
end;
//
function TNewDBSpinEditDouble.GetGlyphDown: TBitmap;
begin
  result:=FButtonDown.Glyph;
end;
//
procedure TNewDBSpinEditDouble.CreateWnd;
begin
  inherited;
  autofit;
end;

procedure TNewDBSpinEditDouble.autofit;
begin
  FbuttonUP.top:=1;
  FbuttonUP.Height :=height-6;
  FButtonUp.Font:=FFontButtons;
  if FProportional then FButtonUp.Width:=FbuttonUP.Height
                  else FButtonUp.Width:=FWidthButton;
  FbuttonUP.Left := Width-FButtonUP.width-5;
  FbuttonDown.top:=1;
  FButtonDown.Font:=FFontButtons;
  FbuttonDown.Height :=height-6;
  if FProportional then FButtonDown.Width:=FButtonDown.Height
                  else FButtonDown.Width:=FWidthButton;
  FbuttonDown.Left := 1;
  case FDecimals of
    0:Self.Text:=FormatFloat('#0',Self.Value);
    1:Self.Text:=FormatFloat('#0.0',Self.Value);
    2:Self.Text:=FormatFloat('#0.#0',Self.Value);
    3:Self.Text:=FormatFloat('#0.##0',Self.Value);
    4:Self.Text:=FormatFloat('#0.###0',Self.Value);
  end;
  Self.Perform(EM_SETMARGINS,EC_LEFTMARGIN,(FButtonDown.Width+4));
  Self.Perform(EM_SETMARGINS,EC_RIGHTMARGIN,(FButtonUP.Width+4)*$10000);
  Self.Repaint;
end;

procedure TNewDBSpinEditDouble.TextChanged(sender: TObject);
begin
  Autofit;
end;
//
procedure TNewDBSpinEditDouble.UpClick(Sender: TObject);
begin
  if ReadOnly then MessageBeep(0) else
  Value := Value + FIncrement;
  EditCanModify;
end;

end.[/DELPHI]

Espero os sean de utilidad.
  • 0

#51 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 10 julio 2013 - 09:48

Muchas gracias Tuni y Poliburro, realmente, esperaba clasificaciones, mucho más bajas, en todos los campos y  considero que mi código es de nivel medio si acaso, además uso mucho código de compañeros y me apoyo mucho en las funciones, pero gracias, espero más votaciones.  llevo un buen puñado de años y aun hay muchas cosas que no he usado y sinceramente, no me he puesto, como son los  threads y Stored procedure ni su verdadera utilidad, yo si me tuviese que valorar, la mayoría de los campos estarían entre 5 y 6

En cuanto al aspecto del diseño, es una de mis mayores preocupaciones, e de reconocer, que no soy muy bueno en temas de interfaces, pero no se como mejorarlas, sin tener que recurrir a componentes de tercero, así que estoy abierto a consejos, ejemplos, etc, podríamos ver como aplicarían una de las pantallas del tutorial con su propio diseño. Incluso se podría abrir un nuevo tema con un tutorial sobre diseños de formularios, se que cada uno tiene su estilo, pero siempre aprendemos, en otro caso la vida sería muy aburrida.
  • 0

#52 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 13.812 mensajes
  • LocationMéxico

Escrito 10 julio 2013 - 10:33

Hola

También comparto mis "calificaciones" aunque se que no soy el mejor jurado :)

[table]
[tr][td]CATEGORÍA[/td][td]    [/td][td]CALIFICACIÓN[/td][/tr]
[tr][td][/td][td][/td][td][/td][/tr]
[tr][td]Explicaciones[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Claridad[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Código[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Tablas[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Descripciones[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Diseño[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Conceptos[/td][td]    [/td][td]10[/td][/tr]
[tr][td]Forma de aplicar los conceptos[/td][td]    [/td][td]9[/td][/tr]
[tr][td]Utilidad[/td][td]    [/td][td]10[/td][/tr]
[tr][td][/td][td][/td][td][/td][/tr]
[tr][td]Altruismo[/td][td]    [/td][td]100[/td][/tr]
[/table]

Saludos
  • 0

#53 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 10 julio 2013 - 10:44

Hola

También comparto mis "calificaciones" aunque se que no soy el mejor jurado :)

[table]
[tr][td]Altruismo[/td][td]    [/td][td]100[/td][/tr]
[/table]

Saludos


Comparto la calificación. Debe reconocerse que pocos comparten el conocimiento y se animan a exponerse ante los demás. Un reconocimiento a ello amigo desart.-
  • 0

#54 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 11 julio 2013 - 06:18

Como podéis imaginaros no voy a contar todos los secretos, pero si lo necesario, para cumplir las normativa (claro esta siempre hablo de la de mi país), así que muchas gracias por vuestras valoraciones, pero sigo pensando que aún me queda mucho que aprender.
  • 0

#55 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 16 julio 2013 - 12:42

Hola compañeros, estoy un poco liado y en breve se supone que saldré de viaje, intentare poneros algo más antes de irme, pero de momento aquí tenéis un cambio que hay que realizar en la tabla documentos, hay que añadir el campo

PORCENTAJEFINANCIADO    POR /* POR = NUMERIC(15,4) */ 


  • 0

#56 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 16 julio 2013 - 03:22

Aquí subo una pantalla de como va quedando la pantalla de documentos

Imagen Enviada

Como podéis ver me he basado, en la que utilizaba en mi anterior programa, pero esta ya empieza a tener sus diferencias y espero no llegar a las 3000 lineas de código como en la otra, se que pueden parecer muchas, pero hay que tener en cuenta todo lo que controlamos., no pondré el código, hasta que más o menos empiece a estar operativa, pero iré poniendo vistas de como va quedando y lo que empieza a tener operativo.
  • 0

#57 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 18 julio 2013 - 02:30

Bueno comencemos describiendo y poniendo el código de diferentes partes, ya que el código entero no lo pondré hasta el final.  Es muy probable que el código de una función o procedure vaya modificándose según avancemos, ya iré explicando por que. Lo ire haciendo en diferentes post, para que quede un poco más esquematizado.


Lo primero será la forma de llamarlo, ya hemos visto la function Acceso, que nos habré los form, según sea nuestro nivel de usuario, con lo que evitamos mayores controles de usuarios y tener que estar poniendo o quitando accesos y ademas gracias al nivel de usuario, también podemos ocultar o mostrar ciertos datos en nuestro form de una manera bastante simple.

Veamos la llamada a facturas

[DELPHI]procedure TFMenu.act_V_FacturasExecute(Sender: TObject);
//------------------------------------------------------------------------------
//**************************************************************[ Facturas ]****
// Gestión de facturas apto desde nivel 6
//------------------------------------------------------------------------------
begin
    VarSTipoDocumento:='FACTURA';
    FXPAF.PC.ActivePageIndex:=0;
    FXPAF.PC2.ActivePageIndex:=0;
    Acceso(6,FXPAF);
end;[/code]

como podemos ver la linea

VarSTipoDocumento:='FACTURA';


llama a una variable del formulario FXPAF, especificando el tipo de documento que es, de esta manera especificamos que documento tenemos seleccionado, ya que como os recuerdo, dentro de la tabla manejaremos 4 tipos de documentos diferentes.

Ademas nos aseguramos de colocar los Pagecontrol en página general, ya que podemos haber cambiado de una página/documento a otra al salir y volver a entrar.
  • 0

#58 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 18 julio 2013 - 02:52

Vamos ahora con el botón nuevo, este es el código
[DELPHI]procedure TFXPAF.SbNuevoClick(Sender: TObject);
//------------------------------------------------------------------------------
//*******************************************[ Creamos un nuevo registro ]******
//------------------------------------------------------------------------------

begin
  PC.ActivePageIndex:=1;
  DSPrincipal.DataSet.Insert;
  NSESerie.Value:=1;
  if DM.IBDCONFIUSARSERIEYEAR.Value='S' then
  begin
    NSESerie.Enabled:=False;
  DBNSerie.Field.Value:=Copy(IntToStr(Ano(now)),3,4);
  end else
  begin
    NSESerie.Enabled:=True;
  DBNSerie.Field.Value:=DM.IBDCONFISERIE.AsString;
  end;
  DBNNumeroDocumento.Field.value:=VerNumeroDocumento(VarSTipoDocumento,DBNSerie.Text);
  DBNSerie.SetFocus;
end;[/DELPHI]

Como podemos ver lo primero es activar el pagecontrol en datos, abrimos inserción de registro en la tabla, ponemos el TNewSpinEdit (NSESerie) en value a 1*, y pasamos a comprobar si en configuración hemos dicho de usar el año como serie, si es así cogemos los 2 últimos dígitos del año en curso, en caso contrario cogemos el valor de la serie por defecto que es la del campo Serie de la tabla de configuración, hecho esto pasamos a mostrar el número de documento perteneciente y pasamos el foco.

* este componente lo activamos o desactivamos ya que su uso es solo para poder elegir entre los tres seriales, por lo que si usamos el año como serie no nos es útil.

También hacemos un llamada a nuestra function VerNumeroDocumento, aquí su código.

[DELPHI]function TFXPAF.VerNumeroDocumento(Tipo, Serie:string):string;
//------------------------------------------------------------------------------
//*****************************************************[ VerNumeroDocumento]****
//  Funcion para este módulo
//------------------------------------------------------------------------------
var  VarILargoSerie, VarINumero:Integer;
begin
  VarILargoSerie:=Length(Serie);
  if Tipo='FACTURA' then if DM.IBDCONFINUMEROFACTURA.Text='0' then VarINumero:=1 else VarINumero:=dm.IBDCONFINUMEROFACTURA.AsInteger+1;
  if Tipo='ALBARAN' then if DM.IBDCONFINUMEROALBARAN.Text='0' then VarINumero:=1 else VarINumero:=dm.IBDCONFINUMEROALBARAN.AsInteger+1;
  if Tipo='PEDIDO'  then if DM.IBDCONFINUMEROPEDIDO.Text='0' then VarINumero:=1 else VarINumero:=dm.IBDCONFINUMEROPEDIDO.AsInteger+1;
  if Tipo='PRESUPUESTO' then if DM.IBDCONFINUMEROPRESUPUESTO.Text='0' then VarINumero:=1 else VarINumero:=dm.IBDCONFINUMEROPRESUPUESTO.AsInteger+1;
  Result:=ceros(IntToStr(VarINumero),dm.IBDCONFILAGONUMEROS.Value-VarILargoSerie)
end;
[/DELPHI]

El primer parámetro que le pasamos es el valor de nuestra variable que nos indica el tipo de documento y que la cargamos al entrar desde el menú o otro lado al documento, el segundo es la serie. Esta function lo que hace es comprobar el numerador de cada tipo de documento, si es cero cargamos como 1, en caso contrario, sera el número actual más 1, al devolvernos el resultado, nos aseguramos que nos lo devuelva relleno de ceros a la izquierda, y descontamos los espacios que va a ocupar la serie.
  • 0

#59 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 18 julio 2013 - 03:44

Pongo nueva mente la imagen del formulario para ir orientándonos

Imagen Enviada

Estamos en el campo serie, al lado esta el spinedit, que activamos o desactivamos, según nos es necesario, de aqui pasamos al número de documento que tiene los dos siguientes eventos,

[DELPHI]procedure TFXPAF.DBNNumeroDocumentoChange(Sender: TObject);
//------------------------------------------------------------------------------
//********************************************[ Cambia el  nº de documento ]****
//------------------------------------------------------------------------------
begin
  LAbel44.Caption:='[ '+Trim(DBNSerie.Text)+DBNNumeroDocumento.Text+' ]';
end;

procedure TFXPAF.DBNNumeroDocumentoExit(Sender: TObject);
// ------------------------------------------------------------------------------
// ***************************************************[ Salir del Núm. Doc. ]****
// Muestra el número de documento
// ------------------------------------------------------------------------------
begin
  if not (DsPrincipal.DataSet.State in [dsEdit]) then
  begin
    ActQuery(IBQBuscarNumeroDocumento,'Select * From DOCUMENTOS where WHERE (DOCUMENTOS.TIPODOCUMENTO = '+QuotedStr(VarSTipoDocumento)+
  ') AND (DOCUMENTOS.NUMERODOCUMENTO = '+QuotedStr(DBNNumeroDocumento.Text) +
                ') AND (DOCUMENTOS.SERIE = '+QuotedStr(DBNSerie.Text)+')');
    if not IBQBuscarNumeroDocumento.IsEmpty then
    begin
      ShowMessage('Este número de documento ya existe');
      DBNNumeroDocumento.SetFocus;
    end;
  end;
end;
[/DELPHI]

El 1º de los eventos, nuestra como queda el número de documento con la serie, el 2º evento crea una búsqueda en un querry para comprobar si el documento ya existe, para ello debemos comprobar, el tipo de documento, el número, asignado y la serie ala que pertenece, ya que recordemos, que es la misma tabla para varios documentos diferentes.
pasamos a la fecha, que al usar el componente DbNewEditJl y estar en Onlydate, controla que sea una fecha válida, nos permite que al entrar tenga la fecha actual y que podamos cambiar la fecha pulsando flecha arriba o abajo.
  • 0

#60 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 714 mensajes
  • LocationEspaña

Escrito 18 julio 2013 - 04:39

Seguimos entrando en el código del cliente, que tiene los siguientes 3 eventos

[DELPHI]
procedure TFXPAF.DBNCodigoClienteChange(Sender: TObject);
// ------------------------------------------------------------------------------
// ********************************************************[ Change Cod Cli ]****
// Para posicionar en el cliente
// ------------------------------------------------------------------------------
begin
  if FXPAF.Active then
  begin
    if DBNCodigoCliente.Text <> '' then
    begin
        ActQuery(IBQClientes, 'Select * from Clientes where Upper(CODIGO)=Upper(' + QuotedStr (DBNCodigoCliente.Text) + ')');
    end;
  end;
end;


procedure TFXPAF.DBNCodigoClienteEnter(Sender: TObject);
// ------------------------------------------------------------------------------
// ****************************************************[ entrar en clientes ]****
// ------------------------------------------------------------------------------
begin
  SBClientesClick(Sender);
end;


procedure TFXPAF.DBNCodigoClienteExit(Sender: TObject);
// ------------------------------------------------------------------------------
// *************************************************[ Salir de cód. cliente ]****
// ------------------------------------------------------------------------------
begin
  if DBNCodigoCliente.Text = '' then
  begin
    ShowMessage('Este campo no puede quedar vacio, por favor rellene l campo [Código de cliente]');
    DBNCodigoCliente.SetFocus;
  end else
  begin
  if UpperCase(DBNCodigoCliente.Text)='B' then SBBuscarClienteClick(Sender) else
    begin
      if IBQClientes.IsEmpty then
      begin
          Case Application.MessageBox(pchar(  'El cliente búscado no se encuntra, ¿desea crearlo?'),
  pchar('No se encuentra el cliente'),4+32+0) of
  6:SBNuevoClienteClick(Sender);      //Si
  7:DBNCodigoCliente.SetFocus;      //No
end;
      end else
      begin
          //Descripción del cliente
          if DBNNombreCliente.Text='' then DBNNombreCliente.Field.Value:=IBQClientesNOMBRE.Value else
          begin
            if DBNNombreCliente.Text<>IBQClientesNOMBRE.AsString then
            begin
                Case Application.MessageBox( pchar(  'El nombre de este cliente y el que tiene puesto no coinciden,            ¿desea cambiarlo por el nombre que tiene asignado este código?'),
                      pchar('Datos diferentes'),4+64+0) of
                  6:DBNNombreCliente.Field.Value:=IBQClientesNOMBRE.Value;      //Si
                end;
            end;
          end;
          //Forma de pago
          if DBNFormaPago.Text='' then DBNFormaPago.Field.Value:=IBQClientesFORMAPAGO.Value else
          begin
            if DBNFormaPago.Text<>IBQClientesFORMAPAGO.AsString then
            begin
                Case Application.MessageBox( pchar(  'La forma de pago de este cliente y el que tiene puesta no coinciden,            ¿desea cambiarlo por la que tiene asignado este código?'),
                      pchar('Datos diferentes'),4+64+0) of
                  6:DBNFormaPago.Field.Value:=IBQClientesFORMAPAGO.Value;      //Si
                end;
            end;
          end;
      end;
    end;
  end;
end;

[/DELPHI]

En el 1º evento, comprobamos que el form este activo, para evitar errores y si el código del cliente no esta vació, creamos una búsqueda con un querry, esta nos permitirá tener otros datos a la vista del cliente, tanto en los siguientes campos, como  en la pagecontrol de datos extendidos (PC3).
En el 2º evento, colocamos los datos visibles del cliente  en el PC3.
y en el 3º evento, hacemos varias cosas, primero que no se quede vació, en caso contrario si hemos puesto una B únicamente llamamos al módulo de búsqueda para el cliente, en caso contrario al de la búsqueda, comprobamos si existe, si no es asi nos avisa y posiciona nuevamente, en caso de que exista, comprueba si ya tenemos relleno uina descripción o forma de pago del cliente, si no existe la pone y si existe comprueba si cuadra con la que tiene el cliente, en caso de ser diferentes, nos da la opción de modificarla por la que tiene el cliente o mantener la que ya tiene.

Pasaríamos al Nombre del cliente, este campo ha de ser editable y guardado independiente al del la tabla clientes, imaginemos el siguiente caso, tenemos el cliente código 0 (contado) y en un día de reparto tenemos 3 clientes con este código, en cambio podríamos editar en cada documento con  Contado, Juan, Contado limpiadora Hotel XXXxxx, etc.

De aquí pasamos a  la forma de pago que pasa con lo mismo que con el nombre del cliente, el caso típico es un cliente que tiene una forma de pago x y quiere en una factura determinada pagarla de contado.

En cuanto alos botones de nuevos y búsqueda, ya los veremos más adelante.

Creo que ya es bastante por hoy.
  • 0