386 lines
11 KiB
ObjectPascal
386 lines
11 KiB
ObjectPascal
|
|
unit uContactosController;
|
|||
|
|
|
|||
|
|
interface
|
|||
|
|
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
Windows, Forms, Classes, Controls, Contnrs, SysUtils, uDADataTable,
|
|||
|
|
uBizContactos, uBizContactosDatosBancarios, uIDataModuleContactos;
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
IContactosController = interface
|
|||
|
|
['{43F9A4ED-6563-4F95-9A56-330CF9C66731}']
|
|||
|
|
function Buscar(const ID: Integer): IBizContacto;
|
|||
|
|
function BuscarTodos: IBizContacto;
|
|||
|
|
procedure Ver(AContacto : IBizContacto);
|
|||
|
|
procedure VerTodos(AContactos: IBizContacto);
|
|||
|
|
function Nuevo : IBizContacto;
|
|||
|
|
procedure Anadir(AContacto : IBizContacto);
|
|||
|
|
procedure Eliminar(const ID : Integer); overload;
|
|||
|
|
function Eliminar(AContacto : IBizContacto): Boolean; overload;
|
|||
|
|
function Guardar(AContacto : IBizContacto): Boolean;
|
|||
|
|
procedure DescartarCambios(AContacto : IBizContacto);
|
|||
|
|
function Existe(const ID: Integer) : Boolean;
|
|||
|
|
function Duplicar(AContacto : IBizContacto) : IBizContacto;
|
|||
|
|
function Localizar(AContactos: IBizContacto; const ID : Integer): Boolean;
|
|||
|
|
function ElegirContacto(AContactos : IBizContacto;
|
|||
|
|
AMensaje: String; AMultiSelect: Boolean): IBizContacto;
|
|||
|
|
|
|||
|
|
function ExtraerSeleccionados(AContactos: IBizContacto) : IBizContacto;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TContactosController = class(TInterfacedObject, IContactosController)
|
|||
|
|
protected
|
|||
|
|
FDataModule : IDataModuleContactos;
|
|||
|
|
procedure AsignarID(AContacto: IBizContacto; const IDNuevo : Integer); virtual;
|
|||
|
|
procedure AsignarIDDetalles(AContacto: IBizContacto;
|
|||
|
|
const IDCabecera : Integer; ADataTable : TDADataTable);
|
|||
|
|
procedure FiltrarEmpresa(AContacto : IBizContacto); virtual;
|
|||
|
|
function _Vacio : IBizContacto; virtual;
|
|||
|
|
function ValidarContacto(AContacto : IBizContacto): Boolean; virtual;
|
|||
|
|
public
|
|||
|
|
constructor Create; virtual;
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
|
|||
|
|
procedure Eliminar(const ID : Integer); overload; virtual;
|
|||
|
|
function Eliminar(AContacto : IBizContacto): Boolean; overload; virtual;
|
|||
|
|
function Guardar(AContacto : IBizContacto): Boolean;
|
|||
|
|
procedure DescartarCambios(AContacto : IBizContacto); virtual;
|
|||
|
|
function Existe(const ID: Integer) : Boolean; virtual;
|
|||
|
|
procedure Anadir(AContacto : IBizContacto); virtual;
|
|||
|
|
function Duplicar(AContacto: IBizContacto): IBizContacto; virtual;
|
|||
|
|
function ExtraerSeleccionados(AContactos: IBizContacto) : IBizContacto; virtual;
|
|||
|
|
function Localizar(AContactos: IBizContacto; const ID : Integer): Boolean;
|
|||
|
|
|
|||
|
|
// Se implementa en los controladores hijos
|
|||
|
|
function Buscar(const ID: Integer): IBizContacto; virtual; abstract;
|
|||
|
|
function BuscarTodos: IBizContacto; virtual; abstract;
|
|||
|
|
function Nuevo : IBizContacto; virtual; abstract;
|
|||
|
|
procedure Ver(AContacto : IBizContacto); virtual; abstract;
|
|||
|
|
procedure VerTodos(AContactos: IBizContacto); virtual; abstract;
|
|||
|
|
function ElegirContacto(AContactos : IBizContacto;
|
|||
|
|
AMensaje: String; AMultiSelect: Boolean): IBizContacto; virtual; abstract;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
implementation
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
Dialogs, uEditorRegistryUtils, cxControls, DB, uDAInterfaces, uDataTableUtils,
|
|||
|
|
uDataModuleUsuarios, schContactosClient_Intf;
|
|||
|
|
|
|||
|
|
{ TContactosController }
|
|||
|
|
|
|||
|
|
procedure TContactosController.Anadir(AContacto: IBizContacto);
|
|||
|
|
begin
|
|||
|
|
AContacto.Insert;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TContactosController.AsignarID(AContacto: IBizContacto; const IDNuevo : Integer);
|
|||
|
|
begin
|
|||
|
|
if not Assigned(AContacto) then
|
|||
|
|
raise Exception.Create ('Contacto no asignado');
|
|||
|
|
|
|||
|
|
if AContacto.EsNuevo then
|
|||
|
|
begin
|
|||
|
|
{ <EFBFBD><EFBFBD><EFBFBD> OJO !!!
|
|||
|
|
Primero cambiamos el ID de las tablas detalles
|
|||
|
|
porque si cambiamos antes el ID de la cabecera
|
|||
|
|
deja de funcionar la relacion M/D y no
|
|||
|
|
encontrar<EFBFBD>amos las filas detalle.
|
|||
|
|
|
|||
|
|
--> MASTER.ID = DETAIL.ID_CONTACTO <--
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
with AContacto._Categorias do
|
|||
|
|
begin
|
|||
|
|
if not DataTable.Active then
|
|||
|
|
DataTable.Active := True;
|
|||
|
|
Insert;
|
|||
|
|
ID_CONTACTO := IDNuevo;
|
|||
|
|
ID_CATEGORIA := AContacto.ID_CATEGORIA;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{ Los datos bancarios hay que comprobarlos siempre
|
|||
|
|
tanto en inserci<EFBFBD>n como en modificaci<EFBFBD>n. }
|
|||
|
|
if Assigned(AContacto.DatosBancarios) then
|
|||
|
|
AsignarIDDetalles(AContacto, IDNuevo, AContacto.DatosBancarios.DataTable);
|
|||
|
|
|
|||
|
|
|
|||
|
|
{ Las direcciones extras hay que comprobarlas siempre
|
|||
|
|
tanto en inserci<EFBFBD>n como en modificaci<EFBFBD>n. }
|
|||
|
|
if Assigned(AContacto.Direcciones) then
|
|||
|
|
AsignarIDDetalles(AContacto, IDNuevo, AContacto.Direcciones.DataTable);
|
|||
|
|
|
|||
|
|
|
|||
|
|
if AContacto.EsNuevo then
|
|||
|
|
begin
|
|||
|
|
AContacto.Edit;
|
|||
|
|
AContacto.ID := IDNuevo;
|
|||
|
|
AContacto.ID_EMPRESA := dmUsuarios.IDEmpresaActual;
|
|||
|
|
AContacto.Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
function TContactosController.Duplicar(AContacto: IBizContacto): IBizContacto;
|
|||
|
|
begin
|
|||
|
|
Result := Self._Vacio;
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
DuplicarRegistros(AContacto.DataTable, Result.DataTable, mdrActual);
|
|||
|
|
DuplicarRegistros(AContacto.DatosBancarios.DataTable, Result.DatosBancarios.DataTable, mdrTodos);
|
|||
|
|
if Assigned(AContacto.Direcciones) then
|
|||
|
|
DuplicarRegistros(AContacto.Direcciones.DataTable, Result.Direcciones.DataTable, mdrTodos);
|
|||
|
|
|
|||
|
|
// Hay que dejar algunos campos como si fuera un contacto nuevo
|
|||
|
|
Result.Edit;
|
|||
|
|
with Result do
|
|||
|
|
begin
|
|||
|
|
ID_EMPRESA := dmUsuarios.IDEmpresaActual;
|
|||
|
|
USUARIO := dmUsuarios.LoginInfo.Usuario;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
Result.Post;
|
|||
|
|
finally
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
constructor TContactosController.Create;
|
|||
|
|
begin
|
|||
|
|
FDataModule := NIL;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TContactosController.DescartarCambios(AContacto: IBizContacto);
|
|||
|
|
begin
|
|||
|
|
if not Assigned(AContacto) then
|
|||
|
|
raise Exception.Create ('Contacto no asignado');
|
|||
|
|
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
if (AContacto.State in dsEditModes) then
|
|||
|
|
AContacto.Cancel;
|
|||
|
|
|
|||
|
|
AContacto.DataTable.CancelUpdates;
|
|||
|
|
finally
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
destructor TContactosController.Destroy;
|
|||
|
|
begin
|
|||
|
|
FDataModule := NIL;
|
|||
|
|
inherited;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController.Eliminar(AContacto: IBizContacto): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
|
|||
|
|
if not Assigned(AContacto) then
|
|||
|
|
raise Exception.Create ('Contacto no asignado');
|
|||
|
|
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
if (AContacto.State in dsEditModes) then
|
|||
|
|
AContacto.Cancel;
|
|||
|
|
|
|||
|
|
AContacto.Delete;
|
|||
|
|
AContacto.DataTable.ApplyUpdates;
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
Result := True;
|
|||
|
|
except
|
|||
|
|
on E: Exception do
|
|||
|
|
begin
|
|||
|
|
AContacto.DataTable.CancelUpdates;
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
if (Pos('FOREIGN KEY', E.Message) > 0) then
|
|||
|
|
MessageBox(0, 'No se puede borrar este contacto porque tiene documentos dados de alta (como presupuestos, albaranes, facturas, etc)', 'Atenci<63>n', MB_ICONWARNING or MB_OK);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TContactosController.Eliminar(const ID: Integer);
|
|||
|
|
var
|
|||
|
|
AContacto : IBizContacto;
|
|||
|
|
begin
|
|||
|
|
AContacto := Buscar(ID);
|
|||
|
|
|
|||
|
|
if not Assigned(AContacto) then
|
|||
|
|
raise Exception.Create(Format('No se ha encontrado el contacto con ID = %d', [ID]));
|
|||
|
|
|
|||
|
|
Eliminar(AContacto);
|
|||
|
|
AContacto := NIL;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController.Existe(const ID: Integer): Boolean;
|
|||
|
|
var
|
|||
|
|
AContacto : IBizContacto;
|
|||
|
|
begin
|
|||
|
|
try
|
|||
|
|
AContacto := Buscar(ID);
|
|||
|
|
Result := Assigned(AContacto) and (AContacto.ID = ID);
|
|||
|
|
finally
|
|||
|
|
AContacto := NIL;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController.ExtraerSeleccionados(
|
|||
|
|
AContactos: IBizContacto): IBizContacto;
|
|||
|
|
var
|
|||
|
|
ASeleccionados : IBizContacto;
|
|||
|
|
begin
|
|||
|
|
ASeleccionados := Self.Buscar(ID_NULO);
|
|||
|
|
CopyDataTable(AContactos.DataTable, ASeleccionados.DataTable, True);
|
|||
|
|
Result := ASeleccionados;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController.Guardar(AContacto: IBizContacto): Boolean;
|
|||
|
|
var
|
|||
|
|
NuevoID : Integer;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
|
|||
|
|
if ValidarContacto(AContacto) then
|
|||
|
|
begin
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
if AContacto.EsNuevo then
|
|||
|
|
NuevoID := FDataModule.GetNextID(AContacto.DataTable.LogicalName)
|
|||
|
|
else
|
|||
|
|
NuevoID := AContacto.ID;
|
|||
|
|
|
|||
|
|
AsignarID(AContacto, NuevoID);
|
|||
|
|
AContacto.DataTable.ApplyUpdates;
|
|||
|
|
|
|||
|
|
Result := True;
|
|||
|
|
finally
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController.Localizar(AContactos: IBizContacto;
|
|||
|
|
const ID: Integer): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := True;
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
with AContactos.DataTable do
|
|||
|
|
begin
|
|||
|
|
DisableControls;
|
|||
|
|
First;
|
|||
|
|
if not Locate(fld_ContactosID, ID, []) then
|
|||
|
|
Result := False;
|
|||
|
|
EnableControls;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TContactosController.AsignarIDDetalles (AContacto: IBizContacto; const IDCabecera : Integer; ADataTable : TDADataTable);
|
|||
|
|
var
|
|||
|
|
AContador : Integer;
|
|||
|
|
begin
|
|||
|
|
if not ADataTable.Active then
|
|||
|
|
ADataTable.Active := True;
|
|||
|
|
|
|||
|
|
if AContacto.EsNuevo then
|
|||
|
|
begin
|
|||
|
|
{ <EFBFBD><EFBFBD><EFBFBD><EFBFBD> OJO !!!!
|
|||
|
|
Para asignar el ID en los detalles hay
|
|||
|
|
que tener en cuenta una cosa:
|
|||
|
|
Si se cambia el ID, ese detalle ya no
|
|||
|
|
pertenece a esa cabecera porque ya no se
|
|||
|
|
cumple la condici<EFBFBD>n de la relacion:
|
|||
|
|
Master.ID = Detail.ID_CONTACTO.
|
|||
|
|
|
|||
|
|
Por esa raz<EFBFBD>n no sirve hacer un recorrido
|
|||
|
|
desde el principio hasta el final porque
|
|||
|
|
las detalles van desapareciendo seg<EFBFBD>n asignamos
|
|||
|
|
el valor al campo ID y nos mueve aleatoriamente
|
|||
|
|
la posici<EFBFBD>n del registro actual.
|
|||
|
|
|
|||
|
|
Es mejor hacer un bucle sencillo hasta que
|
|||
|
|
"se gasten" todos los detalles. Cuando el
|
|||
|
|
RecordCount llegue a 0 quiere decir que hemos
|
|||
|
|
tratado todos los detalles.
|
|||
|
|
}
|
|||
|
|
while ADataTable.RecordCount > 0 do
|
|||
|
|
begin
|
|||
|
|
ADataTable.First;
|
|||
|
|
ADataTable.Edit;
|
|||
|
|
ADataTable.FieldByName('ID').AsInteger := FDataModule.GetNextID(ADataTable.LogicalName);
|
|||
|
|
// ADataTable.FieldByName('ID_CONTACTO').AsInteger := IDCabecera;
|
|||
|
|
//OJO SI UN DIA SON VARIOS LOS CAMPOS FORANEOS, SOLO FUNCIONA CUANDO ES UN <20>NICO CAMPO DE CLAVE FORANEA
|
|||
|
|
ADataTable.FieldByName(ADataTable.DetailFields).AsInteger := IDCabecera;
|
|||
|
|
ADataTable.Post;
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else begin
|
|||
|
|
{ En este caso es un recorrido normal y corriente. }
|
|||
|
|
ADataTable.First;
|
|||
|
|
AContador := ADataTable.RecordCount;
|
|||
|
|
|
|||
|
|
while (AContador > 0) do
|
|||
|
|
begin
|
|||
|
|
// <20>Es nuevo?
|
|||
|
|
if (ADataTable.FieldByName('ID').AsInteger < 0) then
|
|||
|
|
begin
|
|||
|
|
ADataTable.Edit;
|
|||
|
|
ADataTable.FieldByName('ID').AsInteger := FDataModule.GetNextID(ADataTable.LogicalName);
|
|||
|
|
ADataTable.Post;
|
|||
|
|
end;
|
|||
|
|
AContador := AContador - 1;
|
|||
|
|
ADataTable.Next;
|
|||
|
|
end;
|
|||
|
|
ADataTable.First;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
function TContactosController.ValidarContacto(AContacto: IBizContacto): Boolean;
|
|||
|
|
begin
|
|||
|
|
Result := False;
|
|||
|
|
|
|||
|
|
if not Assigned(AContacto) then
|
|||
|
|
raise Exception.Create ('Contacto no asignado');
|
|||
|
|
|
|||
|
|
if (AContacto.DataTable.State in dsEditModes) then
|
|||
|
|
AContacto.DataTable.Post;
|
|||
|
|
|
|||
|
|
if Length(AContacto.NOMBRE) = 0 then
|
|||
|
|
raise Exception.Create('Debe indicar al menos el nombre de este contacto.');
|
|||
|
|
|
|||
|
|
// Asegurarse de valores en campos "autom<6F>ticos"
|
|||
|
|
AContacto.Edit;
|
|||
|
|
AContacto.USUARIO := dmUsuarios.LoginInfo.Usuario;
|
|||
|
|
AContacto.Post;
|
|||
|
|
|
|||
|
|
Result := True;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TContactosController._Vacio: IBizContacto;
|
|||
|
|
begin
|
|||
|
|
Result := Buscar(ID_NULO);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TContactosController.FiltrarEmpresa(AContacto: IBizContacto);
|
|||
|
|
begin
|
|||
|
|
if AContacto.DataTable.Active then
|
|||
|
|
AContacto.DataTable.Active := False;
|
|||
|
|
|
|||
|
|
// Filtrar los contactos actuales por empresa
|
|||
|
|
with AContacto.DataTable.Where do
|
|||
|
|
begin
|
|||
|
|
if NotEmpty then
|
|||
|
|
AddOperator(opAND);
|
|||
|
|
AddCondition(fld_ContactosID_EMPRESA, cEqual, dmUsuarios.IDEmpresaActual);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
end.
|