unit uObrasController;

interface


uses
  Classes, SysUtils, uDADataTable, uControllerBase, uEditorDBItem,
  uIDataModuleObras, uBizObras, uBizDireccionesContacto, uBizContactos;

type
  IObrasController = interface(IControllerBase)
  ['{FC563E47-7634-4227-9E4F-ED15C5C3A783}']
    function Buscar(const ID: Integer): IBizObra;
    function BuscarTodos: IBizObra;
    procedure Ver(AObra : IBizObra);
    procedure VerEjecucion(AObra : IBizObra);    
    procedure VerTodos(AObras: IBizObra);
    function VerLista(AObras: IBizObra): IBizObra;
    function Nuevo : IBizObra; overload;
    procedure Anadir(AObra : IBizObra);
    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AObra : IBizObra): Boolean; overload;
    function Guardar(AObra : IBizObra): Boolean;
    procedure DescartarCambios(AObra : IBizObra);
    function Existe(const ID: Integer) : Boolean;
    function Duplicar(AObra: IBizObra): IBizObra;
    procedure Preview(AObra : IBizObra);
    procedure Print(AObra : IBizObra);

    procedure QuitarDireccion(AObra: IBizObra);
    procedure CopiarDireccion (const ADireccionEnvio: IBizDireccionesContacto; AObra: IBizObra); overload;
    procedure CopiarDireccion (const ACliente: IBizCliente; AObra: IBizObra); overload;

//    procedure NuevaEjecucion(AObra: IBizObra; const AFecha : TDateTime);
    procedure CerrarEjecucionActiva(AObra: IBizObra; const AFecha : TDateTime);
    function LocalizarEjecucionActiva(AEjecuciones: IBizEjecucionesObra): boolean;
    function DarListaObras : TStringList;
  end;

  TObrasController = class(TControllerBase, IObrasController)
  protected
    FDataModule : IDataModuleObras;

    procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override;
//    procedure AssignarID(AObra: IBizObra; ADataModule : IDataModuleObras); virtual;
    function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
    function _Vacio : IBizObra;

    procedure FiltrarEmpresa(AObra: IBizObra);
    function ValidarObra(AObra: IBizObra): Boolean;

    //Estos son los tres métodos a sobre escribir si se desea heredar toda la logica de
    //este controller
    procedure AsignarDataModule; virtual;
    procedure RecuperarObjetos(AObra: IBizObra); virtual;

    procedure ValidarObjetos; virtual;
//    procedure AsignarCodigo(AObra: IBizObra); virtual;

  public
    constructor Create; override;
    destructor Destroy; override;

    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AObra : IBizObra): Boolean; overload;
    function Guardar(AObra : IBizObra): Boolean;
    procedure DescartarCambios(AObra : IBizObra);
    function Existe(const ID: Integer) : Boolean; virtual;
    procedure Anadir(AObra : IBizObra);
    function Buscar(const ID: Integer): IBizObra;
    function BuscarTodos: IBizObra;
    function Nuevo : IBizObra; overload;
    procedure Ver(AObra : IBizObra);
    procedure VerEjecucion(AObra : IBizObra);
    procedure VerTodos(AObras: IBizObra);
    function VerLista(AObras: IBizObra): IBizObra;
    function Duplicar(AObra: IBizObra): IBizObra;
    procedure Preview(AObra : IBizObra);
    procedure Print(AObra : IBizObra);
//    procedure NuevaEjecucion(AObra: IBizObra; const AFecha : TDateTime);
    procedure CerrarEjecucionActiva(AObra: IBizObra; const AFecha : TDateTime);
    procedure QuitarDireccion(AObra: IBizObra);
    procedure CopiarDireccion (const ADireccionEnvio: IBizDireccionesContacto; AObra: IBizObra); overload;
    procedure CopiarDireccion (const ACliente: IBizCliente; AObra: IBizObra); overload;
    function LocalizarEjecucionActiva(AEjecuciones: IBizEjecucionesObra): boolean;
    function DarListaObras : TStringList;
  end;

implementation

uses
  cxControls, DB, uEditorRegistryUtils, schObrasClient_Intf,
  uIEditorObras, uIEditorObra, uDataModuleObras, Variants,
  uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uFactuGES_App,
  uDateUtils, uROTypes, DateUtils, Controls, Windows, uIEditorListaObras,
  uIEditorFechaCierreObra, uIEditorEjecucionObra;

{ TObrasController }

procedure TObrasController.Anadir(AObra: IBizObra);
begin
  AObra.Insert;
end;

{procedure TObrasController.AsignarCodigo(AObra: IBizObra);
begin
  if (AObra.EsNuevo) then
     AssignarID(AObra, (FDataModule as IDataModuleObras));
end;}

procedure TObrasController.AsignarDataModule;
begin
  FDataModule := TDataModuleObras.Create(Nil);
end;

{procedure TObrasController.AssignarID(AObra: IBizObra; ADataModule : IDataModuleObras);
var
  NuevoIDCabecera : Integer;
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada');

  NuevoIDCabecera := ADataModule.GetNextID(AObra.DataTable.LogicalName);

  AObra.Edit;
  AObra.ID := NuevoIDCabecera;
  AObra.Post;
end;}

function TObrasController.Buscar(const ID: Integer): IBizObra;
begin
  Result := (FDataModule as IDataModuleObras).GetItem(ID);
  FiltrarEmpresa(Result);  
end;

function TObrasController.BuscarTodos: IBizObra;
begin
  Result := FDataModule.GetItems;
  FiltrarEmpresa(Result);  
end;

procedure TObrasController.CopiarDireccion(const ADireccionEnvio: IBizDireccionesContacto; AObra: IBizObra);
var
  bEnEdicion : Boolean;
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada (CopiarDireccion)');

  if not Assigned(ADireccionEnvio) then
    raise Exception.Create ('No se ha indicado la dirección (CopiarDireccionEnvio)');

  if AObra.DataTable.Active then
    AObra.DataTable.Active := True;

  if ADireccionEnvio.DataTable.Active then
    ADireccionEnvio.DataTable.Active := True;


  bEnEdicion := (AObra.DataTable.State in dsEditModes);
  if not bEnEdicion then
     AObra.Edit;

  ShowHourglassCursor;
  AObra.Edit;
  try
    AObra.CALLE := ADireccionEnvio.CALLE;
    AObra.POBLACION := ADireccionEnvio.POBLACION;
    AObra.CODIGO_POSTAL := ADireccionEnvio.CODIGO_POSTAL;
    AObra.PROVINCIA := ADireccionEnvio.PROVINCIA;
    AObra.TELEFONO := ADireccionEnvio.TELEFONO;
    AObra.PERSONA_CONTACTO := ADireccionEnvio.PERSONA_CONTACTO;

    if not bEnEdicion then
       AObra.Post;
  finally
    HideHourglassCursor;
  end;
end;

procedure TObrasController.CerrarEjecucionActiva(AObra: IBizObra;
  const AFecha: TDateTime);
var
  AEditor : IEditorFechaCierreObra;
begin
  AEditor := NIL;

  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada (CerrarEjecucion)');

  if AObra.DataTable.Active then
     AObra.DataTable.Active := True;

  CreateEditor('EditorFechaCierreObra', IEditorFechaCierreObra, AEditor);
  if Assigned(AEditor) then
    try
      AEditor.FechaCierre := DateOf(AFecha);
      if (AEditor.ShowModal = mrOk) then
      begin
        AObra.Ejecuciones.Edit;
        AObra.Ejecuciones.FECHA_FIN := DateOf(AEditor.FechaCierre);
        AObra.Ejecuciones.Post;
      end;
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

procedure TObrasController.CopiarDireccion(const ACliente: IBizCliente;
  AObra: IBizObra);
var
  bEnEdicion : Boolean;
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada (CopiarDireccion)');

  if not Assigned(ACliente) then
    raise Exception.Create ('No se ha indicado el cliente (CopiarDireccionEnvio)');

  if AObra.DataTable.Active then
    AObra.DataTable.Active := True;

  if ACliente.DataTable.Active then
    ACliente.DataTable.Active := True;


  bEnEdicion := (AObra.DataTable.State in dsEditModes);
  if not bEnEdicion then
     AObra.Edit;

  ShowHourglassCursor;
  AObra.Edit;
  try
    AObra.CALLE := ACliente.CALLE;
    AObra.POBLACION := ACliente.POBLACION;
    AObra.CODIGO_POSTAL := ACliente.CODIGO_POSTAL;
    AObra.PROVINCIA := ACliente.PROVINCIA;
    AObra.TELEFONO := ACliente.TELEFONO_1;
    AObra.PERSONA_CONTACTO := ACliente.PERSONA_CONTACTO;

    if not bEnEdicion then
       AObra.Post;
  finally
    HideHourglassCursor;
  end;
end;

constructor TObrasController.Create;
begin
  inherited;
  AsignarDataModule;
end;

function TObrasController.CreateEditor(const AName: String;
  const IID: TGUID; out Intf): Boolean;
begin
  Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf);
end;

function TObrasController.DarListaObras: TStringList;
begin
  ShowHourglassCursor;
  try
    Result := FDataModule.DarListaObras(AppFactuGES.EmpresaActiva.ID);
  finally
    HideHourglassCursor;
  end;
end;

procedure TObrasController.DescartarCambios(AObra : IBizObra);
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignado');

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

    AObra.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

destructor TObrasController.Destroy;
begin
  FDataModule := Nil;
  inherited;
end;

function TObrasController.Duplicar(AObra: IBizObra): IBizObra;
begin
  Result := Self._Vacio;
  ShowHourglassCursor;
  try
    DuplicarRegistros(AObra.DataTable, Result.DataTable, mdrActual);

    // Hay que dejar algunos campos como si fuera una obra nuevo
    Result.Edit;
    with Result do
    begin
      ID_EMPRESA := AppFactuGES.EmpresaActiva.ID;
      USUARIO := AppFactuGES.UsuarioActivo.UserName;
    end;

    Result.Post;
  finally
    HideHourglassCursor;
  end;
end;

function TObrasController.ValidarObra(AObra: IBizObra): Boolean;
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada');

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

  if Length(AObra.NOMBRE) = 0 then
    raise Exception.Create('Debe indicar al menos el nombre de esta obra.');

  // Asegurarse de valores en campos "automáticos"
  AObra.Edit;
  try
    AObra.USUARIO := AppFactuGES.UsuarioActivo.UserName;

    Result := True;
  finally
    AObra.Post;
  end;
end;

procedure TObrasController.ValidarObjetos;
begin
//
end;

procedure TObrasController.Ver(AObra: IBizObra);
var
  AEditor : IEditorObra;
begin
  AEditor := NIL;

  RecuperarObjetos(AObra);
  CreateEditor('EditorObra', IEditorObra, AEditor);
  if Assigned(AEditor) then
    try
      AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
      AEditor.Obra := AObra;
      AEditor.ShowModal;
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

procedure TObrasController.VerEjecucion(AObra: IBizObra);
var
  AEditor : IEditorEjecucionObra;
begin
  AEditor := NIL;

  RecuperarObjetos(AObra);
  CreateEditor('EditorEjecucionObra', IEditorEjecucionObra, AEditor);
  if Assigned(AEditor) then
    try
      AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
      AEditor.Obra := AObra;
      AEditor.ShowModal;
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

function TObrasController.VerLista(AObras: IBizObra): IBizObra;
var
  AEditor : IEditorListaObras;
begin
  AEditor := NIL;
  Result := NIL;

  CreateEditor('EditorListaObras', IEditorListaObras, AEditor);
  if Assigned(AEditor) then
    try
       AEditor.Obras := AObras;
       if IsPositiveResult(AEditor.ShowModal) then
          Result := AEditor.ObraSeleccionado;
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

procedure TObrasController.VerTodos(AObras: IBizObra);
var
  AEditor : IEditorObras;
begin
  AEditor := NIL;

  CreateEditor('EditorObras', IEditorObras, AEditor);
  if Assigned(AEditor) then
     with AEditor do
     begin
        Controller := Self; //OJO ORDEN MUY IMPORTANTE
        Obras := AObras;
        ShowEmbedded;
     end;
end;

function TObrasController._Vacio: IBizObra;
begin
  Result := Buscar(ID_NULO);
end;

function TObrasController.Eliminar(const ID: Integer): Boolean;
var
  AObra : IBizObra;
begin
  AObra := Buscar(ID);

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

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

function TObrasController.Eliminar(AObra: IBizObra): Boolean;
begin
  Result := False;

  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada');

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

    AObra.Delete;
    AObra.DataTable.ApplyUpdates;
    HideHourglassCursor;
    Result := True;
  except
    on E: Exception do
    begin
      AObra.DataTable.CancelUpdates;
      HideHourglassCursor;
      if (Pos('FOREIGN KEY', E.Message) > 0) then
         MessageBox(0, 'No se puede borrar esta obra porque tiene artículos', 'Atención', MB_ICONWARNING or MB_OK);
    end;
  end;
end;

procedure TObrasController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable);
begin
  inherited;
//
end;

procedure TObrasController.RecuperarObjetos(AObra: IBizObra);
begin
//
end;

function TObrasController.Existe(const ID: Integer): Boolean;
var
  AObra : IBizObra;
begin
  try
    AObra := Buscar(ID);
    Result := Assigned(AObra) and (AObra.ID = ID);
  finally
    AObra := NIL;
  end;
end;

procedure TObrasController.FiltrarEmpresa(AObra: IBizObra);
var
  Condicion: TDAWhereExpression;
begin
  if AObra.DataTable.Active then
    AObra.DataTable.Active := False;

  // Filtrar los Obras actuales por empresa
  with AObra.DataTable.DynamicWhere do
  begin
    // (ID_EMPRESA >= ID)
    Condicion := NewBinaryExpression(NewField('', fld_ObrasID_EMPRESA), NewConstant(AppFactuGES.EmpresaActiva.ID, datInteger), dboEqual);

    if IsEmpty then
       Expression := Condicion
    else
       Expression := NewBinaryExpression(Expression, Condicion, dboAnd);
  end;
end;

function TObrasController.Guardar(AObra: IBizObra): Boolean;
begin
  Result := False;

  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada');

  ValidarObjetos;

  if ValidarObra(AObra) then
  begin
    ShowHourglassCursor;
    try
      if (AObra.DataTable.State in dsEditModes) then
          AObra.DataTable.Post;
      AObra.DataTable.ApplyUpdates;
      Result := True;
    finally
      HideHourglassCursor;
    end;
  end;
end;

function TObrasController.LocalizarEjecucionActiva(
  AEjecuciones: IBizEjecucionesObra): boolean;
begin
  Result := False;

  if not Assigned(AEjecuciones) then
    raise Exception.Create ('Ejecuciones no asignada (LocalizarEjecucionActiva)');

  if AEjecuciones.IsEmpty then
    Exit;

  ShowHourglassCursor;
  try
    with AEjecuciones.DataTable do
    begin
      DisableControls;
      try
        First;
        while not EOF do
        begin
          if AEjecuciones.FECHA_FINIsNull then
          begin
            Result := True;
            Break;
          end
          else
            Next;
        end;
      finally
        EnableControls;
      end;
    end;
  finally
    HideHourglassCursor;
  end;
end;

{procedure TObrasController.NuevaEjecucion(AObra: IBizObra;
  const AFecha: TDateTime);
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada (NuevaEjecucion)');

  if AObra.DataTable.Active then
     AObra.DataTable.Active := True;

  with AObra.EjecucionEnCurso do
  begin
    Insert;
    FECHA_INICIO := AFecha;
    Post;
  end;
end;}

function TObrasController.Nuevo: IBizObra;
var
  AObra : IBizObra;
begin
  AObra := FDataModule.NewItem;
  FiltrarEmpresa(AObra);
  AObra.DataTable.Active := True;
  AObra.Insert;
  Result := AObra;
end;

procedure TObrasController.Preview(AObra: IBizObra);
//var
//  AReportController : IObrasReportController;
begin
{  AReportController := TObrasReportController.Create;
  try
    AReportController.Preview(AObra.ID);
  finally
    AReportController := NIL;
  end;
}
end;

procedure TObrasController.Print(AObra: IBizObra);
//var
//  AReportController : IObrasReportController;
begin
{  AReportController := TObrasReportController.Create;
  try
    AReportController.Print(AObra.ID);
  finally
    AReportController := NIL;
  end;
}
end;

procedure TObrasController.QuitarDireccion(AObra: IBizObra);
var
  bEnEdicion : Boolean;
begin
  if not Assigned(AObra) then
    raise Exception.Create ('Obra no asignada (QuitarDireccion)');

  if AObra.DataTable.Active then
     AObra.DataTable.Active := True;

  bEnEdicion := (AObra.DataTable.State in dsEditModes);
  if not bEnEdicion then
     AObra.Edit;

  ShowHourglassCursor;
  AObra.Edit;
  try
    AObra.DataTable.FieldByName(fld_ObrasCALLE).Clear;
    AObra.DataTable.FieldByName(fld_ObrasPOBLACION).Clear;
    AObra.DataTable.FieldByName(fld_ObrasCODIGO_POSTAL).Clear;
    AObra.DataTable.FieldByName(fld_ObrasPROVINCIA).Clear;
    AObra.DataTable.FieldByName(fld_ObrasTELEFONO).Clear;
    AObra.DataTable.FieldByName(fld_ObrasPERSONA_CONTACTO).Clear;

    if not bEnEdicion then
      AObra.Post;
  finally
    HideHourglassCursor;
  end;
end;

end.
