Ir al contenido



Foto

Programa de gestión desde 0 (Activo)


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

#21 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 19 junio 2013 - 10:01

Vaya que ha causado sensación en Face este hilo amigo mio.  :D. A todos les ha gustado. Gracias por todo el trabajo que esto conlleva.
  • 0

#22 Desart

Desart

    Advanced Member

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

Escrito 20 junio 2013 - 12:59

Yo tengo página en FaceBook y apenas entro  *-)
  • 0

#23 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.937 mensajes
  • LocationMéxico

Escrito 20 junio 2013 - 07:44

Yo tengo página en FaceBook y apenas entro  *-)


jejeje, me tomé el atrevimiento de compartirte den el grupo de Delphi solidario. :p y vaya que ha gustado tu artículo.
  • 0

#24 Desart

Desart

    Advanced Member

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

Escrito 21 junio 2013 - 06:33

Modificaciones en el módulo UPC,

Imagen Enviada

Como podéis ver hemos puesto un nuevo botón sobre un nuevo NewPanelDb, el datasource=DsPrincipal y el InverseAction=true.  Este botón lo que hace es crear un nuevo registro con los datos de la Persona de contacto activa en ese momento, creando así el nuevo registro de manera automatizada.


El código añadido

[DELPHI]

procedure TFPC.FormActivate(Sender: TObject);
//------------------------------------------------------------------------------
//********************************************[ Cuando se activa El form ]******
// Lo que queremos que haga nuestro Form Cuando se Actiba
//------------------------------------------------------------------------------
begin
    . . .
    //Se ha añadido las siguientes lineas
    PanelAux.ColorNotActive:=COLORPANELACT;
    PanelAux.ActiveColor:=COLORPANELNOACT;
end;

procedure TFPC.SpeedButtonBC4Click(Sender: TObject);
//------------------------------------------------------------------------------
//****************************************************[ Añadir a contactos ]****
// añadir al uses    UContactos    (Importante, para que funcione)
//------------------------------------------------------------------------------
begin
  try //Cremoas en contactos uno con los mismos datos que persona de contacto
      DSContactos.DataSet.Insert;
      DSContactos.DataSet.FieldByName('MODULO').Value:=DsPrincipal.DataSet.FieldByName('MODULO').value;
      DSContactos.DataSet.FieldByName('CODIGO').Value:=DsPrincipal.DataSet.FieldByName('CODIGO').value;
      DSContactos.DataSet.FieldByName('NOMBRE').Value:=DsPrincipal.DataSet.FieldByName('NOMBRE').value;
      DSContactos.DataSet.FieldByName('MOVIL').Value:=DsPrincipal.DataSet.FieldByName('MOVIL').value;
      DSContactos.DataSet.FieldByName('MAIL').Value:=DsPrincipal.DataSet.FieldByName('EMAIL').value;
    DSContactos.DataSet.Post;
    IBT.CommitRetaining;    //Donde IBT es el nombre de su Ibtrasaction, con ruta
      ShowMessage('Se ha creado un nuevo contacto con los datos de la persona de contacto actual');
  except
    on E: Exception do
    begin
        MessageBeep(1000);
        ShowMessage('Se ha producido un error y el proceso no se ha podido terminar  Unidad:[ UPC ]  Modulo:[ Grabar nuevo contacto]' + Chr(13) + Chr(13)
                  + 'Clase de error: ' + E.ClassName + Chr(13) + Chr(13)
                  + 'Mensaje del error:' + E.Message+Chr(13) + Chr(13)
                  + '    '+Chr(13) + Chr(13)
                  + 'El proceso ha quedado interrumpido');
        if DSContactos.DataSet.State in [dsEdit, dsInsert] then DSPrincipal.DataSet.Cancel;
        IBT.RollbackRetaining;    //Donde IBT es el nombre de su Ibtrasaction, con ruta
    end;
  end;
end;[/DELPHI]


También se detecto un error en el código de proveedores, os pongo el procedure con la corrección

[DELPHI]procedure TFProveedor.CambiarPagina(index: Integer; Sender: TObject);
//------------------------------------------------------------------------------
//********************************************************[ Cambiar Página ]****
// Al pulsar los botones para acceder a las pestañas
//------------------------------------------------------------------------------
var VarBActivar:Boolean;
    VarISegundoPageControlIndex:Integer;
    VarSModulo, VarSCodigo:string;
begin
      . . .
       
    case Tipo of   

        . . .

      4:begin  //personas de contacto
         
          // Cambiar la linea ActQuery(DM.IBQContactos,'SELECT * FROM CONTACTOS WHERE (CONTACTOS.MODULO = '+QuotedStr(VarSModulo)+') AND (CONTACTOS.CODIGO = '+QuotedStr(VarSCodigo)+')'); 
          //  Por

          ActQuery(DM.IBQPersonasContacto,'SELECT * FROM PC WHERE (PC.MODULO = '+QuotedStr(VarSModulo)+') AND (PC.CODIGO = '+QuotedStr(VarSCodigo)+')');
          if not DM.IBQPersonasContacto.IsEmpty then
          begin
          DBNavigator1.DataSource:=DM.DSIBQPersonasContacto;
          end else DM.IBQPersonasContacto.Active:=False;
          VarISegundoPageControlIndex:=1;
        end;
   
        . . .

    end;
end;[/DELPHI]
  • 0

#25 Desart

Desart

    Advanced Member

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

Escrito 21 junio 2013 - 06:48

Módulo empleados

Imagen Enviada

No seguiré comentando sobre las pestañas ya tratadas en post anteriores ya que son lo mismo

Mejoras que hacer en los otros módulos incorporadas a este, al Dsprincipal en su evento DSPrincipalDataChange, se ha añadido, para que las tablas auxiliares cambien cuando cambiamos de datos, siempre y cuando no este en edición o inserción.

Hay cosa nuevas como el modulo de registros de histórico y poco más.

como siempre el código completo en https://gist.github....onymous/5831048
  • 0

#26 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.090 mensajes
  • LocationRepública Dominicana

Escrito 21 junio 2013 - 07:55

Saludos.

@Desart, esto puede verse como una pequeña molestía, en la pantalla personas de contactos tiene un error ortografico, dice: Frcha de Nacimiento.

Nuevamente te reitero el agredecimiento por el aporte.

Keep Moving Foward!!
  • 0

#27 Desart

Desart

    Advanced Member

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

Escrito 21 junio 2013 - 08:51

Muchas gracias, lo corregiré mañana, seguro que habrá o hay más faltas de ortografía.
  • 0

#28 Desart

Desart

    Advanced Member

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

Escrito 22 junio 2013 - 02:23

Vamos con dos tablas auxiliares importantes

CREATE TABLE STOCK (
    ID                INTEGER NOT NULL,
    CODIGOPRODUCTO    T20 /* T20 = VARCHAR(20) */,  //Código del producto
    LOTE              T20 /* T20 = VARCHAR(20) */,  //Lote del producto
    CANTIDADDEENTRADA  INTEGER,  //Cantidad de entrada, aquí se ira sumando según las entradas (1)
    EXISTENCIAS        INTEGER,  //Las Existencias que quedan (2)
    FECHAENTRADA      DATE,  //Fecha de la primera entrada , aunque luego sigan entrado más cantidades
    CADUCIDAD          DATE,  //Fecha en la que se caduca el producto(3)
    ACTIVO            LOG /* LOG = CHAR(1) */ (4)
);



Es de suma importancia  saber que en este caso el stock lo hacemos por Lote, con lo que saber el total de existencias reales, seria la suma de de todos los lotes que estén en activo y cuya EXISTENCIAS  sean mayor o igual a 1, quiero decir que las existencias del 16-5 es todas las que estén en la tabla Stock con los siguientes datos
 
    CODIGOPRODUCTO='16-5', ACTIVO='S' y EXISTENCIAS>=1

lo que nos puede dar varios registros.
     

(1) En ciertos tipos de fabricación, las mercancías no se sacan todas a la vez, por eso este campo, lo que hace es incrementar, según hagamos entradas

(2) Aquí debemos tener mucho ojo, es las Existencias (el verdadero Stock), debe indicarnos en todo momento la cantidad real de artículos que quedan , es importante esta cantidad normalmente disminuye, pero hay que tener en cuenta que si hemos echo un documento (albarán, Factura, Etc) que afecta al stock, debemos controlar sus modificamos
veamos diferentes ejemplos  pongamos que inicialmente sacamos 10 vajillas

Primero tener en cuenta que si las existencias llegan a 0 debemos marcar como no activo (4)

Caso 1º  Salida de 10 vajillas 5L código del producto 16-5 Lote 130001  Seria CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS-10

Caso 2º  Salida de 10 vajillas 5L código del producto 16-5 Lote 130001(6) y 130002(4)  ya que del primer lote nos quedan solo 6, los cambios en la tabla stock serían

              CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS-6, ACTIVO='N'

                Y

              CODIGOPRODUCTO='16-5', LOTE=130002, EXISTENCIAS=EXISTENCIAS-4

Caso 3º Sobre el que teníamos con salida de 10 vajillas 5L código del producto 16-5 Lote 130001  lo modificamos y en vez de 10, subimos a 12 los cambios serían


              CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS-2  (ya que habíamos descontado anteriormente 10 por ello debemos controlar al editar la cantidad anterior siendo el cálculo resultante el siguiente CantiadaADescontar:=CantidadActual-CantidadAnterior; )

Caso 4º Sobre el que teníamos con salida de 10 vajillas 5L código del producto 16-5 Lote 130001  lo modificamos y en vez de 10, Bajamos a 8 los cambios serían

              CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS+2  (ya que habíamos descontado anteriormente 10 por ello debemos controlar al editar la cantidad anterior siendo el cálculo resultante el siguiente CantiadaADescontar:=CantidadActual-CantidadAnterior;  en este caso cantidad actual sería mayor con los que nos daría -2 de resultado al ser el resultado negativo entonces sumamo)

Caso 5º Sobre el que teníamos con salida de 10 vajillas 5L código del producto 16-5 Lote 130001  lo modificamos Cambiamos el Lote por 130004 los cambios serían

              CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS+10
              CODIGOPRODUCTO='16-5', LOTE=130004, EXISTENCIAS=EXISTENCIAS-10

Caso 6º  Eliminamos el que teníamos con salida de 10 vajillas 5L código del producto 16-5 Lote 130001  lo  cambios serían

            CODIGOPRODUCTO='16-5', LOTE=130001, EXISTENCIAS=EXISTENCIAS+10
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Si existiesen varios lotes debemos tener Stringrid, dividiendo los lotes con sus cantidades y un edit por Row, para poder poner la nueva cantidad, su estructura seria más o menos como sigue

Lote, Fecha, Caducidad, Existencias,  Activo (en caso de que sea 'N' no nos permitirá números positivos, pero si recuperar, si este fuese el caso debemos añadir a existencias y cambiar ACTIVO de 'N' a 'S')

(3) Si el producto es caduco aquí ira su Fecha de caducidad, como un lote sólo puede tener una única fecha de producción, sólo habrá una fecha de caducidad y repito a un número de lote asignado, es una única fabricación.

(4) El Campo ACTIVO tendrá los valores S o N y es de vital importancia, por defecto cuando damos una entrada, si no existe en la tabla STOCK, lo creamos con ACTIVO='S', salvo que indicamos lo contrario, el motivo para esta r en 'N' son los siguientes, que en la mayoría de los casos no tiene que ver con las Existencias

1º) Existencias a 0, en este caso no es lógico que cada vez que entramos en el artículo, o en uno de los documentos de venta siguiera apareciendo si no hay artículo de donde extraer.
2º) Un lote a retirar, podríamos detectar un problema en un lote y tener que retirarlo, para evitar que siga habiendo salidas, lo marcamos como no activo
3º) Es un producto de uso interno y por lo tanto no se vende, tato para uso del personal, como creado para usar en la fabricación/uso de otros productos

Siento el coñazo, pero es muy importante que este tema quede bien claro, para no tener problemas de trazabilidad y existencias reales. Si queda alguna duda, prefiero dedicarle más tiempo y aclararlo ahora que más adelante cuando el programa este más avanzado.

Espero no haberme dejado alguno de los casos posibles, si es así, por favor comunicármelo.
  • 0

#29 Desart

Desart

    Advanced Member

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

Escrito 22 junio 2013 - 02:29

La otra tabla

CREATE TABLE ENTRADAS (
    ID              INTEGER NOT NULL,
    CODIGOPRODUCTO  T20 /* T20 = VARCHAR(20) */,  //Código del producto
    LOTE            T20 /* T20 = VARCHAR(20) */,  //Lote asignado
    FECHA          DATE,  //Fecha de la entrada y no del lote
    CADUCIDAD      DATE,  //Fecha de la caducidad, esta si la recogemos de la tabla LOTES
    CANTIDAD        INTEGER,  //Cantidad
    CODIGOOPERARIO  T20 /* T20 = VARCHAR(20) */  //Código del empleado
);;


Como podemos una tabla sencilla, que nos permite tener un buen control de las diferentes entradas.
  • 0

#30 Desart

Desart

    Advanced Member

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

Escrito 22 junio 2013 - 02:33

Se me olvidaba, por supuesto es importante que si el producto es caduco quiero decir con esto que tiene fecha de caducidad y no esta en blanco, debe controlar que la fecha actual es menor que la de la caducidad y como no si el caso es que la fecha es mayor que la de la caducidad debemos poner ACTIVO='N'
  • 0

#31 Desart

Desart

    Advanced Member

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

Escrito 22 junio 2013 - 05:38

Como estaba harto de que este componente me diese problemas con el tema de la negrita, lo he vuelto a modificar y aquí lo dejo ya corregido

[DELPHI]{ ****************************************************************** }
{                                                                    }
{  VCL component TDBIBCheckbox                                      }
{                                                                    }
{  Dbcheckbox para Firebird permitiendo Cambiae El Value según Check }
{                                                                    }
{  Code generated by Component Create for Delphi                    }
{                                                                    }
{  Generated from untitled component definition                    }
{  on 23 March 2012 at 15:59                                        }
{                                                                    }
{  Copyright © 2012 by J.L.G.T.                                    }
{                                                                    }
{ ****************************************************************** }

unit TDbIbchkbox;

interface

uses WinTypes, WinProcs, Messages, SysUtils, Classes, Controls,
    Forms, Graphics, Stdctrls, DbTables, DB, DBCtrls, TypInfo, Dialogs;

type
  TDBIBCheckbox = class(TCheckBox)
    private
      { Private fields of TDBIBCheckbox }
        FUpperCaseChk : Boolean;
        FBoldCheck: Boolean;
        FValueChecked : String;
        FValueUnChecked : String;
        { Pointer to application's OnChange handler, if any }
        FOnChange : TNotifyEvent;
        FDataLink : TFieldDataLink;
        FBoldfixed: Boolean;
        { Private methods of TDBIBCheckbox }
        { Method to set variable and property values and create objects }
        procedure AutoInitialize;
        { Method to free any objects created by AutoInitialize }
        procedure AutoDestroy;
        function GetDataField : String;
        procedure SetDataField(Value : String);
        function GetDataSource : TDataSource;
        procedure SetDataSource(Value : TDataSource);
        procedure SetUppercaseChk(value:Boolean);
        function GetUpperCaseChk : Boolean;
        procedure SetValueChecked(value:string);
        procedure SetValueUnChecked(value:string);
        procedure ActiveChange(Sender : TObject);
        procedure DataChange(Sender : TObject);
        procedure EditingChange(Sender : TObject);
        procedure UpdateData(Sender : TObject);
        procedure SetBoldCheck(Value:Boolean);
        procedure SetBoldfixed(Value:Boolean);      //Permite que sea fija o no la negrita
    protected
      { Protected fields of TDBIBCheckbox }

      { Protected methods of TDBIBCheckbox }
        { Method to generate OnChange event }
        procedure Change(Sender : TObject); virtual;
        procedure Click; override;
        procedure KeyPress(var Key : Char); override;
        procedure Loaded; override;

    public
      { Public fields and properties of TDBIBCheckbox }
      { Public methods of TDBIBCheckbox }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;

    published
      { Published properties of TDBIBCheckbox }
        { Cuando Cambia el Checked }
        property OnChange : TNotifyEvent read FOnChange write FOnChange;
        property OnClick;
        property OnDblClick;
        property OnDragDrop;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseMove;
        property OnMouseUp;
        { Campo de la base de datos }
        property DataField : String read GetDataField write SetDataField;
        { Datasource unido a la base de datos }
        property DataSource : TDataSource    read GetDataSource write SetDataSource;
        { Asegura que Se grave en mayusculas }
        property UpperCaseChk : Boolean read GetUpperCaseChk    write SetUppercaseChk  default True;
        { Valor de cuando Esta Checked=true }
        property ValueChecked : String        read FValueChecked      write SetValueChecked;
        { Valor de cuando no esta Checked (Checked=False) }
        property ValueUnChecked : String      read FValueUnChecked    write SetValueUnChecked;
        property BoldCheck:Boolean            read FBoldCheck        write SetBoldCheck  default True;
        property Boldfixed:Boolean            read FBoldfixed        write SetBoldfixed  default True;

        Procedure DBICHKNOT;
  end;

procedure Register;

implementation


Function GetTipoCampo (DataSet :TDataSet; Index :Integer) :String;
Begin
    Result := GetEnumName (TypeInfo (TFieldType),
    Integer (DataSet.Fields [Index].DataType));
End;

procedure Register;
begin
    RegisterComponents('InterBase', [TDBIBCheckbox]);
end;

{ Method to set variable and property values and create objects }
procedure TDBIBCheckbox.AutoInitialize;
begin
    FDataLink := TFieldDataLink.Create;
    FBoldCheck:=True;
    FUpperCaseChk:=True;
    FBoldfixed:=True;
    with FDataLink do
    begin
          { Assign handlers }
          OnDataChange := DataChange;
          OnUpdateData := UpdateData;
          OnEditingChange := EditingChange;
          OnActiveChange := ActiveChange;
    end;
end; { of AutoInitialize }

{ Method to free any objects created by AutoInitialize }
procedure TDBIBCheckbox.AutoDestroy;
begin
    FDataLink.Free;
end; { of AutoDestroy }

function TDBIBCheckbox.GetDataField : String;
begin { Return the FDataLink.FieldName property }
    Result := FDataLink.FieldName;
end;

procedure TDBIBCheckbox.SetDataField(Value : String);
begin { Set the FDataLink.FieldName property }
    FDataLink.FieldName := Value;
end;

function TDBIBCheckbox.GetDataSource : TDataSource;
begin { Return the FDataLink.DataSource property }
    Result := FDataLink.DataSource;
end;

procedure TDBIBCheckbox.SetDataSource(Value : TDataSource);
begin { Set the FDataLink.DataSource property }
    FDataLink.DataSource := Value;
end;

function TDBIBCheckbox.GetUpperCasechk : Boolean;
begin
Result := FUpperCaseChk;
end;

{ Method to generate OnChange event }
procedure TDBIBCheckbox.Change(Sender : TObject);
begin
    if Assigned(FOnChange) then FOnChange(Sender);
end;

{ Override OnClick handler from TCheckBox }
procedure TDBIBCheckbox.Click;
begin { Call method of parent class }
    if FDataLink.Editing then  //Comprueba si se esta editando el registro
    begin
          FDataLink.Modified;
          if fDataLink.field <> nil then
          begin
            if (Checked) then
            begin
              if FUpperCaseChk then fDataLink.field.Value := UPperCase(FValueChecked)
                                else fDataLink.field.Value := FValueChecked;
              if (FBoldCheck) then
              begin
              if (fBoldfixed=False)  then Self.Font.Style:=[fsBold]
                                        else Self.Font.Style:=[];
              end;
            end else
            begin
              if FUpperCaseChk=False then fDataLink.field.Value := UpperCase(FValueChecked)
                                    else  fDataLink.field.Value := FValueUnChecked;
            end;
          end;
          inherited Click;
//      end;
    end;
end;

{ Override OnKeyPress handler from TCheckBox }
procedure TDBIBCheckbox.KeyPress(var Key : Char);
begin { Call method of parent class }
    inherited KeyPress(Key);
end;

constructor TDBIBCheckbox.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
    AutoInitialize;
    FUpperCaseChk:=True;
    FValueChecked:='SI';
    FValueUnChecked:='NO';
    { Code to perform other tasks when the component is created }
end;

procedure TDBIBCheckbox.DataChange(Sender : TObject);
begin
    if fDataLink.field <> nil then
    begin
      if FUpperCaseChk then
      begin
          if UpperCase(FDataLink.Field.AsString)=UpperCase(FValueChecked) then Checked:=true
                                                                          else Checked:=False;
      end else
      begin
          if FDataLink.Field.Value=FValueChecked then Checked:=true
                                                else Checked:=False;
      end;
      if (Checked) then
      begin
              if (FBoldCheck) then
              begin
              if (fBoldfixed=False)  then Self.Font.Style:=[fsBold]
                                        else Self.Font.Style:=[];
              end;
      end;
      if Assigned(FOnChange) then FOnChange(Sender);
    end;
end;

destructor TDBIBCheckbox.Destroy;
begin
    AutoDestroy;
    inherited Destroy;
end;

procedure TDBIBCheckbox.EditingChange(Sender : TObject);
begin
    //
end;

procedure TDBIBCheckbox.Loaded;
begin
    inherited Loaded;
end;

procedure TDBIBCheckbox.ActiveChange(Sender : TObject);
const
    IntFieldTypes = [ftSmallInt, ftInteger, ftWord];
begin
    if DataField = '' then  Exit;
end;

procedure TDBIBCheckbox.UpdateData(Sender : TObject);
begin
    if fDataLink.field <> nil then
    begin
  if (Checked) then
      begin
        if FUpperCaseChk then fDataLink.field.Value := UPperCase(FValueChecked)
                          else fDataLink.field.Value := FValueChecked;
        if (FBoldCheck) then
        begin
            if (fBoldfixed=False)  then Self.Font.Style:=[fsBold]
                                    else Self.Font.Style:=[];
        end;
      end else
      begin
      if FUpperCaseChk=False then fDataLink.field.Value := UpperCase(FValueChecked)
      else  fDataLink.field.Value := FValueUnChecked;
    end;
end;
end;

procedure TDBIBCheckbox.SetUppercaseChk(value: Boolean);
begin
    if value<>FUpperCaseChk then FUpperCaseChk:=value;
end;

procedure TDBIBCheckbox.SetValueChecked(value: string);
begin
      if value<>FValueChecked then
      begin
        if FDataLink.Field<>nil then
        begin
        if Length(value)>FDataLink.Field.Size then ShowMessage('El ValueCheck [ '+Value+' ] contiene más caracteres de los '+#13+#10+
                        'permitidos, que es de  [ '+IntToStr(FDataLink.Field.Size)+' ] caracteres')
                                                  else FValueChecked:=value;
        end else FValueChecked:=value;
      end;
end;
procedure TDBIBCheckbox.SetBoldCheck(Value: Boolean);
begin
    if FBoldCheck<>value then FBoldCheck:=Value;

end;

procedure TDBIBCheckbox.SetBoldfixed(Value: Boolean);
begin
  if FBoldfixed<>Value then FBoldfixed:=Value;
  if FBoldfixed then Self.Font.Style:=[fsBold] else Self.Font.Style:=[]
end;

procedure TDBIBCheckbox.SetValueUnChecked(value: string);
begin
      if value<>FValueUnChecked then
      begin
        if FDataLink.Field<>nil then
        begin
        if Length(value)>FDataLink.Field.Size then ShowMessage('El ValueUnCheck [ '+Value+' ] contiene más caracteres de los '+#13+#10+
                        'permitidos, que es de  [ '+IntToStr(FDataLink.Field.Size)+' ] caracteres')
                                                  else FValueUnChecked:=value;
        end else FValueUnChecked:=value;
      end;
end;

Procedure TDBIBCheckbox.DBICHKNOT;
begin
  if  FDataLink.Editing=true then
  begin
        FDataLink.Field.Value:=FValueUnChecked;
  end;
end;

end.[/DELPHI]
  • 0

#32 Desart

Desart

    Advanced Member

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

Escrito 23 junio 2013 - 05:36

El Módulo de Lotes

Imagen Enviada

Es importante darse cuenta que el nuevo número de lote siempre lo cogemos de configuración evitando de esta manera que se puedan duplicar los número de lotes

Tenemos que poner un apartado en el programa para cerrar el año, ya que este nos permite poner el contador de lotes y de otros si es necesario a 0

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

Veamos un detalle de como va cambiando el módulo UbusquedaFP

[DELPHI]
procedure TFbusquedaFP.FormActivate(Sender: TObject);
//------------------------------------------------------------------------------
//********************[ Cargamos los Campos de la tabla  en el ComboBox  ]******
//------------------------------------------------------------------------------
begin
  //Comprobamos si el combo esta vacio cargamos los datos
if Edbusqueda.Text='' then ActQuery(IBQBusqueda,'Select * From '+VarSTabla);
  if IBQBusqueda.IsEmpty then
  begin
    ShowMessage('No hay datos para buscar o mostrar');
    SB_SalirClick(Sender);
  end else
  begin
  if comboCampos.Items.Count=0 then DataSource1.DataSet.GetFieldNames(comboCampos.items);
    if VarSTabla='FPAGOS' then
    begin
      CarGarGrid(0,'ID',50,'ID');
      CarGarGrid(1,'CODIGO',130,'Código');
      CarGarGrid(2,'FORMAPAGO',260,'Forma de pago');
      CarGarGrid(3,'DIASPRESENTACION',130,'Días de presentación');
      CarGarGrid(4,'DIASCOBRO',130,'Días de cobro');
      CarGarGrid(5,'NUMERODEPAGOS',130,'Número de pagos');
    end;
    if VarSTabla='FABRICABLES' then
    begin
      CarGarGrid(0,'ID',50,'ID');
      CarGarGrid(1,'CODIGO',130,'Código');
      CarGarGrid(2,'PRODUCTO',520,'Producto');
    end;
    if VarSTabla='EMPLEADOS' then
    begin
      CarGarGrid(0,'ID',50,'ID');
      CarGarGrid(1,'CODIGO',130,'Código');
      CarGarGrid(2,'NOMBRE',520,'Nombre');
      CarGarGrid(3,'PUESTO',130,'Puesto de trabajo');
      CarGarGrid(4,'AGENTE ',130,'Es Agente o comercial');
    end;
  end;
end;

procedure TFbusquedaFP.FormClose(Sender: TObject; var Action: TCloseAction);
//------------------------------------------------------------------------------
//****************************************************************[ Cerrar ]****
//------------------------------------------------------------------------------
begin
if (VarSNomMod='PROVEEDORES')  and (FProveedor.DsPrincipal.DataSet.State in [dsEdit,dsInsert]) then
  begin
      FProveedor.DBNCodigoFormaPago.Field.Value:=IBQBusqueda.FieldByName('FORMAPAGO').AsString; //Ponemos la forma de pago elegida
    FProveedor.DBNCodigoFormaPago.SetFocus;                        //Damos el foco nuevamente al campo
  end;
  if (VarSNomMod='LOTESF')  and (FLotes.DsPrincipal.DataSet.State in [dsEdit,dsInsert]) then
  begin
      FLotes.DBNCodFabricable.Field.Value:=IBQBusqueda.FieldByName('CODIGO').AsString; //Ponemos el código elegido
    FLotes.DBNCodFabricable.SetFocus;                        //Damos el foco nuevamente al campo
  end;
  if (VarSNomMod='LOTESE')  and (FLotes.DsPrincipal.DataSet.State in [dsEdit,dsInsert]) then
  begin
      FLotes.DBNCodEmpleado.Field.Value:=IBQBusqueda.FieldByName('CODIGO').AsString; //Ponemos el código elegido
    FLotes.DBNCodEmpleado.SetFocus;                        //Damos el foco nuevamente al campo
  end;
  Button3Click(Sender);
  QuerryOC(IBQBusqueda);
  comboCampos.Items.Clear;
end;

procedure TFbusquedaFP.FormShow(Sender: TObject);
//------------------------------------------------------------------------------
//****************************************************************[ OnShow ]****
// Adaptamos el título del form a la tabla que usamos
//------------------------------------------------------------------------------
begin
if VarSTabla='FPAGOS' then Caption:='Búsquedas en Fomas de pago';  //Caption del Form
  if VarSTabla='EMPLEADOS' then Caption:='Búsquedas en Empleados';  //Caption del Form
  if VarSTabla='FABRICABLES' then Caption:='Búsquedas en Fabricables';  //Caption del Form
end;

[/code]

como podemos ver usamos el mismo módulo, para diferentes llamadas, e incluso cunado las llamadas son desde el mismo módulo, pero para diferente Tablas ('LOTESF' y 'LOTESE')

El próximo módulo es el de entradas, que tiene muchas similitudes con este pero también con el de Stock, realmente es el paso intermedio entre ambos.

Que paséis un buen Domingo.
  • 0

#33 Desart

Desart

    Advanced Member

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

Escrito 24 junio 2013 - 07:33

Bueno le toca al modulo de entradas

Imagen Enviada

y el código como siempre en https://gist.github....onymous/5850255

Como se puede apreciar, se va complicando la cosa  :| , os que yo soy muy complicado como prefierán :D:D:D
  • 0

#34 jaumet

jaumet

    Member

  • Miembros
  • PipPip
  • 10 mensajes

Escrito 25 junio 2013 - 02:54

Gracias por este magnífico tutorial!  (y)
  • 0

#35 Desart

Desart

    Advanced Member

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

Escrito 06 julio 2013 - 03:23

Primero que nada pedir disculpas por haberme atrasado, tanto en seguir, pero estoy preparando la documentación y el material de un curso para una nueva Fabrica de productos de limpieza (es a lo que me dedico ahora a montar fabricas de productos de limpieza por toda España y otros países) y claro me lleva bastante tiempo preparar un informe por producto, más todo lo demás.

Vamos con el módulo de Regulación de Stock, debería ser un módulo con doble nivel de acceso, el nivel de usuario, en mi caso un 8 y además solicito la clave de usuario nuevamente, aún así se debería al grabar los datos, grabar , en un log, ini, XLS o tabla, tanto el usuario, fecha, hora, cantidad anterior, nueva cantidad y motivo, ya que este apartado afectara seriamente a la trazabilidad, en el ejemplo pongo el resumen pero no lo hago pero creo importante este punto.

Dicho lo dicho aquí la imagen

Imagen Enviada

y aquí el código https://gist.github....onymous/5939351
  • 0

#36 Desart

Desart

    Advanced Member

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

Escrito 06 julio 2013 - 03:36

Lo siguiente será empezar con nuestras tablas de documentos (para presupuestos, pedidos, albaranes y facturas), usare el sistema de 3 tablas, la maestro, la detalle y la de lotes, creando sólo las 3  para los cuatro tipos de documentos, la estructura ya os la pondré, pero será fundamental, que las tres tendrán tres campos comunes que ademas las hará maestro-detalle entre las 3, los campos serán Documento(Presupuesto, pedido, etc.), número del documento y serie.

El apartado de documentos lo haré una vez (Facturas, el más completo), y explicare los respectivos cambios aplicables a los otros formatos, pero como comprenderéis, es un apartado enorme, por lo que tendré que ir haciéndolo por partes, empezare, por la facturación tal cual, los lotes, , trazabilidad y regulación de stock, estarán incluidos en estas partes, gestión de comisiones, etc.

Según nos vayamos introduciendo, tendremos que ir creando otras tablas a las que haremos referencia y las iremos comentando, una vez terminado el proceso, nos quedara, los módulos de convención de documentos, rutas y cartas de porte, etc. y podremos dar por terminado el tutorial, salvo que queráis un poco más, tendríamos que verlo.

HE dicho que no pondré como hacer los informes (impresiones) ya que cada uno elegirá su método, pero creo que podre mostraros por lo menos dos, una factura y comentaros, que debe llevar y por que y una carta de portes.
  • 0

#37 Desart

Desart

    Advanced Member

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

Escrito 06 julio 2013 - 03:44

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 :D :D :D o nivelar :rolleyes:
  • 0

#38 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 06 julio 2013 - 09:04

Amigo, yo te otorgo un 10 en todo, porque como dirían en España, "Te has puesto por delante de un toro muy grande".
Más que debilidades, quiero resaltar una fortaleza que percibo en ti, tienes una excelente "macrovisión del problema", tienes bien claras las partes que lo conforman y la manera de afrontar la solución para cada parte del problema, en otras palabras eres un muy buen analista.

Un cordial saludo.


  • 0

#39 Desart

Desart

    Advanced Member

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

Escrito 06 julio 2013 - 09:23

Gracias Wilson, pero creo que no creo que el código se puede simplificar, que el diseño es mejorable, etc.  pero muchas gracias por tu apoyo
  • 0

#40 Desart

Desart

    Advanced Member

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

Escrito 07 julio 2013 - 03:33

Empezamos con la tabla documentos, como es una tabla para nuestros tipos de documentos, usaremos los identificadores X=Presupuestos, P=Pedidos, A=Albaranes y F=Facturas para indicar en que documento lo usaremos.

CREATE TABLE DOCUMENTOS (
    ID                      INTEGER NOT NULL,
    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)
    CODIGOCLIENTE           T20 NOT NULL /* T20 = VARCHAR(20) */,  //.....................Código del cliente (XPAF)
    DESCRIPCIONCLIENTE      T80 /* T80 = VARCHAR(80) */,  //......................1  (XPAF)
    IDDIRECCIONES          INTEGER NOT NULL,  //.....................el campo id de la tabla direcciones ya tratada, al tener la posibilidad de varias direcciones  (XPAF)
    CODIGOAGENTE            T20 NOT NULL /* T20 = VARCHAR(20) */,  //.....................código del agente o comercial  (XPAF)
    DESCRIPCIONAGENTE      T80 /* T80 = VARCHAR(80) */,  //.....................1  (XPAF)
    FECHA                  DATE NOT NULL,  //.....................Fecha de emisión de la factura  (XPAF)
    NUMERODECOBRO          T20 /* T20 = VARCHAR(20) */,  //.....................Numero (código) de tablas COBROS (Pendiente) donde registraremos la forma en que se nos ha pagado  (F)
    COBRADO                 LOG NOT NULL /* LOG = CHAR(1) */,  //.....................(S/N)  indica si la factura ya esta cobrada, al tener el campo NUMERODECOBRO podemos ver más detalles      (F)
    NUMERORUTA              T20 /* T20 = VARCHAR(20) */,  //.....................Numero (código) de tablas RUTAS (Pendiente) donde registraremos las rutas de entrega  (PAF)
    FECHAENTREGA            DATE,  //.....................Fecha de la entrega, si cambiamos la ruta, cambiara la fecha (2)  (PAF)
    FORMADEPAGO            T20 NOT NULL /* T20 = VARCHAR(20) */,  //.....................Código de la taba forma de pago  (XPAF)
    DESCRIPCIONFORMADEPAGO  T80 /* T80 = VARCHAR(80) */,  //...................../1 (XPAF)
    NUMEROFINANCIADO        T20 /* T20 = VARCHAR(20) */,  //.....................Numero (código) de tablas FINANCIADO (Pendiente) donde registraremos las financiación de pagos  (PAF)
    TOTALFINANCIADO        POR /* POR = NUMERIC(15,4) */,  //.....................Total del dinero financiado, no tiene por que ser el total de la factura
    NUMERORETENCIONES      T20 /* T20 = VARCHAR(20) */,  //...................../Numero (código) de tablas RETENCIONES (Pendiente) donde registraremos las retenciones hechas a clientes (PAF)
    TOTALRETENCIONES        POR /* POR = NUMERIC(15,4) */,  //...................../Importe de las retenciones
    PORCENTAJERETENCIONES  POR /* POR = NUMERIC(15,4) */,  //.....................porcentaje de retenciones aplicadas, puede variar a la que ya tiene aplicada el cliente (3) (F)
    TOTALCOMISIONES        POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de comisiones  (XPAF). (4)
    NUMEROPROTECCIONDATOS  INTEGER NOT NULL  //.....................Elegimos entre el 1 y el 3 de la tabla CONFIGURACION donde 1 =LDPD1 ... 3=LDPD3, que texto debemos poner  (XPAF)
    CAMPOLIBRE              T80 /* T80 = VARCHAR(80) */,  //.....................Campo libre ya que la ley va cambiando o podemos necesitar  (XPAF)
    MODIFICACIONES          INTEGER NOT NULL,  //.....................Número de veces que se ha modificado la factura, nos permite controlar si se ha alterado (5)  (XPAF)
    ESTADO                  T40 /* T40 = VARCHAR(40) */,  //...................../Estado actual de la factura (Pendiente, cobrada, nula (5), etc) (XAPF)
    NUMERORELACIONFACTURAS  T20 /* T20 = VARCHAR(20) */,  //...................../Numero (código) de tablas RELACIONFACTURAS (Pendiente) donde agruparemos facturas de un cliente (F)
    SERIERELACIONFACTURAS  T3 /* T3 = VARCHAR(3) */,  //.....................Serie de la relación de facturas (F)
    SUBTOTAL               POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Subtotal del importe (XPAF)
    TOTALDESCUENTOS        POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Importe del total de descuentos  (XPAF)
    TOTALPESO              POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total del peso perteneciente al documento (XPAF)
    TOTALIMPUESTOS          POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de impuestos (XPAF)
    TOTALIMPUESTO1         POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de impuestos tipo 1 (XPAF)
    TOTALIMPUESTO2          POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de impuestos tipo 2 (XPAF)
    TOTALIMPUESTO3         POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de impuestos tipo 3 (XPAF)
    TOTALIMPUESTO4         POR NOT NULL /* POR = NUMERIC(15,4) */,  //.....................Total de impuestos tipo 4 (XPAF)
    MININOTA               VARCHAR(150)  //...................../Campo de 150 caracteres, ya que las notas las haremos a través de la tabla NOTAS  (XPAF)
);



1) las descripciones es para posibles cambios sin tener que editar o crear un registro nuevo
              ejemplo:  Código cliente= 0  Descripción general 'Contado'  campo DESCRIPCIONCLIENTE  'Contado - (trabajador taller Antonio)'

2) Si ponemos la ruta para hoy i por cualquier motivo no se puede entregar en la fecha prevista, la pondremos en la siguiente hoja de ruta, por lo que debemos controlar el cambio                 
    de la fecha de entrega

3) El cliente puede solicitar que le aumentes  o disminuyas el porcentaje de retenciones en una factura, únicamente. Estará presente en PAF, pero se puede variar y determina sólo
    el de la factura, por defecto coge el del cliente, que es lo habitual.

4)  Las comisiones irán a su tabla de comisiones, donde pondremos de que documento viene, de aquí podremos realizar el pago de comisiones, recordar que el pago de comisiones
    hay que hacerle la retención para el pago de Hacienda.

5) Las Facturas no se pueden borrar, ya que afectan a varios departamentos y alteran la aplicación, no quiero decir que no se puedan, pero no se deben bajo ningún concepto,
    ejemplo : tenemos la factura 120001, que es el mismo valor actual de nuestro numerador de facturas y nos damos cuenta al terminar, de que esta mal, claro que podríamos
    borrarla y modificar el numerador, pero si el numerador ya va por el 120025, o otro cualquiera, borramos la factura y queda un salto en el registro de facturación, motivo de
    auditoria en hacienda, si no queda bien explicado y suele pasar, cuando trabajamos todo el año con cientos o miles de facturas, quien se acuerda de una determinada, de hace 
    x meses.

---------------------------------------------------------------------------------------------------------------------------------------------------------


Como podemos ver  se va complicando la cosa, es posible que se me olvide algún campo, así que ya iremos viendo.
  • 0