Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 17-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Analizando Maestro-Detalle

Hola amigos del Foro. Ahora solicitando su ayuda para analizar un código:
Uso: Delphi6, Firebird 2.0, IBX.

Explico:
Tengo un formulario para REGISTRAR datos con el concepto Maestro-Detalle. Les envío el código que estoy tratando de que funcione, pero marca el siguiente error:

Cita:
Project Archivo.exe raised exception class EDatabaseError with message 'Field 'LECHER' must have a value'. Process stopped. Use Step or Run to continue.
Entiendo lo q me dice...al campo LECHER le falta el dato ya que es parte de la clave primaria y no le esta llegando. Por cierto les comento los campos de la llave primaria de ambos tablas (MAestro y Detalle)

MAESTRO:
m_Lecher numeric(10)
m_mes numeric(2)
m_anio numeric(4)

DETALLE
m_Lecher numeric(10)
m_mes numeric(2)
m_anio numeric(4)
d_pbl_tipo numeric(3)
d_pbl_causa numeric(3)

Este error me lo muestra al dar click sobre el boton "btnAgregar" (Evento OnClick)
Código Delphi [-]
procedure TfrmPBLCaptura.btnAgregarClick(Sender: TObject);
begin
    btnGuardar.Enabled:=True;
//    AbrirDetalle(Sender);
    RegNuevo:=1;
    dsPBLDetalle.Append;
    dsPBLDetalle.FieldByName('LECHER').AsString:=edLecheria.Text;
    dsPBLDetalle.FieldByName('pbl_mes').AsInteger:=cbxMes.ItemIndex+1;
    dsPBLDetalle.FieldByName('pbl_anio').AsString:=mskAnio.Text;
    dsPBLDetalle.FieldByName('id_pbl_tipo').AsInteger:=cbxTipoPBL.KeyValue;
    dsPBLDetalle.FieldByName('id_pbl_causa').AsInteger:=cbxCausasPBL.KeyValue;
    dsPBLDetalle.FieldByName('pbl_det_dias').AsString:=edDias.Text;
    dsPBLDetalle.FieldByName('pbl_det_diferencia').AsString:=edDiferencia.Text;
    dsPBLDetalle.Post;
    AbrirDetalleGrid(Sender);
    cbxTipoPBL.SetFocus;
end;

Exactamente en la linea del dsPBLDetalle.Append es donde marca el error....algo estoy haciendo mal.

Detalles de los componentes: Tengo 2 DataSet (dsPBLMaestro y dsPBLDetalle), en el detalle tengo enlazado en su propiedad DataSource el TDataSource que tiene el Maestro, por lo tanto según lo he consultado, para grabar el registro (si todo esta bien), lo hago de esta manera:
Código Delphi [-]
procedure TfrmPBLCaptura.btnGuardarClick(Sender: TObject);
begin
     try
         dsPBLDetalle.DataSource:=nil;
         ModDatos.dbFluida.ApplyUpdates( [dsPBLMaestro, dsPBLDetalle] );
         dsPBLDetalle.DataSource:=dSoPBLMaestro;
         ModDatos.trsFluida.CommitRetaining;
     except
       on E: Exception do
       begin
          Application.MessageBox('El o los registros no pueden ser grabados en este momento, probablemente el registro que estas consultando esta siendo editado por otro usuario','Error', mb_ok+mb_IconError);
          ShowMessage(E.Message);
          ModDatos.trsFluida.RollbackRetaining;
       end;
     end;
     mskAnio.SetFocus;
end;

Primeramente lo que hago es llenar EL MAESTRO, q cuando doy click sobre el botón (btnRegistrarDetalle) hace esto:
Código Delphi [-]
procedure TfrmPBLCaptura.btnRegistrarDetalleClick(Sender: TObject);
begin
      if sBtnPresionado>0 then
      begin
          btnRegistrarDetalle.Enabled:=False;
          dsPBLMaestro.FieldByName('id_origen_reporte').AsInteger:=sBtnPresionado;
          dsPBLMaestro.Post;
          AbrirTipoPBL_y_Causas(Sender); //Abro un catalogo para ser usado al momento del registro del detalle
          btnAgregar.Enabled:=True;
      end Else
      begin
          Application.MessageBox('Debes seleccionar un ORIGEN DE REPORTE','Advertencia',mb_Ok+mb_IconExclamation);
      end;
end;

Posteriormente lleno los campos para el detalle y doy click sobre el botón "btnAgregar" y hace esto en su evento OnClick:
Código Delphi [-]
procedure TfrmPBLCaptura.btnAgregarClick(Sender: TObject);
begin
    btnGuardar.Enabled:=True;
//    AbrirDetalle(Sender);
    RegNuevo:=1;
    dsPBLDetalle.Append; // AQUI MARCA EL ERROR
    dsPBLDetalle.FieldByName('LECHER').AsString:=edLecheria.Text;
    dsPBLDetalle.FieldByName('pbl_mes').AsInteger:=cbxMes.ItemIndex+1;
    dsPBLDetalle.FieldByName('pbl_anio').AsString:=mskAnio.Text;
    dsPBLDetalle.FieldByName('id_pbl_tipo').AsInteger:=cbxTipoPBL.KeyValue;
    dsPBLDetalle.FieldByName('id_pbl_causa').AsInteger:=cbxCausasPBL.KeyValue;
    dsPBLDetalle.FieldByName('pbl_det_dias').AsString:=edDias.Text;
    dsPBLDetalle.FieldByName('pbl_det_diferencia').AsString:=edDiferencia.Text;
    dsPBLDetalle.Post;
    AbrirDetalleGrid(Sender);
    cbxTipoPBL.SetFocus;
end;

No sé donde me estoy equivocando...agradecere mucho alguien q me ayude a localizar lo q tengo mal??...

CÓDIGO COMPLETO:
Código Delphi [-]
unit pblCaptura;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Mask, ExtCtrls, ComCtrls, Buttons, DBCtrls, Grids,
  DBGrids, DB, IBCustomDataSet, IBQuery, Provider, DBClient, DBLocal,
  DBLocalI;

type
  TfrmPBLCaptura = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    Label2: TLabel;
    cbxMes: TComboBox;
    mskAnio: TMaskEdit;
    Label3: TLabel;
    edLecheria: TEdit;
    Panel2: TPanel;
    Panel11: TPanel;
    dsPBLMaestro: TIBDataSet;
    dsPBLDetalle: TIBDataSet;
    dSoPBLMaestro: TDataSource;
    dSoPBLDetalle: TDataSource;
    qryCausas: TIBQuery;
    qryConsultarLech: TIBQuery;
    dSoConsultarLech: TDataSource;
    qryLocal: TIBQuery;
    dSoLocal: TDataSource;
    Panel13: TPanel;
    GroupBox1: TGroupBox;
    sBtnBeneficiarios: TSpeedButton;
    sBtnEncargado: TSpeedButton;
    sBtnPromotor: TSpeedButton;
    sBtnDiconsa: TSpeedButton;
    sBtnOtroOrigen: TSpeedButton;
    GroupBox2: TGroupBox;
    DBMemo1: TDBMemo;
    btnRegistrarDetalle: TBitBtn;
    dSoTipoPBL: TDataSource;
    qryTipoPBL: TIBQuery;
    Panel4: TPanel;
    Label4: TLabel;
    Label5: TLabel;
    cbxTipoPBL: TDBLookupComboBox;
    cbxCausasPBL: TDBLookupComboBox;
    dSoCausas: TDataSource;
    btnGuardar: TBitBtn;
    qryTipoPBLID_PBL_TIPO: TSmallintField;
    qryTipoPBLPBL_TIPO_DESCRIPCION: TIBStringField;
    qryDetalleRegsGrid: TIBQuery;
    dSoDetalleRegsGrid: TDataSource;
    qryCausasID_PBL_TIPO: TSmallintField;
    qryCausasID_PBL_CAUSA: TSmallintField;
    qryCausasPBL_CAUSA_DESCRIP_CORTA: TIBStringField;
    qryCausasPBL_CAUSA_DESCRIP_LARGA: TMemoField;
    qryInventarios: TIBQuery;
    qryInventariosVENTA_INVENTARIOS: TIntegerField;
    qryInventariosVTA_LIBRO: TIntegerField;
    dSoInvenarios: TDataSource;
    qryInventariosDIFER: TLargeintField;
    IBClientDataSet1: TIBClientDataSet;
    Panel3: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    pnlDesabasto: TPanel;
    Label6: TLabel;
    edDias: TEdit;
    pnlLlenado: TPanel;
    GroupBox4: TGroupBox;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    DBEdit1: TDBEdit;
    DBEdit2: TDBEdit;
    edDiferencia: TEdit;
    TabSheet2: TTabSheet;
    DBGrid1: TDBGrid;
    Panel5: TPanel;
    GroupBox3: TGroupBox;
    DBMemo2: TDBMemo;
    btnAgregar: TBitBtn;
    btnEliminar: TBitBtn;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure sBtnBeneficiariosClick(Sender: TObject);
    procedure sBtnEncargadoClick(Sender: TObject);
    procedure sBtnPromotorClick(Sender: TObject);
    procedure sBtnDiconsaClick(Sender: TObject);
    procedure sBtnOtroOrigenClick(Sender: TObject);
    procedure cbxOperacionCloseUp(Sender: TObject);
    procedure AbrirCausas(Sender: TObject);
    procedure cbxOperacionChange(Sender: TObject);
    procedure Panel1Enter(Sender: TObject);
    procedure Panel1Exit(Sender: TObject);
    procedure btnRegistrarDetalleClick(Sender: TObject);
    procedure cbxTipoPBLExit(Sender: TObject);
    procedure cbxTipoPBLCloseUp(Sender: TObject);
    procedure AbrirTipoPBL_y_Causas(Sender: TObject);
    procedure btnAgregarClick(Sender: TObject);
    procedure btnGuardarClick(Sender: TObject);
    procedure AbrirDetalleGrid(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure LimpiarCampos(Sender: TOBject);
    procedure OcultarPaneles(Sender: TObject);
    procedure Panel4Enter(Sender: TObject);
    procedure edLecheriaExit(Sender: TObject);
    procedure AbrirDetalle(Sender: TObject);
    procedure pnlLlenadoEnter(Sender: TObject);
    procedure DBGrid1CellClick(Column: TColumn);
    procedure btnEliminarClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    nTag,sBtnPresionado,RegNuevo:integer;
  end;

var
  frmPBLCaptura: TfrmPBLCaptura;

implementation
uses ModuloDatos,pblProblematicas;
{$R *.dfm}

procedure TfrmPBLCaptura.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
    frmPBL.FormShow(Sender);
    Action:=caFree;
end;

procedure TfrmPBLCaptura.sBtnBeneficiariosClick(Sender: TObject);
begin
     GRoupBox1.Caption:='Origen del Reporte: BENEFICIARIOS';
     sBtnPresionado:=1;
end;

procedure TfrmPBLCaptura.sBtnEncargadoClick(Sender: TObject);
begin
     GRoupBox1.Caption:='Origen del Reporte: ENCARGADO DE TIENDA';
     sBtnPresionado:=2;
end;

procedure TfrmPBLCaptura.sBtnPromotorClick(Sender: TObject);
begin
     GRoupBox1.Caption:='Origen del Reporte: PROMOTOR SOCIAL';
     sBtnPresionado:=3;
end;

procedure TfrmPBLCaptura.sBtnDiconsaClick(Sender: TObject);
begin
     GRoupBox1.Caption:='Origen del Reporte: PERSONAL DE DICONSA';
     sBtnPresionado:=4;
end;

procedure TfrmPBLCaptura.sBtnOtroOrigenClick(Sender: TObject);
begin
     GRoupBox1.Caption:='Origen del Reporte: OTRO';
     sBtnPresionado:=5;
end;

procedure TfrmPBLCaptura.cbxOperacionCloseUp(Sender: TObject);
begin
{     GroupBox6.Caption:=cbxOperacion.Items.Strings[cbxOperacion.ItemIndex];
     case cbxOperacion.ItemIndex of
       0: begin
             pnlOperacion_1.Visible:=False;
             pnlOperacion_2.Visible:=False;
          end;
       1: begin
             pnlOperacion_1.Visible:=True;
             pnlOperacion_2.Visible:=False;
             pnlOperacion_1.Align:=alClient;
          end;
       2: begin
             pnlOperacion_1.Visible:=False;
             pnlOperacion_2.Visible:=True;
             pnlOperacion_2.Align:=alClient;
          end;
     end;}
end;

procedure TfrmPBLCaptura.AbrirCausas(Sender: TObject);
begin
//     rGrupoCausas.Items.Clear;
     qryCausas.Close;
     qryCausas.ParamByName('id_pbl').AsInteger:=nTag;
     qryCausas.Open;
     qryCausas.First;
end;

procedure TfrmPBLCaptura.cbxOperacionChange(Sender: TObject);
begin
        cbxOperacionCloseUp(Sender);
end;

procedure TfrmPBLCaptura.Panel1Enter(Sender: TObject);
begin
//    mskFechaRegistro.Text:='';

    ModDatos.trsFluida.Active:=False;
    ModDatos.trsFluida.StartTransaction;

    LimpiarCampos(Sender);
    OcultarPaneles(Sender);
    RegNuevo:=0;
    btnGuardar.Enabled:=False;
    btnAgregar.Enabled:=False;
    btnEliminar.Enabled:=False;
    PageControl1.ActivePageIndex:=0;
    qryTipoPBL.Close;
    qryCausas.Close;
    qryConsultarLech.Close;

    dsPBLMaestro.Close;
    dsPBLDetalle.Close;

    sBtnPresionado:=0;
    sBtnBeneficiarios.Enabled:=False;
    sBtnEncargado.Enabled:=False;
    sBtnPromotor.Enabled:=False;
    sBtnDiconsa.Enabled:=False;
    sBtnOtroOrigen.Enabled:=False;

    sBtnBeneficiarios.Down:=False;
    sBtnEncargado.Down:=False;
    sBtnPromotor.Down:=False;
    sBtnDiconsa.Down:=False;
    sBtnOtroOrigen.Down:=False;

    btnRegistrarDetalle.Enabled:=False;
//    btnAgregar.Enabled:=False;
end;

procedure TfrmPBLCaptura.Panel1Exit(Sender: TObject);
begin
    if not( (mskAnio.Text='') or (cbxMes.Items.Text='') or (edLecheria.Text='') ) then
    begin
         sBtnBeneficiarios.Enabled:=True;
         sBtnEncargado.Enabled:=True;
         sBtnPromotor.Enabled:=True;
         sBtnDiconsa.Enabled:=True;
         sBtnOtroOrigen.Enabled:=True;
         btnRegistrarDetalle.Enabled:=True;

         dsPBLMaestro.Close;
         dsPBLMaestro.ParamByName('anio').AsString:=mskAnio.Text;
         dsPBLMaestro.ParamByName('mes').AsInteger:=cbxMes.ItemIndex+1;
         dsPBLMaestro.ParamByName('lecher').AsString:=edLecheria.Text;
         dsPBLMaestro.Open;
         if dsPBLMaestro.IsEmpty then
         begin
              dsPBLMaestro.Append;
              dsPBLMaestro.FieldByName('lecher').AsString:=edLecheria.Text;
              dsPBLMaestro.FieldByName('pbl_anio').AsString:=mskAnio.Text;
              dsPBLMaestro.FieldByName('pbl_mes').AsInteger:=cbxMes.ItemIndex+1;
         end Else
         begin
              dsPBLMaestro.Edit;
              PageControl1.ActivePageIndex:=1;
              case dsPBLMaestro.FieldByName('id_origen_reporte').AsInteger of
                  1 : begin
                        sBtnBeneficiarios.Down:=True;
                        sBtnPresionado:=1;
                      end;
                  2 : begin
                        sBtnEncargado.Down:=True;
                        sBtnPresionado:=2;
                      end;
                  3 : begin
                        sBtnPromotor.Down:=True;
                        sBtnPresionado:=3;
                      end;
                  4 : begin
                        sBtnDiconsa.Down:=True;
                        sBtnPresionado:=4;
                      end;
                  5 : begin
                        sBtnOtroOrigen.Down:=True;
                        sBtnPresionado:=5;
                      end;
              end;
              AbrirDetalleGrid(Sender);
         end;
         AbrirDetalle(Sender);
    end Else
    begin
        Application.MessageBox('Ingrese datos validos para el registro de una problematica','Error', mb_Ok+mb_IconError);
        mskAnio.SetFocus;
    end;
end;

procedure TfrmPBLCaptura.btnRegistrarDetalleClick(Sender: TObject);
begin
      if sBtnPresionado>0 then
      begin
          btnRegistrarDetalle.Enabled:=False;
          dsPBLMaestro.FieldByName('id_origen_reporte').AsInteger:=sBtnPresionado;
          dsPBLMaestro.Post;
          AbrirTipoPBL_y_Causas(Sender);
          btnAgregar.Enabled:=True;
      end Else
      begin
          Application.MessageBox('Debes seleccionar un ORIGEN DE REPORTE','Advertencia',mb_Ok+mb_IconExclamation);
      end;
end;

procedure TfrmPBLCaptura.AbrirDetalle(Sender: TObject);
begin
    dsPBLDetalle.Close;
    dsPBLDetalle.ParamByName('lecher').AsString:=edLecheria.Text;
    dsPBLDetalle.ParamByName('mes').AsInteger:=cbxMes.ItemIndex+1;
    dsPBLDetalle.ParamByName('anio').AsString:=mskAnio.Text;
    dsPBLDetalle.Open;
end;

procedure TfrmPBLCaptura.cbxTipoPBLExit(Sender: TObject);
begin
    if qryTipoPBL.Active then
    begin
        qryCausas.Close;
        qryCausas.ParamByName('id_pbl').AsInteger:=cbxTipoPBL.KeyValue;
        qryCausas.Open;
        qryCausas.FetchAll;
    end;
end;

procedure TfrmPBLCaptura.cbxTipoPBLCloseUp(Sender: TObject);
begin
     PageControl1.ActivePageIndex:=0;
     case cbxTipoPBL.KeyValue of
     1:begin
           pnlDesabasto.Visible:=True;
       end;
     2:begin
           pnlLlenado.Visible:=True;
       end;
     end;
end;

procedure TfrmPBLCaptura.AbrirTipoPBL_y_Causas(Sender: TObject);
begin
      qryTipoPBL.Close;
      qryTipoPBL.Open;
      qryTipoPBL.FetchAll;
end;

procedure TfrmPBLCaptura.btnAgregarClick(Sender: TObject);
begin
    btnGuardar.Enabled:=True;
//    AbrirDetalle(Sender);
    RegNuevo:=1;
    dsPBLDetalle.Append;
    dsPBLDetalle.FieldByName('LECHER').AsString:=edLecheria.Text;
    dsPBLDetalle.FieldByName('pbl_mes').AsInteger:=cbxMes.ItemIndex+1;
    dsPBLDetalle.FieldByName('pbl_anio').AsString:=mskAnio.Text;
    dsPBLDetalle.FieldByName('id_pbl_tipo').AsInteger:=cbxTipoPBL.KeyValue;
    dsPBLDetalle.FieldByName('id_pbl_causa').AsInteger:=cbxCausasPBL.KeyValue;
    dsPBLDetalle.FieldByName('pbl_det_dias').AsString:=edDias.Text;
    dsPBLDetalle.FieldByName('pbl_det_diferencia').AsString:=edDiferencia.Text;
    dsPBLDetalle.Post;
    AbrirDetalleGrid(Sender);
    cbxTipoPBL.SetFocus;
end;

procedure TfrmPBLCaptura.btnGuardarClick(Sender: TObject);
begin
     try
         dsPBLDetalle.DataSource:=nil;
         ModDatos.dbFluida.ApplyUpdates( [dsPBLMaestro, dsPBLDetalle] );
         dsPBLDetalle.DataSource:=dSoPBLMaestro;
         ModDatos.trsFluida.CommitRetaining;
     except
       on E: Exception do
       begin
          Application.MessageBox('El o los registros no pueden ser grabados en este momento, probablemente el registro que estas consultando esta siendo editado por otro usuario','Error', mb_ok+mb_IconError);
          ShowMessage(E.Message);
          ModDatos.trsFluida.RollbackRetaining;
       end;
     end;
     mskAnio.SetFocus;
end;

procedure TfrmPBLCaptura.AbrirDetalleGrid(Sender: TObject);
begin
     qryDetalleRegsGrid.Close;
     qryDetalleRegsGrid.ParamByName('lecher').AsString:=edLecheria.Text;
     qryDetalleRegsGrid.ParamByName('mes').AsInteger:=cbxMes.ItemIndex+1;
     qryDetalleRegsGrid.ParamByName('anio').AsString:=mskAnio.Text;
     qryDetalleRegsGrid.Open;
end;

procedure TfrmPBLCaptura.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   case Key of
      VK_ESCAPE: mskAnio.SetFocus;
   end;
end;

procedure TfrmPBLCaptura.LimpiarCampos(Sender: TObject);
begin
    edDias.Text:='';
    edDiferencia.Text:='';
end;

procedure TfrmPBLCaptura.OcultarPaneles(Sender: TObject);
begin
    pnlDesabasto.Visible:=False;
    pnlLlenado.Visible:=False;
end;

procedure TfrmPBLCaptura.Panel4Enter(Sender: TObject);
begin
     OcultarPaneles(Sender);
     LimpiarCampos(Sender);
end;

procedure TfrmPBLCaptura.edLecheriaExit(Sender: TObject);
begin
    qryConsultarLech.Close;
    qryConsultarLech.ParamByName('lecher').AsString:=edLecheria.Text;
    qryConsultarLech.Open;
    if qryConsultarLech.IsEmpty then
    begin
        Application.MessageBox('El numero de lecheria ingresado no existe en catálogo!','Error',mb_ok+mb_IconError);
        edLecheria.SetFocus;
    end;
end;

procedure TfrmPBLCaptura.pnlLlenadoEnter(Sender: TObject);
begin
     qryInventarios.Close;
     qryInventarios.ParamByName('lecher').AsString:=edLecheria.Text;
     qryInventarios.ParamByName('mes').AsInteger:=cbxMes.ItemIndex+1;
     qryInventarios.ParamByName('anio').AsString:=mskAnio.Text;
     qryInventarios.Open;
     if qryInventarios.IsEmpty then
     begin
         Application.MessageBox('No existen inventarios registrados para esta lecheria','Aviso',mb_Ok+mb_IconExclamation);
         edDiferencia.SetFocus;

     end Else
     begin
         edDiferencia.Text:=qryInventarios.fieldByName('difer').AsString;
     end;

end;

procedure TfrmPBLCaptura.DBGrid1CellClick(Column: TColumn);
begin
    btnEliminar.Enabled:=True;
    btnGuardar.Enabled:=True;
end;

procedure TfrmPBLCaptura.btnEliminarClick(Sender: TObject);
begin
     if Application.MessageBox('Estas seguro de ejectuar el proceso','Pregunta',mb_OkCancel+mb_IconQuestion)=idOk then begin
         dsPBLDetalle.Delete;
         dsPBLDetalle.ApplyUpdates;
         ModDatos.trsFluida.Commit;
     end;
end;

end.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!

Última edición por mRoman fecha: 17-05-2018 a las 20:25:57.
Responder Con Cita
  #2  
Antiguo 17-05-2018
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Dado el error que mencionas, lo primero que revisaría es el estado de la propiedad Required del TField en cuestión:
Código Delphi [-]
   dsPBLDetalle.FieldByName('LECHER').Required := False;
Si creaste los campos persistentes podes cambiar el valor desde el Object Inspector.

Lo siguiente no tiene que ver con el error, pero es mas seguro hacer:
Código Delphi [-]
  ...
  try
    dsPBLDetalle.DataSource := nil;
    try
      ModDatos.dbFluida.ApplyUpdates([dsPBLMaestro, dsPBLDetalle]);
    finally
     dsPBLDetalle.DataSource := dSoPBLMaestro;
    end;
    ModDatos.trsFluida.CommitRetaining;
 except on E: Exception do
 begin
   Application.MessageBox(' ...

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 17-05-2018 a las 21:20:10.
Responder Con Cita
  #3  
Antiguo 17-05-2018
orodriguezca orodriguezca is offline
Miembro
 
Registrado: ene 2009
Posts: 221
Poder: 16
orodriguezca Va por buen camino
Cita:
Empezado por ecfisa Ver Mensaje
Dado el error que mencionas, lo primero que revisaría es el estado de la propiedad Required del TField en cuestión:
Código Delphi [-]
   dsPBLDetalle.FieldByName('LECHER').Required := False;
Coincido con la solución, pero nunca he visto este error en un método Append o Insert, sino en el método Post. Quizas el error no se está generando en el dataset de Detalle sino en el Maestro. Yo colocaría un ShowMessage en el evento beforePost tanto del Maestro como del Detalle con fines de depuración para verificar cual de los dataset es el que genera el error.
Responder Con Cita
  #4  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Gracias ecfisa (...tu nombre es Daniel?).

Cambiaré el código a la forma como me sugieres...

Gracias por tus comentarios y tu tiempo.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #5  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Cita:
Empezado por orodriguezca Ver Mensaje
Coincido con la solución, pero nunca he visto este error en un método Append o Insert, sino en el método Post. Quizas el error no se está generando en el dataset de Detalle sino en el Maestro. Yo colocaría un ShowMessage en el evento beforePost tanto del Maestro como del Detalle con fines de depuración para verificar cual de los dataset es el que genera el error.
Si....tienes razón, verificaré en cual de los 2 dataset me da el error...ya que en ambas tablas (Maestro y Detalle) tengo definido el mismo nombre de campo "LECHER"...por lo tanto no sé en cual es....

Analizando lo q comentas, pudiera ser que el problema me lo este dando en el DataSet Maestro, ya que en cuanto llega al Append del DataSet Detalle, marca el error...es decir NI SIQUIERA ME DEJA ASIGNARLE EL DATO AL CAMPO LECHER lo que corresponde !!.

Verifico y les comento....

p.d. Aclaración de los nombres de campo q comparti al inicio del hilo....estos inician con "m_" para maestro y "d_" para el detalle, lo hice asi para fines de ilustracion, pero el campo real es LECHER, sin "m_" y "d_", respectivamente.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!

Última edición por mRoman fecha: 18-05-2018 a las 00:25:20.
Responder Con Cita
  #6  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Cita:
Empezado por ecfisa Ver Mensaje
Hola.

Dado el error que mencionas, lo primero que revisaría es el estado de la propiedad Required del TField en cuestión:
Código Delphi [-]
   dsPBLDetalle.FieldByName('LECHER').Required := False;
Si creaste los campos persistentes podes cambiar el valor desde el Object Inspector.
Este campo forma parte de la llave primaria, definido como NOT NULL desde la base de datos, por lo tanto si requiere el dato.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #7  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Cita:
Empezado por orodriguezca Ver Mensaje
Coincido con la solución, pero nunca he visto este error en un método Append o Insert, sino en el método Post. Quizas el error no se está generando en el dataset de Detalle sino en el Maestro. Yo colocaría un ShowMessage en el evento beforePost tanto del Maestro como del Detalle con fines de depuración para verificar cual de los dataset es el que genera el error.
Y que le pondría dentro del ShowMessage???...Para mostrar que?...lo q va asignar al campo LECHER?...

Algo como esto:

Código Delphi [-]
   Showmessage(edLecheria.text);

o esto otro:
Código Delphi [-]
   Showmessage(dsPBLMaestro.FieldByName('LECHER').AsString); //Esto también en el detalle por supuesto.

En este ultimo talvez no muestre nada....

Bueno dejen hago pruebas.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #8  
Antiguo 18-05-2018
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.
Cita:
Empezado por mRoman Ver Mensaje
Este campo forma parte de la llave primaria, definido como NOT NULL desde la base de datos, por lo tanto si requiere el dato.
Ah, correcto... y supongo que ya controlaste que tenga un valor ingresado. Pensé en esa columna por que era la que estaba señalizada en el mensaje de error.
Pero también podría ser cualquier otra que tenga su propiedad Required en True la que esté disparando la excepción y, como señaló orodriguezca, el problema se esté generando en otro lado.

Esa situación podría producirse cuando, por ejemplo, generas los campos en el IBDataSet y luego modificas (quitas) la restricción NOT NULL desde la bd. En ese caso tal vez te funcione volver a gererar las sentencias SQL de los IBDataSets que actuan en la relación.

Realmente es muy difícil tratar de reproducir la situación de error dado lo largo del código y los múltiples elementos que entran en juego.


Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #9  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Cita:
Empezado por ecfisa Ver Mensaje
Hola.

Ah, correcto... y supongo que ya controlaste que tenga un valor ingresado. Pensé en esa columna por que era la que estaba señalizada en el mensaje de error.
Pero también podría ser cualquier otra que tenga su propiedad Required en True la que esté disparando la excepción y, como señaló orodriguezca, el problema se esté generando en otro lado.

Esa situación podría producirse cuando, por ejemplo, generas los campos en el IBDataSet y luego modificas (quitas) la restricción NOT NULL desde la bd. En ese caso tal vez te funcione volver a gererar las sentencias SQL de los IBDataSets que actuan en la relación.

Realmente es muy difícil tratar de reproducir la situación de error dado lo largo del código y los múltiples elementos que entran en juego.


Saludos
Ya hice las pruebas, hice lo q me sugierieron, revisé con el ShowMessage que el objeto edLecheria, tuviera datos en su propiedad Text y sí, si tiene.

Realice la verificacion de los campos del Maestro y el Detalle, dentro del DataSet respectivo y los campos que pertenecen a la PrimaryKey de la tabla, tenian en su propiedad Required=True, se lo cambie a False y ya no marco error al momento de realizar el Post al dataset del detalle, ahora lo marca en el ApplyUpdates.

Código Delphi [-]
procedure TfrmPBLCaptura.btnGuardarClick(Sender: TObject);
begin
     try
         dsPBLDetalle.DataSource:=nil;
         try
           ModDatos.dbFluida.ApplyUpdates( [dsPBLMaestro, dsPBLDetalle] );
         finally
           dsPBLDetalle.DataSource:=dSoPBLMaestro;
         end;
         ModDatos.trsFluida.CommitRetaining;
     except
       on E: Exception do
       begin
          Application.MessageBox('El o los registros no pueden ser grabados en este momento, probablemente el registro que estas consultando esta siendo editado por otro usuario','Error', mb_ok+mb_IconError);
          ShowMessage(E.Message);
          ModDatos.trsFluida.RollbackRetaining;
       end;
     end;
     mskAnio.SetFocus;
end;

Código:
 'validation error for column LECHER, value "*** null ***"'.
Quiere decir q entonces no se esta almacenando nada cuando se ejecuta este código:
Código Delphi [-]
procedure TfrmPBLCaptura.btnAgregarClick(Sender: TObject);
begin
    btnGuardar.Enabled:=True;
//    AbrirDetalle(Sender);
    RegNuevo:=1;
    dsPBLDetalle.Append;
        dsPBLDetalle.FieldByName('LECHER').AsString:=edLecheria.Text; // Como que aqui no esta haciendo la asignacion....raro!
    dsPBLDetalle.FieldByName('pbl_mes').AsInteger:=cbxMes.ItemIndex+1; //Por lo tanto aqui tampoco
    dsPBLDetalle.FieldByName('pbl_anio').AsString:=mskAnio.Text;
    dsPBLDetalle.FieldByName('id_pbl_tipo').AsInteger:=cbxTipoPBL.KeyValue;
    dsPBLDetalle.FieldByName('id_pbl_causa').AsInteger:=cbxCausasPBL.KeyValue;
    dsPBLDetalle.FieldByName('pbl_det_dias').AsString:=edDias.Text;
    dsPBLDetalle.FieldByName('pbl_det_diferencia').AsString:=edDiferencia.Text;
    dsPBLDetalle.Post;
    AbrirDetalleGrid(Sender);
    cbxTipoPBL.SetFocus;
end;

(Lo marcado con color son los campos de la llave primaria de la tabla DETALLE)

Sinceramente esta es la primera vez que trabajo Maestro-Detalle usando el enlace entre los dataset, mediante la propiedad DataSource.

Ahora por donde va la cosa???...

Gracias por su tiempo !. Saludos
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #10  
Antiguo 18-05-2018
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Cuando la estructura del algoritmo se complejiza y estamos en una situación nueva, es muy útil crearse un ejemplo simple para cotejar con lo echo.

Te hice uno basado en Firebird+IBX, espero te sirva de guía.

Tablas:
Código SQL [-]
SET TERM ^ ;

CREATE TABLE MAESTRO(
  ID         INTEGER NOT NULL,
  TEXT       VARCHAR(30) CHARACTER SET ISO8859_1 COLLATE ES_ES_CI_AI,
  CONSTRAINT PK_MAESTRO PRIMARY KEY(ID)

)^

CREATE TABLE DETALLE (
  ID         INTEGER NOT NULL,
  TEXT       VARCHAR(30) CHARACTER SET ISO8859_1 COLLATE ES_ES_CI_AI,
  MAESTRO_ID INTEGER NOT NULL,
  CONSTRAINT PK_DETALLE PRIMARY KEY(ID),
  CONSTRAINT FK_DETALLE FOREIGN KEY(MAESTRO_ID) REFERENCES MAESTRO(ID)
) ^

SET TERM ; ^

DataModule:
Código Delphi [-]
unit Unit2;

interface

uses SysUtils, Classes, DB, IBCustomDataSet, IBDatabase;

type
  TDataModule1 = class(TDataModule)
    IBDatabase1: TIBDatabase;
    IBTransaction1: TIBTransaction;
    tbMaster: TIBDataSet;
    tbDetail: TIBDataSet;
    dsMaster: TDataSource;
    dsDetail: TDataSource;
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
  private
  public
  end;

var
  DM: TDataModule1;

implementation {$R *.dfm}

procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
  IBTransaction1.DefaultDatabase := IBDatabase1;

  // Master table
  tbMaster.Database := IBDatabase1;
  tbMaster.SelectSQL.Text  := 'SELECT * FROM MAESTRO';
  tbMaster.RefreshSQL.Text := 'SELECT ID, TEXT FROM MAESTRO WHERE ID = :ID';
  tbMaster.ModifySQL.Text  := 'UPDATE MAESTRO SET ID  = :ID, TEXT = :TEXT WHERE ID = :OLD_ID';
  tbMaster.InsertSQL.Text  := 'INSERT INTO MAESTRO(ID, TEXT) VALUES(:ID, :TEXT)';
  tbMaster.DeleteSQL.Text  := 'DELETE FROM MAESTRO WHERE ID = :OLD_ID';
  dsMaster.DataSet         := tbMaster;
  tbMaster.CachedUpdates   := True;

  // Detail table
  tbDetail.Database := IBDatabase1;
  tbDetail.SelectSQL.Text  := 'SELECT * FROM DETALLE WHERE MAESTRO_ID = :ID';
  tbDetail.RefreshSQL.Text := 'SELECT ID, TEXT, MAESTRO_ID FROM DETALLE WHERE ID = :ID';
  tbDetail.ModifySQL.Text  := 'UPDATE DETALLE SET ID = :ID, TEXT = :TEXT, MAESTRO_ID = :MAESTRO_ID WHERE ID = :OLD_ID';
  tbDetail.InsertSQL.Text  := 'INSERT INTO DETALLE(ID, TEXT, MAESTRO_ID) VALUES(:ID, :TEXT, :MAESTRO_ID)';
  tbDetail.DeleteSQL.Text  := 'DELETE FROM DETALLE WHERE ID = :OLD_ID';
  tbDetail.DataSource      := dsMaster;
  dsDetail.DataSet         := tbDetail;
  tbDetail.CachedUpdates   := True;
end;

procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
  tbDetail.CachedUpdates := False;
  tbMaster.CachedUpdates := False;
end;
end.
(el DataModule deberá ser el primero en Auto-create forms )

Prueba:
Código Delphi [-]
unit Unit1;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, 
  DBCtrls, Grids, DBGrids, StdCtrls;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    GroupBox2: TGroupBox;
    DBGrid2: TDBGrid;
    DBNavigator2: TDBNavigator;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation {$R *.dfm}

uses Unit2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DBGrid1.DataSource      := DM.dsMaster;
  DBNavigator1.DataSource := DM.dsMaster;
  DBGrid2.DataSource      := DM.dsDetail;
  DBNavigator1.DataSource := DM.dsDetail;
  DM.tbMaster.Open;
  DM.tbDetail.Open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   DM.tbDetail.Close;
   DM.tbMaster.Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // add some data to master
  DM.tbMaster.Append;
  DM.tbMaster.FieldByName('ID').AsInteger  := 5;
  DM.tbMaster.FieldByName('TEXT').AsString := 'ROW 5';
  // add some data to detail
  DM.tbDetail.Append;
  DM.tbDetail.FieldByName('ID').AsInteger  := 6;
  DM.tbDetail.FieldByName('TEXT').AsString := '';
  DM.tbDetail.FieldByName('MAESTRO_ID').AsInteger := 5;
  // Save cache data
  DM.tbDetail.DataSource := nil;
  try
    DM.IBDatabase1.ApplyUpdates([DM.tbMaster, DM.tbDetail]);
  finally
    DM.tbDetail.DataSource := DM.dsMaster;
  end;
end;
end.

Resultado:


Saludos

Pd: Si el código de prueba te pudiera ser útil avisame y te lo adjunto.
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #11  
Antiguo 18-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Ok....te agradezco ecfisa, Muchas gracias por dedicarle tiempo a mi problema.

Haré los cambios a mi código y te (les) comentó como me fue. Pendiente con el aviso para el envío de tu código.

Saludos y nuevamente gracias.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!

Última edición por Casimiro Notevi fecha: 18-05-2018 a las 23:55:03.
Responder Con Cita
  #12  
Antiguo 19-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Oye....no haría falta en esta parte del código...el POST para ambos DataSets??
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
  // add some data to master
  DM.tbMaster.Append;
  DM.tbMaster.FieldByName('ID').AsInteger  := 5;
  DM.tbMaster.FieldByName('TEXT').AsString := 'ROW 5';
  // add some data to detail
  DM.tbDetail.Append;
  DM.tbDetail.FieldByName('ID').AsInteger  := 6;
  DM.tbDetail.FieldByName('TEXT').AsString := '';
  DM.tbDetail.FieldByName('MAESTRO_ID').AsInteger := 5;
  // Save cache data
// DONDE IRIA EL POST???.....AQUI?
  DM.tbDetail.DataSource := nil;
  try
    DM.IBDatabase1.ApplyUpdates([DM.tbMaster, DM.tbDetail]);
  finally
    DM.tbDetail.DataSource := DM.dsMaster;
  end;
end;
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #13  
Antiguo 19-05-2018
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola Miguel.

El método ApplyUpdates se encarga de realizar el guardado (post) de los datos almacenados en caché para cada TDataSet que se le pasa como argumento.

Te adjunto la prueba mas afinada y un script SQL para generar las tablas y algunos datos para el archivo maestro.

Saludos
Archivos Adjuntos
Tipo de Archivo: zip mRoman.zip (6,6 KB, 3 visitas)
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #14  
Antiguo 24-05-2018
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 638
Poder: 21
mRoman Va por buen camino
Cita:
Empezado por ecfisa Ver Mensaje
Hola Miguel.

El método ApplyUpdates se encarga de realizar el guardado (post) de los datos almacenados en caché para cada TDataSet que se le pasa como argumento.

Te adjunto la prueba mas afinada y un script SQL para generar las tablas y algunos datos para el archivo maestro.

Saludos
Te agradezco....no sabia que el metodo ApplyUpdate incluia esto!. Entonces por ahi va la cosa.
Lo reviso gracias.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Saber si el DBGrid (Detalle) esta Vacio en Relacion Maestro/Detalle Adrian Murua Conexión con bases de datos 2 03-01-2009 14:48:46
Maestro/Detalle (No graba en tabla Maestro) teclilla Tablas planas 12 21-04-2008 21:59:54
Problema tabla Maestro-detalle en la q la pk de t.detalle formad por 2cods de la maes akinom38 Varios 1 09-11-2007 20:27:44
Numerar el detalle Maestro / detalle en secuencia josejose SQL 5 10-02-2007 01:27:38
Maestro-Detalle ;Actualizar detalle a partir de un DBgrid norberto_larios Conexión con bases de datos 1 11-09-2004 19:17:34


La franja horaria es GMT +2. Ahora son las 01:01:05.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi