Diferencia entre revisiones de «TprxADODataSetEdit»
Sin resumen de edición |
Sin resumen de edición |
||
Línea 472: | Línea 472: | ||
===function LocalAfterPostWhere(DataSet: TDataSet): String=== | ===function LocalAfterPostWhere(DataSet: TDataSet): String=== | ||
Arma el código con la condición WHERE del registro, si corresponde. | Arma el código con la condición WHERE del registro, si corresponde. | ||
===procedure GetPopupOptions(Sender: TprxPopupMenu)=== | |||
Retorna las opciones de menú disponibles, el procedimiento también verifica si existe un dataset implementado (Ver [[DATASETS/IMPLEMENTADOS]]) y muestra esas opciones también. | |||
===function ORIGENES_Initialize(aMenu: TprxPopupMenu): Integer=== | |||
Inicializa los orígenes de datos de una clase, si los tiene los agrega al menú de opciones de la pantalla que está mostrando al dataset. | |||
===function CommandText_Select_Make(aTop1: Boolean = False): String=== | |||
Arma el comando SELECT de la clase en función de los campos que tiene, si el argumento aTop1 está definido en True no trae registros, solo las columnas vacías, sino trae todos los registros. | |||
===function SelectXtd(aLoadRecords: Boolean): Boolean=== | |||
Hace el SELECT del DataSet, notar que toma el comando del SELECT en sí y le agrega la posible condición del WHERE (que construye dinámicamente en la llamada a esta función). | |||
===function FieldControlEnable(aFieldName: String; aCondition: Boolean): Boolean=== | |||
Si la condición aCondition es True habilita el control del campo, si es False lo deshabilita. El Result es la aCondition que puede haber sido modificada por la función retornando False cuando no pudo activar el campo y True si lo hizo. | |||
===function FieldControlDisable(aFieldName: String; aCondition: Boolean): Boolean=== | |||
Si la condición aCondition es True deshabilita el control del campo, si es False lo habilita. El Result es la aCondition que puede haber sido modificada por la función. | |||
=Uso= | |||
Este dataset se usa mucho en la aplicación, pero siempre como ancestro de algún otro. |
Revisión actual - 19:25 16 may 2025
Introducción
El objeto TprxADODataSetEdit (Dataset con habilidades de armado de pantallas y edición de datos.) es un dataset bastante complejo que implementa habilidades para:
- Cargar la estructura de una tabla.
- Armar los campos.
- Ejecutar validaciones y eventos.
- Guardar los datos en la base usando transacciones.
Es el ancestro de otros datasets con funcionalidad aún más específica (aunque no tan general como éste).
Hace un uso extensivo de TDataSetNotifyEvent que son eventos de Delphi que notifican acontecimientos relacionados con el dataset.
Identidad
- Ancestro: TprxADODataSet
- Carpeta: C:\DevelopPrx\library
- Archivo: prxADODataSetEdit.pas
Declaración
type TprxADODataSetEdit = class(TprxADODataSet) private FQuerySQL: TStringList; FIsMasterDataSet: Boolean; FRecordExistenceChecked: Boolean; FLastDatabaseOp: TprxADODataSetLastDatabaseOp; FOnEditReady: TDataSetNotifyEvent; FOnExistingKey: TDataSetNotifyEvent; FOnMostrarIndicaciones: TprxADOShowFieldHint; FCommandOrderBy: TStrings; FLocalInsertXtdFlag: Boolean; FAddNavButtons: Boolean; FOnOpcionesPopupXtd: TprxOnOpcionesPopup; FOnEnterExternal: TprxADODataFieldOnEnter; FOnExitExternal: TprxADODataFieldOnExit; FFilteredOnInsert: Boolean; FDetalleCodigo: String; FDetalleVisual: String; FQueryAUX: TprxADOQuery; FListaFK: TStringList; FCascadeUpdate: Boolean; FCascadeDelete: Boolean; Fop_insert: Boolean; Fop_update: Boolean; Fop_delete: Boolean; FBookmark: TBookmark; FCommandText_Select: String; FCommandText_Where: String; FOnVerifyKeyData: TprxADOVerifyKeyData; FCallingDataSet: TprxADODataSetEdit; FCMP_RELACION_ACCION: String; FCMP_RELACION_ESTADO: String; FCMP_RELACION_RECIDS: TStringList; FTableDescription: String; FCatalogo: String; FTipoDato: String; FTAG_READONLY: Boolean; FTAG_AUTOPRINT: Boolean; FStatusBar: TStatusBar; Ffvs: Boolean; Fdevlog_monitor: Tfva_devlog_monitor; FUsaPanelPIE_Comentarios: Boolean; FUsaPanelPIE_Totales: Boolean; FPropertyFieldList: TStringList; Frefresco_modo: String; FPopupOptions: TprxADODataSet_Options; FTransactionTimeStamp: String; FCanDeleteCheckConstraints_NotInList: TStringList; // Para asignar prxADOQueryRESULTADO: TprxADOQuery del form de ejecución de // consultas... FClassConsultasResultado_Query: TprxADOQuery; FWHERE: TprxADODataSet_WHERE; Fdevlog_TestCommands: TStringList; FClase_Muestra_tab_first: Boolean; FClase_Muestra_tab_last: Boolean; FClase_Muestra_tab_comments: Boolean; FClase_Muestra_panel_comments: Integer; FBandFilter: TComponent; FRelacionesComponent: TComponent; FOnExitFieldXtd_Result: Boolean; FSCANDOCS_Field: String; // Los usamos para OnEnterFieldXtd y OnExitFieldXtd... FFieldEvent_FieldName: String; FFieldEvent_FieldValue: Variant; protected FTableName: String; FLoadRecords: Boolean; InLocateRecordFlag: Boolean; procedure SetTableName(aValue: String); virtual; procedure SetCommandOrderBy(aValue: TStrings); procedure SetCallingDataSet(aValue: TprxADODataSetEdit); procedure Set_fvs(aValue: Boolean); function GetCatalogo: String; function GetTipoDato: String; function Get_TAG_READONLY: Boolean; virtual; function Get_TAG_AUTOPRINT: Boolean; virtual; function StructureLoad: Integer; virtual; procedure DefaultValuesAssign; virtual; function KeyFieldsLoaded(aFieldName: String): Boolean; function LocateRecord: Boolean; virtual; procedure LocalAfterPost(DataSet: TDataSet); function LocalAfterPostInsert(DataSet: TDataSet): String; procedure LocalAfterPostIndicaDefecto; function LocalAfterPostEdit(DataSet: TDataSet; aWhere: String): String; function LocalAfterPostDelete(DataSet: TDataSet; aWhere: String): String; function CommandText_Select_Make(aTop1: Boolean = False): String; { 16/05/2025 function CommandText_Select_Make_DeUnBAK_PodemosBorrarlo(aTop1: Boolean = False): String; } property LocalInsertXtdFlag: Boolean read FLocalInsertXtdFlag write FLocalInsertXtdFlag; property FilteredOnInsert: Boolean read FFilteredOnInsert write FFilteredOnInsert; property Bookmark: TBookmark read FBookmark write FBookmark; property CommandText_Where: String read FCommandText_Where write FCommandText_Where; property refresco_modo: String read Frefresco_modo write Frefresco_modo; property PopupOptions: TprxADODataSet_Options read FPopupOptions write FPopupOptions; property QuerySQL: TStringList read FQuerySQL write FQuerySQL; // Los usamos para OnEnterFieldXtd y OnExitFieldXtd... property FieldEvent_FieldName: String read FFieldEvent_FieldName write FFieldEvent_FieldName; property FieldEvent_FieldValue: Variant read FFieldEvent_FieldValue write FFieldEvent_FieldValue; public FieldsXtdList: Tfva_campos_items; procedure Loaded; override; property CommandText_Select: String read FCommandText_Select; function FieldIsComputed(aFieldNo: Integer): Boolean; procedure LocalAfterScroll(DataSet: TDataSet); override; procedure Activate(aLoadRecords: Boolean); override; function IsTransactionMaster: Boolean; virtual; function Select(aSQLCommand: String = ''): Boolean; override; function LocalAfterPostWhere(DataSet: TDataSet): String; procedure DefaultValueAdd(aFieldName: String; aDefaultValue: String); procedure AssignFieldValueByName(aFieldName: String; aFieldValue: Variant); override; procedure AssignValueToField(aCampo: String; aValue: Variant); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function DataSetId: String; function LocateRecordOnClient(aKeyValuesA: TprxFieldValues; aKeyValuesCount: Integer): Boolean; function LocateRecordOnServer(aKeyValuesA: TprxFieldValues; aKeyValuesCount: Integer): Boolean; function CanInsertXtd: Boolean; virtual; procedure InsertXtd(Sender: TObject); virtual; function CanEditXtd: Boolean; virtual; procedure EditXtd(Sender: TObject); virtual; function PostXtd(Sender: TObject): Boolean; virtual; procedure CancelXtd(Sender: TObject); virtual; function CanDeleteXtd(aAsk: Boolean): Boolean; virtual; function CanDeleteCheckConstraints(aWarn: Boolean): Boolean; procedure DeleteXtd(Sender: TObject); virtual; procedure DeleteRecordsXtd(Sender: TObject); virtual; function UpdateBatchXtd(AffectRecords: TAffectRecords = arAll): Boolean; virtual; procedure OnEnterFieldXtd(Sender: TObject; aFieldName: String; aFieldValue: Variant); virtual; function OnExitFieldXtd(Sender: TObject; aFieldName: String; aFieldValue: Variant; aErrMsg: String): Boolean; virtual; function OnChangeFieldXtd(Sender: TObject; aFieldName: String; aFieldValue: Variant): Boolean; virtual; function ArmarClaveAuditoria: String; function ArmarClaveAuditoriaLARGO: String; procedure GetPopupOptions(Sender: TprxPopupMenu); {overload; }virtual; function DetailsEnabled: Boolean; function ORIGENES_Initialize(aMenu: TprxPopupMenu): Integer; function SelectXtd(aLoadRecords: Boolean): Boolean; property RecordExistenceChecked: Boolean read FRecordExistenceChecked write FRecordExistenceChecked; function ValidateQuery: TprxADOQuery; property LastDatabaseOp: TprxADODataSetLastDatabaseOp read FLastDatabaseOp; property DetalleCodigo: String read FDetalleCodigo; property DetalleVisual: String read FDetalleVisual; property QueryAUX: TprxADOQuery read FQueryAUX write FQueryAUX; property ListaFK: TStringList read FListaFK write FListaFK; property CascadeUpdate: Boolean read FCascadeUpdate write FCascadeUpdate; property CascadeDelete: Boolean read FCascadeDelete write FCascadeDelete; property op_insert: Boolean read Fop_insert write Fop_insert; property op_update: Boolean read Fop_update write Fop_update; property op_delete: Boolean read Fop_delete write Fop_delete; property TAG_READONLY: Boolean read Get_TAG_READONLY; property TAG_AUTOPRINT: Boolean read Get_TAG_AUTOPRINT; property ppOnVerifyKeyData: TprxADOVerifyKeyData read FOnVerifyKeyData write FOnVerifyKeyData; property xxCallingDataSet: TprxADODataSetEdit read FCallingDataSet write SetCallingDataSet; property CMP_RELACION_ACCION: String read FCMP_RELACION_ACCION write FCMP_RELACION_ACCION; property CMP_RELACION_ESTADO: String read FCMP_RELACION_ESTADO write FCMP_RELACION_ESTADO; property CMP_RELACION_RECIDS: TStringList read FCMP_RELACION_RECIDS write FCMP_RELACION_RECIDS; property TableDescription: String read FTableDescription; property Catalogo: String read GetCatalogo; property TipoDato: String read GetTipoDato; property StatusBar: TStatusBar read FStatusBar write FStatusBar; property fvs: Boolean read Ffvs write Set_fvs; property x_devlog_monitor: Tfva_devlog_monitor read Fdevlog_monitor write Fdevlog_monitor; property UsaPanelPIE_Comentarios: Boolean read FUsaPanelPIE_Comentarios write FUsaPanelPIE_Comentarios; property UsaPanelPIE_Totales: Boolean read FUsaPanelPIE_Totales write FUsaPanelPIE_Totales; property PropertyFieldList: TStringList read FPropertyFieldList; property CanDeleteCheckConstraints_NotInList: TStringList read FCanDeleteCheckConstraints_NotInList write FCanDeleteCheckConstraints_NotInList; property WHERE: TprxADODataSet_WHERE read FWHERE write FWHERE; property devlog_TestCommands: TStringList read Fdevlog_TestCommands write Fdevlog_TestCommands; property Clase_Muestra_tab_first: Boolean read FClase_Muestra_tab_first write FClase_Muestra_tab_first; property Clase_Muestra_tab_last: Boolean read FClase_Muestra_tab_last write FClase_Muestra_tab_last; property Clase_Muestra_tab_comments: Boolean read FClase_Muestra_tab_comments write FClase_Muestra_tab_comments; property Clase_Muestra_panel_comments : Integer read FClase_Muestra_panel_comments write FClase_Muestra_panel_comments; property OnExitFieldXtd_Result: Boolean read FOnExitFieldXtd_Result; property SCANDOCS_Field: String read FSCANDOCS_Field; published property ppTableName: String read FTableName write SetTableName; property ppCommandOrderBy: TStrings read FCommandOrderBy write SetCommandOrderBy; property ppIsMasterDataSet: Boolean read FIsMasterDataSet write FIsMasterDataSet; property ppOnEditReady: TDataSetNotifyEvent read FOnEditReady write FOnEditReady; property ppAddNavButtons: Boolean read FAddNavButtons write FAddNavButtons; property ppOnOpcionesPopupXtd: TprxOnOpcionesPopup read FOnOpcionesPopupXtd write FOnOpcionesPopupXtd; property ppOnShowFieldHint: TprxADOShowFieldHint read FOnMostrarIndicaciones write FOnMostrarIndicaciones; property ppOnEnterExternal: TprxADODataFieldOnEnter read FOnEnterExternal write FOnEnterExternal; property ppOnExitExternal: TprxADODataFieldOnExit read FOnExitExternal write FOnExitExternal; property ppOnExistingKey: TDataSetNotifyEvent read FOnExistingKey write FOnExistingKey; property TransactionTimeStamp: String read FTransactionTimeStamp write FTransactionTimeStamp; property ClassConsultasResultado_Query: TprxADOQuery read FClassConsultasResultado_Query write FClassConsultasResultado_Query; property LoadRecords: Boolean read FLoadRecords; property BandFilter: TComponent read FBandFilter write FBandFilter; property RelacionesComponent: TComponent read FRelacionesComponent write FRelacionesComponent; function FieldControlEnable(aFieldName: String; aCondition: Boolean): Boolean; function FieldControlDisable(aFieldName: String; aCondition: Boolean): Boolean; end;
FIsMasterDataSet: Boolean
Los datasets pueden ser el maestro o el detalle en una relación master-detail, esta propiedad se setea a True cuando se trata del dataset maestro.
FTableName: String
Guarda el nombre de la tabla asociada al dataset, tiene un métido de acceso documentado más abajo.
FieldsXtdList: Tfva_campos_items
La propiedad FieldsXtdList es de tipo [[Tfva_campos_items[]] y guarda un registro para cada campo de la tabla (información cargada en la función StructureLoad).
Implementación
procedure SetTableName(aValue: String)
Es un método de acceso al nombre de la tabla asociado al dataset, la declaración es:
protected FTableName: String;
Y el acceso a esa variable es:
published property ppTableName: String read FTableName write SetTableName;
La propiedad ppTableName es published aunque podría ser pública.
El procedimiento realiza algunos seteos pero lo más importante es la llamada a un procedimiento llamado StructureLoad; que carga la estructura de la tabla:
procedure TprxADODataSetEdit.SetTableName(aValue: String); begin if Trim(aValue) <> FTableName then begin if Assigned(Connection) = False then FindConnection; FTableName := aValue; if csDesigning in ComponentState = False then begin StructureLoad; end; fbn_parser_object.p_dataset := Self; fbn_parser_object.p_table_name := aValue; end; end;
function StructureLoad: Integer
Este procedimiento:
- Carga las claves foráneas que tiene la tabla, es decir, las tablas sobre las que validan sus propios campos (por ejemplo: si tenemos un campo FARTICULO con atributo dmoART va a cargar esa definición), esta información se usa para validar los datos cargados durante la edición.
- Carga las columnas de la tabla usando la vista prxcamposJER_RUNTIME_VISTA.
- Guarda algunos datos relacionados a la tabla, tales como Catalogo, TableDescription, DetalleCodigo, DetalleVisual, CascadeUpdate, CascadeDelete, TipoDato, TAG_READONLY y TAG_AUTOPRINT.
La información sobre los campos se carga al array FieldsXtdList que guarda un registro para cada campo de la tabla.
Consulta la documentación de los Campos puede resultar útil.
procedure DefaultValueAdd(aFieldName: String; aDefaultValue: String)
Procedimiento que permite agregar un valor por defecto a un campo.
procedure DefaultValuesAssign
Procedimiento que asigna todos los valores por defecto que tiene la definición de las columnas, se usa una vez que el estado de la tabla ha cambiado a dsInsert, es decir que pasó a inserción y permitirá que carguemos un nuevo registro.
function ArmarClaveAuditoria: String
Dada la clave primaria de la tabla, y los valores de sus campos, crea una clave (ejemplo: [FCMPCODIGO=FCF-0001-000000006][FCMPLINEA=1]) para usar en las rutinas de auditoría (documentado más adelante).
function ArmarClaveAuditoriaLARGO: String
Similar anterior, pero con una representación diferente en las fechas.
function KeyFieldsLoaded(aFieldName: String): Boolean
Dado el nombre de un campo de la tabla verifica si todos los campos clave han sido ingresados durante la inserción. Una vez que se hayan ingresado todos los campos clave tenemos que verificar si el registro existe y habilitar o deshabilitar los controles de edición según corresponda.
Válido para las operaciones de inserción.
function LocateRecordOnClient(aKeyValuesA: TprxFieldValues; aKeyValuesCount: Integer): Boolean
En una operación de inserción, y una vez que se han cargado todos los campos clave, verificamos si existe algún registro en la tabla (ya cargada en la aplicación) que corresponda a esa clave primaria, si la hay activamos ese registro. Esta función contribuye a que no intentemos dar de alta más de un registro con la misma clave primaria.
function LocateRecordOnServer(aKeyValuesA: TprxFieldValues; aKeyValuesCount: Integer): Boolean
Similar anterior, pero intenta encontrar el registro en el servidor. Esta función se ejecuta solamente si la función anterior retornó False indicando que no encontró un registro con esa clave primaria.
Es posible que el dataset contenga una lista de registros parcial que no incluye al que tiene esa clave primara, por eso es que intentamos cargarlo desde el servidor.
function LocateRecord: Boolean
Es la función llamada desde la aplicación para verificar si encontramos un registro con la clave primaria correspondiente a los datos cargados. Llama a las funciones:
- LocateRecordOnClient.
- LocateRecordOnServer.
Si encuentra el registro pasa el dataset al estado dsEdit (edición) de modo que podamos editar sus datos sin intentar darlo de alta (recibiríamos un error de clave duplicada). Si no encuentra el registro pasa el dataset al estado dsInsert (inserción) de modo que podamos seguir insertando los valores del nuevo registro.
function CanInsertXtd: Boolean
Verifica si podemos insertar un nuevo registro, retorna True si podemos insertar, False si no.
procedure InsertXtd(Sender: TObject)
Cambia el estado del dataset a dsInsert (inserción), todas las comprobaciones requeridas deberían haberse ejecutado previamente.
function CanEditXtd: Boolean
Verifica si podemos editar el registro corriente, retorna True si podemos insertar, False si no.
procedure EditXtd(Sender: TObject)
Cambia el estado del dataset a dsEdit (edición), todas las comprobaciones requeridas deberían haberse ejecutado previamente.
function PostXtd(Sender: TObject): Boolean
Guarda los cambios hechos a un registro localmente, es decir que los cambios se guardan en el dataset pero aún no impactan en la base de datos. De este modo podemos agregar una cantidad de registros (por ejemplo: la cabecera y todos los detalles de una factura y eventualmente grabarlos en la BD todos juntos). Realiza las comprobaciones necesarias antes de aplicar los cambios.
procedure CancelXtd(Sender: TObject)
Cancela la operación corriente, sea una inserción o una edición y retorna al registro activo antes de que la operación comenzara.
function CanDeleteXtd(aAsk: Boolean): Boolean
Verifica si el registro corriente puede ser eliminado.
function CanDeleteCheckConstraints(aWarn: Boolean): Boolean
Dado un registro (que pretendemos eliminar) revisa todas las claves foráneas sobre esta tabla y verifica si alguna de ellas hace referencia a la clave del registro corriente, si hay alguna dá un mensaje e indica que no se puede eliminar. Retorna True si puede eliminarlo o False si no puede.
La función es llamada desde CanDeleteXtd.
procedure DeleteXtd(Sender: TObject)
Elimina el registro corriente, realiza las comprobaciones necesarias.
procedure DeleteRecordsXtd(Sender: TObject)
Elimina todos los registros del dataset de una manera sencilla.
function UpdateBatchXtd(AffectRecords: TAffectRecords = arAll): Boolean
Aplica todos los cambios aplicados al dataset a la base de datos, usa la transacción del TprxADOConnection.
procedure LocalAfterPost(DataSet: TDataSet)
Arma el comando SQL que representa la operación que se está aplicando, se ejecuta en el evento AfterPost que se genera con cualquier cambio a los datos del dataset.
Según la operación llama a:
- LocalAfterPostInsert(DataSet) arma el comando SQL de una operación de inserción, la condición es if rsNew in RecordStatus then.
- LocalAfterPostEdit(DataSet, vWhere) arma el comando de una operación de edición, la condición es if rsModified in RecordStatus then.
- LocalAfterPostDelete(DataSet, vWhere) arma el comando de una operación de eliminación, la condición es if (rsDeleted in RecordStatus) then
function LocalAfterPostWhere(DataSet: TDataSet): String
Arma el código con la condición WHERE del registro, si corresponde.
procedure GetPopupOptions(Sender: TprxPopupMenu)
Retorna las opciones de menú disponibles, el procedimiento también verifica si existe un dataset implementado (Ver DATASETS/IMPLEMENTADOS) y muestra esas opciones también.
function ORIGENES_Initialize(aMenu: TprxPopupMenu): Integer
Inicializa los orígenes de datos de una clase, si los tiene los agrega al menú de opciones de la pantalla que está mostrando al dataset.
function CommandText_Select_Make(aTop1: Boolean = False): String
Arma el comando SELECT de la clase en función de los campos que tiene, si el argumento aTop1 está definido en True no trae registros, solo las columnas vacías, sino trae todos los registros.
function SelectXtd(aLoadRecords: Boolean): Boolean
Hace el SELECT del DataSet, notar que toma el comando del SELECT en sí y le agrega la posible condición del WHERE (que construye dinámicamente en la llamada a esta función).
function FieldControlEnable(aFieldName: String; aCondition: Boolean): Boolean
Si la condición aCondition es True habilita el control del campo, si es False lo deshabilita. El Result es la aCondition que puede haber sido modificada por la función retornando False cuando no pudo activar el campo y True si lo hizo.
function FieldControlDisable(aFieldName: String; aCondition: Boolean): Boolean
Si la condición aCondition es True deshabilita el control del campo, si es False lo habilita. El Result es la aCondition que puede haber sido modificada por la función.
Uso
Este dataset se usa mucho en la aplicación, pero siempre como ancestro de algún otro.