unit uEmpresasController;

interface


uses
  Windows, Forms, Classes, Controls, Contnrs, SysUtils,
  uBizEmpresas, uIDataModuleEmpresas, uDADataTable;

type
  IEmpresasController = interface
    ['{2F0AB21C-4F19-446E-87C4-B9C1038850FC}']
    function Buscar(const ID: Integer): IBizEmpresa;
    function BuscarTodos: IBizEmpresa;
    procedure Ver(AEmpresa : IBizEmpresa);
    procedure VerTodos(AEmpresas: IBizEmpresa);
    function Nuevo : IBizEmpresa;
    procedure Anadir(AEmpresa : IBizEmpresa);
    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AEmpresa : IBizEmpresa): Boolean; overload;
    function Guardar(AEmpresa : IBizEmpresa): Boolean;
    procedure DescartarCambios(AEmpresa : IBizEmpresa);
    function Existe(const ID: Integer) : Boolean;
    function ToStringList(AEmpresa : IBizEmpresa) : TStringList;
  end;

  TEmpresasController = class(TInterfacedObject, IEmpresasController)
  protected
    FDataModule : IDataModuleEmpresas;
    procedure AsignarID(AEmpresa: IBizEmpresa;
      const IDNuevo : Integer); virtual;
    procedure AsignarIDDetalles(AEmpresa: IBizEmpresa;
      const IDCabecera : Integer; ADataTable : TDADataTable);
    function ValidarEmpresa(AEmpresa : IBizEmpresa): Boolean; virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;

    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AEmpresa : IBizEmpresa): Boolean; overload; 
    function Guardar(AEmpresa : IBizEmpresa): Boolean; 
    procedure DescartarCambios(AEmpresa : IBizEmpresa); virtual;
    function Existe(const ID: Integer) : Boolean; virtual;
    procedure Anadir(AEmpresa : IBizEmpresa); virtual;

    function Buscar(const ID: Integer): IBizEmpresa; virtual;
    function BuscarTodos: IBizEmpresa; virtual;
    function Nuevo : IBizEmpresa; virtual;
    procedure Ver(AEmpresa : IBizEmpresa); virtual;
    procedure VerTodos(AEmpresas: IBizEmpresa); virtual;
    function ToStringList(AEmpresa : IBizEmpresa) : TStringList; virtual;
  end;

implementation

uses
  uEditorRegistryUtils, cxControls, DB, 
  uDataModuleEmpresas, uIEditorEmpresa;

{ TEmpresasController }

procedure TEmpresasController.Anadir(AEmpresa: IBizEmpresa);
begin
  AEmpresa.Insert;
end;

procedure TEmpresasController.AsignarID(AEmpresa: IBizEmpresa;
  const IDNuevo: Integer);
var
  AContador : Integer;
begin
  if not Assigned(AEmpresa) then
    raise Exception.Create ('Empresa no asignada');

  { Los datos bancarios hay que comprobarlos siempre
    tanto en inserción como en modificación. }
  if Assigned(AEmpresa.DatosBancarios) then
    AsignarIDDetalles(AEmpresa, IDNuevo, AEmpresa.DatosBancarios.DataTable);


  if AEmpresa.EsNuevo then
  begin
    AEmpresa.Edit;
    AEmpresa.ID := IDNuevo;
    AEmpresa.Post;
  end;
end;

procedure TEmpresasController.AsignarIDDetalles(AEmpresa: IBizEmpresa;
  const IDCabecera: Integer; ADataTable: TDADataTable);
var
  AContador : Integer;
begin
  if not ADataTable.Active then
    ADataTable.Active := True;

  if AEmpresa.EsNuevo then
  begin
    { ¡¡¡¡ 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 AEmpresa esa cabecera porque ya no se
      cumple la condición de la relacion:
        Master.ID = Detail.ID_CONTACTO.

      Por esa razón no sirve hacer un recorrido
      desde el principio hasta el final porque
      las detalles van desapareciendo según asignamos
      el valor al campo ID y nos mueve aleatoriamente
      la posición del registro actual.

      Es mejor hacer un bucle sencillo hasta que
      "se gasten" todos los detalles. Cuando el
      RecordCount llegue AEmpresa 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_EMPRESA').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
      // ¿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 TEmpresasController.Buscar(const ID: Integer): IBizEmpresa;
begin
  Result := FDataModule.GetItem(ID)
end;

function TEmpresasController.BuscarTodos: IBizEmpresa;
begin
  Result := FDataModule.GetItems;
end;

constructor TEmpresasController.Create;
begin
  FDataModule := TDataModuleEmpresas.Create(Nil);
end;

procedure TEmpresasController.DescartarCambios(AEmpresa: IBizEmpresa);
begin
  if not Assigned(AEmpresa) then
    raise Exception.Create ('Empresa no asignada');

  ShowHourglassCursor;
  try
    if (AEmpresa.State in dsEditModes) then
      AEmpresa.Cancel;

    AEmpresa.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

destructor TEmpresasController.Destroy;
begin
  FDataModule := NIL;
  inherited;
end;

function TEmpresasController.Eliminar(AEmpresa: IBizEmpresa): Boolean;
begin
  Result := False;

  if not Assigned(AEmpresa) then
    raise Exception.Create ('Empresa no asignada');

  ShowHourglassCursor;
  try
    if (AEmpresa.State in dsEditModes) then
      AEmpresa.Cancel;

    AEmpresa.Delete;
    AEmpresa.DataTable.ApplyUpdates;

    Result := True;
  finally
    HideHourglassCursor;
  end;
end;

function TEmpresasController.Eliminar(const ID: Integer): Boolean;
var
  AEmpresa : IBizEmpresa;
begin
  AEmpresa := Buscar(ID);

  if not Assigned(AEmpresa) then
    raise Exception.Create(Format('No se ha encontrado la empresa con ID = %d', [ID]));

  Result := Eliminar(AEmpresa);
  AEmpresa := NIL;
end;

function TEmpresasController.Existe(const ID: Integer): Boolean;
var
  AEmpresa : IBizEmpresa;
begin
  try
    AEmpresa := Buscar(ID);
    Result := Assigned(AEmpresa) and (AEmpresa.ID = ID);
  finally
    AEmpresa := NIL;
  end;
end;

function TEmpresasController.Guardar(AEmpresa: IBizEmpresa): Boolean;
var
  NuevoID : Integer;
begin
  Result := False;

  if ValidarEmpresa(AEmpresa) then
  begin
    ShowHourglassCursor;
    try
      if AEmpresa.EsNuevo then
        NuevoID := FDataModule.GetNextID(AEmpresa.DataTable.LogicalName)
      else
        NuevoID := AEmpresa.ID;

      AsignarID(AEmpresa, NuevoID);
      AEmpresa.DataTable.ApplyUpdates;

      Result := True;
    finally
      HideHourglassCursor;
    end;
  end;
end;

function TEmpresasController.Nuevo: IBizEmpresa;
begin
  Result := FDataModule.NewItem;
end;

function TEmpresasController.ToStringList(AEmpresa: IBizEmpresa): TStringList;
begin
  Result := TStringList.Create;
  with Result do
  begin
    AEmpresa.DataTable.Active := True;
    AEmpresa.First;
    while not AEmpresa.EOF do
    begin
      Add(AEmpresa.NOMBRE);
      AEmpresa.Next;
    end;
  end;
end;

function TEmpresasController.ValidarEmpresa(AEmpresa: IBizEmpresa): Boolean;
begin
  Result := False;

  if not Assigned(AEmpresa) then
    raise Exception.Create ('Empresa no asignada');

  if (AEmpresa.DataTable.State in dsEditModes) then
    AEmpresa.DataTable.Post;

  if Length(AEmpresa.NOMBRE) = 0 then
    raise Exception.Create('Debe indicar al menos el nombre de la empresa.');

  // Asegurarse de valores en campos "automáticos"
{  AEmpresa.Edit;
  AEmpresa.USUARIO := dmUsuarios.LoginInfo.Usuario;
  AEmpresa.Post;}
  
  Result := True;
end;

procedure TEmpresasController.Ver(AEmpresa: IBizEmpresa);
var
  AEditor : IEditorEmpresa;
begin
  AEditor := NIL;	
  ShowHourglassCursor;
  try
	CreateEditor('EditorEmpresa', IEditorEmpresa, AEditor);
	with AEditor do
	begin
		Empresa := AEmpresa;
		Controller := Self;
	end;
  finally
    HideHourglassCursor;
  end;

  if Assigned(AEditor) then
    try
      AEditor.ShowModal;
      AEditor.Release;
    finally
      AEditor := NIL;
    end; 
end;

procedure TEmpresasController.VerTodos(AEmpresas: IBizEmpresa);
{var
  AEditor : IEditorClientes;}
begin
{  CreateEditor('EditorEmpresas', IEditorClientes, AEditor);
  with AEditor do
  begin
    Contactos := AContactos;
    Controller := Self;
    ShowEmbedded;
  end;}
end;

end.
