unit uEditorDBBase; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uEditorItem, ImgList, PngImageList, StdActns, ActnList, TBX, TB2Item, TB2Dock, TB2Toolbar, ComCtrls, JvExControls, JvComponent, JvNavigationPane, DB, uDADataTable, uEditorBase, JvFormAutoSize, uDAScriptingProvider, uDACDSDataTable, AppEvnts, uCustomView, uViewBase, JvAppStorage, JvAppRegistryStorage, JvFormPlacement, pngimage, ExtCtrls, dxLayoutLookAndFeels, JvComponentBase; type IEditorDBBase = interface(IEditorBase) ['{497AE4CE-D061-4F75-A29A-320F8565FF54}'] end; TfEditorDBBase = class(TfEditorBase, IEditorDBBase) dsDataTable: TDADataSource; procedure actRefrescarExecute(Sender: TObject); procedure actAnteriorExecute(Sender: TObject); procedure actSiguienteExecute(Sender: TObject); procedure actAnteriorUpdate(Sender: TObject); procedure actSiguienteUpdate(Sender: TObject); procedure actRefrescarUpdate(Sender: TObject); procedure actCancelarCambiosExecute(Sender: TObject); procedure actGuardarExecute(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); virtual; procedure actEliminarExecute(Sender: TObject); procedure actEliminarUpdate(Sender: TObject); procedure actModificarUpdate(Sender: TObject); procedure actPrevisualizarUpdate(Sender: TObject); procedure actImprimirUpdate(Sender: TObject); protected FApplyUpdates: Boolean; function GetModified: Boolean; override; published constructor Create(AOwner: TComponent); override; end; var fEditorDBBase: TfEditorDBBase; implementation uses uExceptions, uDataTableUtils, uBizInformesBase, uDAInterfaces, uBizImportesDetalleBase; {$R *.dfm} procedure TfEditorDBBase.actRefrescarExecute(Sender: TObject); var ACursor: TCursor; ABookmark : TBookmark; begin inherited; if Assigned(dsDataTable.DataTable) then begin if (dsDataTable.DataTable.IsEmpty) or (not ModifiedQuery) then Exit; // No continuar con el refresco ABookmark := dsDataTable.DataTable.GetBookMark; // dsDataTable.DataTable.DisableControls; <- No descomentar ACursor := Screen.Cursor; Screen.Cursor := crHourGlass; try dsDataTable.DataTable.Refresh; if dsDataTable.DataTable.Dataset.BookmarkValid(ABookmark) then dsDataTable.DataTable.GotoBookmark(ABookmark); finally dsDataTable.DataTable.FreeBookmark(ABookmark); // dsDataTable.DataTable.EnableControls; <- No descomentar Screen.Cursor := ACursor; end; end; end; procedure TfEditorDBBase.actAnteriorExecute(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then begin if (not ModifiedQuery) then Exit; dsDataTable.DataTable.Prior; end; end; procedure TfEditorDBBase.actSiguienteExecute(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then begin if (not ModifiedQuery) then Exit; dsDataTable.DataTable.Next; end; end; procedure TfEditorDBBase.actAnteriorUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := not dsDataTable.DataTable.BOF else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actSiguienteUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := not dsDataTable.DataTable.EOF else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actRefrescarUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) and (not (dsDataTable.DataTable.State = dsInsert)) then (Sender as TAction).Enabled := not (dsDataTable.DataTable.Fetching or dsDataTable.DataTable.Opening or dsDataTable.DataTable.Closing) else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actCancelarCambiosExecute(Sender: TObject); var dtDetails : TList; i : integer; ABookmark : TBookmark; ACursor : TCursor; AParche : IParche; begin inherited; AParche := NIL; if Assigned(dsDataTable.DataTable) then begin ABookmark := dsDataTable.DataTable.GetBookMark; dsDataTable.DataTable.DisableControls; // dsDataTable.DataTable.DisableEventHandlers; <- No descomentar ACursor := Screen.Cursor; Screen.Cursor := crHourGlass; { No lo pongo en try..finally para ver posibles errores } //try dsDataTable.DataTable.Cancel; dtDetails := dsDataTable.DataTable.GetDetailDataTables; for i := 0 to dtDetails.Count - 1 do begin (TDADataTable(dtDetails.Items[i])).Cancel; { PARCHE ********************************** OJO: Está pensado para que sólo una de las tablas detalle soporte el interfaz de IParche } if not Assigned(AParche) and Supports((TDADataTable(dtDetails.Items[i])), IParche, AParche) then AParche.DesactivarEventos; end; dsDataTable.DataTable.CancelUpdates; { Comprobar si el bookmark no es válido cuando estamos cancelando la inserción de una fila nueva. CUIDADO!! Si no es válido salta una excepción. NO devuelve false!!!} try if (Assigned(ABookmark)) and (dsDataTable.DataTable.Dataset.BookmarkValid(ABookmark)) then dsDataTable.DataTable.GotoBookmark(ABookmark); except end; { PARCHE ********************************** } if Assigned(AParche) then begin AParche.ActivarEventos; AParche.Refrescar; AParche := NIL; end; //finally dsDataTable.DataTable.EnableControls; dsDataTable.DataTable.FreeBookmark(ABookmark); // dsDataTable.DataTable.EnableEventHandlers; <- No descomentar Screen.Cursor := ACursor; //end; end; end; procedure TfEditorDBBase.actGuardarExecute(Sender: TObject); var dtDetails : TList; i : integer; ABookmark : TBookmark; begin inherited; if Assigned(dsDataTable.DataTable) then begin if dsDataTable.DataTable.Editing then dsDataTable.DataTable.Post; dtDetails := dsDataTable.DataTable.GetDetailDataTables; for i := 0 to dtDetails.Count - 1 do if (TDADataTable(dtDetails.Items[i])).Editing then (TDADataTable(dtDetails.Items[i])).Post; //Esta parte se quitará cuando cambien los detalles de facturas, se tiene que //volver a hacer el post de la tabla maestro porque los eventos de calculo de //importe total de los detalles cambian el campo base imponible entre otros de //la cabecera y luego no se hace post esto provoca que se queden deltas perdidos //y un pete que te cagas al dar a guardar sin salir del campo importe. if dsDataTable.DataTable.Editing then dsDataTable.DataTable.Post; if FApplyUpdates then begin // ABookmark := dsDataTable.DataTable.GetBookMark; try dsDataTable.DataTable.ApplyUpdates; // if dsDataTable.DataTable.Dataset.BookmarkValid(ABookmark) then // dsDataTable.DataTable.GotoBookmark(ABookmark); finally // dsDataTable.DataTable.FreeBookmark(ABookmark); end; end; Modified := False; end; end; function TfEditorDBBase.GetModified: Boolean; var dtDetails : TList; i : integer; bCambiado : Boolean; begin bCambiado := False; if Assigned(dsDataTable.DataTable) then begin bCambiado := (dsDataTable.DataTable.State = dsEdit); if FApplyUpdates then if (not bCambiado) then bCambiado := DeltaValuesAreDifferent(dsDataTable.DataTable.Delta); if (not bCambiado) then begin dtDetails := dsDataTable.DataTable.GetDetailDataTables; for i := 0 to dtDetails.Count - 1 do begin bCambiado := bCambiado or ((TDADataTable(dtDetails.Items[i])).State = dsEdit); if FApplyUpdates then if (not bCambiado) then bCambiado := bCambiado or (DeltaValuesAreDifferent((TDADataTable(dtDetails.Items[i])).Delta)); if bCambiado then Break; end; end; end; if (not bCambiado) then bCambiado := inherited GetModified; Result := bCambiado; end; procedure TfEditorDBBase.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin { Para resetear el estado de la tabla en el caso de hacer un insert sin meter ningún dato. } if Assigned(dsDataTable.DataTable) and (not Modified) then dsDataTable.DataTable.Cancel; inherited; end; procedure TfEditorDBBase.actEliminarExecute(Sender: TObject); var aObj : IApplyUpdateFailedException; ACursor: TCursor; begin inherited; ACursor := Screen.Cursor; Screen.Cursor := crHourGlass; try if dsDataTable.DataTable.State in dsEditModes then dsDataTable.DataTable.Cancel; dsDataTable.DataTable.Delete; try if FApplyUpdates then dsDataTable.DataTable.ApplyUpdates; Modified := False; except on E: EDAApplyUpdateFailed do begin dsDataTable.DataTable.CancelUpdates; actRefrescar.Execute; if Supports(dsDataTable.DataTable, IApplyUpdateFailedException, aObj) then aObj.ShowApplyUpdateFailed(E); end else raise; // Generic exception end; finally Screen.Cursor := ACursor; end; end; procedure TfEditorDBBase.actEliminarUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := (not dsDataTable.DataTable.IsEmpty) and not (dsDataTable.DataTable.State = dsInsert) else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actModificarUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := (not dsDataTable.DataTable.IsEmpty) else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actPrevisualizarUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := (not dsDataTable.DataTable.IsEmpty) else (Sender as TAction).Enabled := False; end; procedure TfEditorDBBase.actImprimirUpdate(Sender: TObject); begin inherited; if Assigned(dsDataTable.DataTable) then (Sender as TAction).Enabled := (not dsDataTable.DataTable.IsEmpty) else (Sender as TAction).Enabled := False; end; constructor TfEditorDBBase.Create(AOwner: TComponent); begin inherited; FApplyUpdates := True; end; end.