unit uMontajesController;

interface


uses
  Classes, SysUtils, uDADataTable, uControllerBase, uEditorDBItem,
  uIDataModuleMontajes,
  uClientesController, uBizMontajes;

type
  IMontajesController = interface(IObservador)
  ['{84A6AB42-D89D-4BA8-8B0C-594B96CA0C13}']
    function GetClienteController: IClientesController;
    procedure SetClienteController(const Value: IClientesController);
    property ClienteController: IClientesController read GetClienteController write SetClienteController;

    function Buscar(const ID: Integer): IBizMontaje;
    function BuscarTodos: IBizMontaje;
    procedure Ver(AMontaje : IBizMontaje);
    procedure VerTodos(AMontajes: IBizMontaje);
    function Nuevo : IBizMontaje; overload;
    procedure Anadir(AMontaje : IBizMontaje);
    procedure Eliminar(const ID : Integer); overload;
    procedure Eliminar(AMontaje : IBizMontaje); overload;
    procedure Guardar(AMontaje : IBizMontaje);
    procedure DescartarCambios(AMontaje : IBizMontaje);
    function Existe(const ID: Integer) : Boolean;
    function Duplicar(AMontaje: IBizMontaje): IBizMontaje;
    procedure Preview(AMontaje : IBizMontaje);
    procedure Print(AMontaje : IBizMontaje);
    procedure RecuperarCliente(AMontaje : IBizMontaje);
    function CambiarSituacion(AMontaje: IBizMontaje; ASituacion : String; AFecha: TDateTime = 0; DoPost: Boolean = True): Boolean; overload;
    function CambiarSituacion(AMontaje: IBizMontaje): Boolean; overload;

    function ElegirMontaje(AMontajes : IBizMontaje; AMensaje: String; AMultiSelect: Boolean): IBizMontaje;
    function ExtraerSeleccionados(AMontajes: IBizMontaje) : IBizMontaje;
  end;

  TMontajesController = class(TObservador, IMontajesController)
  protected
    FDataModule : IDataModuleMontajes;
    FClienteController : IClientesController;

    function GetClienteController: IClientesController;
    procedure SetClienteController(const Value: IClientesController);

    procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override;
    function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
    function _Vacio : IBizMontaje;

    procedure FiltrarEmpresa(AMontaje: IBizMontaje);
    function ValidarSituacion(ASituacion: String; AFechaIni: TDateTime; var AFechaFin: TDateTime): 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(AMontaje: IBizMontaje); virtual;
    procedure AsignarEditor(out AEditor: IEditorDBItem); virtual;

    function ValidarMontaje(AMontaje: IBizMontaje): Boolean; virtual;
    procedure AsignarID(AMontaje: IBizMontaje; NuevoID:Integer); virtual;

  public
    property ClienteController: IClientesController read GetClienteController write SetClienteController;

    constructor Create;
    destructor Destroy; override;

    procedure Eliminar(const ID : Integer); overload;
    procedure Eliminar(AMontaje : IBizMontaje); overload;
    procedure Guardar(AMontaje : IBizMontaje); virtual;
    procedure DescartarCambios(AMontaje : IBizMontaje); virtual;
    function Existe(const ID: Integer) : Boolean; virtual;
    procedure Anadir(AMontaje : IBizMontaje);
    function Buscar(const ID: Integer): IBizMontaje;
    function BuscarTodos: IBizMontaje;
    function Nuevo : IBizMontaje; overload;
    procedure Ver(AMontaje : IBizMontaje);
    procedure VerTodos(AMontajes: IBizMontaje);
    function Duplicar(AMontaje: IBizMontaje): IBizMontaje;
    procedure Preview(AMontaje : IBizMontaje);
    procedure Print(AMontaje : IBizMontaje);
    procedure RecuperarCliente(AMontaje : IBizMontaje);
    function ElegirMontaje(AMontajes : IBizMontaje; AMensaje: String; AMultiSelect: Boolean): IBizMontaje;
    function ExtraerSeleccionados(AMontajes: IBizMontaje) : IBizMontaje;
    function CambiarSituacion(AMontaje: IBizMontaje; ASituacion : String; AFecha: TDateTime = 0; DoPost: Boolean = True): Boolean; overload;
    function CambiarSituacion(AMontaje: IBizMontaje): Boolean; overload;
  end;

implementation

uses
  cxControls, DB, uEditorRegistryUtils, schMontajesClient_Intf,
  uBizContactos, uIEditorMontajes, uIEditorMontaje, uDataModuleMontajes,
  uIEditorElegirMontajes, variants,
  uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uIEditorSituacionMontaje,
  uDateUtils, uROTypes, DateUtils, Controls;

{ TMontajesController }

procedure TMontajesController.Anadir(AMontaje: IBizMontaje);
begin
  AMontaje.Insert;
  AMontaje.Cliente := (FClienteController.Nuevo as IBizCliente);
end;

procedure TMontajesController.AsignarDataModule;
begin
  FDataModule := TDataModuleMontajes.Create(Nil);
end;

procedure TMontajesController.AsignarEditor(out AEditor: IEditorDBItem);
begin
  CreateEditor('EditorMontaje', IEditorMontaje, AEditor);
end;

procedure TMontajesController.AsignarID(AMontaje: IBizMontaje; NuevoID:Integer);
begin
  if not Assigned(AMontaje) then
    raise Exception.Create ('Montaje no asignada');

  if AMontaje.EsNuevo then
  begin
    AMontaje.Edit;
    AMontaje.ID := NuevoID;
    AMontaje.Post;
  end;
end;

function TMontajesController.Buscar(const ID: Integer): IBizMontaje;
begin
  Result := (FDataModule as IDataModuleMontajes).GetItem(ID);
  FiltrarEmpresa(Result);  
end;

function TMontajesController.BuscarTodos: IBizMontaje;
begin
  Result := FDataModule.GetItems;
  FiltrarEmpresa(Result);  
end;

function TMontajesController.CambiarSituacion(AMontaje: IBizMontaje; ASituacion: String; AFecha: TDateTime; DoPost: Boolean): Boolean;
begin
  Result := False;

  // Validar la situación del montaje
  if ValidarSituacion(ASituacion, AMontaje.FECHA_INICIO, AFecha) then
  begin
    ShowHourglassCursor;
    AMontaje.DataTable.DisableControls;
    try
      AMontaje.Edit;
      AMontaje.SITUACION := ASituacion;
      if ASituacion = SITUACION_MONTAJE_EJECUCION then
      begin
         if AFecha <> AMontaje.FECHA_INICIO then
            AMontaje.FECHA_INICIO := AFecha;
      end
      else if ASituacion = SITUACION_MONTAJE_TERMINADO then
      begin
         if AFecha <> AMontaje.FECHA_FIN then
            AMontaje.FECHA_FIN := AFecha;
      end
      else if ASituacion = SITUACION_MONTAJE_PENDIENTE then
      begin
         AMontaje.DataTable.FieldByName(fld_MontajesFECHA_INICIO).AsVariant := Null;
         AMontaje.DataTable.FieldByName(fld_MontajesFECHA_Fin).AsVariant := Null;
      end;
      AMontaje.Post;
      if DoPost then
         Guardar(AMontaje);
      Result := True;
    finally
      AMontaje.DataTable.EnableControls;
      HideHourglassCursor;
    end;
  end;
end;

function TMontajesController.CambiarSituacion(AMontaje: IBizMontaje): Boolean;
var
  AEditor : IEditorSituacionMontaje;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    RecuperarCliente(AMontaje);
    CreateEditor('EditorSituacionMontaje', IEditorSituacionMontaje, AEditor);
    with AEditor do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Montaje := AMontaje;
    end;
  finally
    HideHourglassCursor;
  end;

  if Assigned(AEditor) then
    AEditor.ShowModal;
end;

constructor TMontajesController.Create;
begin
  AsignarDataModule;
  FClienteController := TClientesController.Create;
end;

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

procedure TMontajesController.DescartarCambios(AMontaje: IBizMontaje);
begin
  if not Assigned(AMontaje) then
    raise Exception.Create ('Montaje no asignado');

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

    AMontaje.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

destructor TMontajesController.Destroy;
begin
  FDataModule := Nil;
  FClienteController := Nil;
  inherited;
end;

function TMontajesController.Duplicar(AMontaje: IBizMontaje): IBizMontaje;
begin
  Result := Self._Vacio;
  ShowHourglassCursor;
  try
    DuplicarRegistros(AMontaje.DataTable, Result.DataTable, mdrActual);

    // Hay que dejar algunos campos como si fuera un montaje nuevo
    Result.Edit;
    with Result do
    begin
      ID_EMPRESA := dmUsuarios.IDEmpresaActual;
      USUARIO := dmUsuarios.LoginInfo.Usuario;
      REFERENCIA := ''; //Para que asigne uno nuevo
      FECHA_INICIO := DateOf(Now);
    end;

    Result.Post;
  finally
    HideHourglassCursor;
  end;
end;

function TMontajesController.ValidarMontaje(AMontaje: IBizMontaje): Boolean;
var
  AFechaPagado : TDateTime;
begin
  Result := False;

  if not Assigned(AMontaje) then
    raise Exception.Create ('Montaje no asignada');

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

  //Validamos
  if (AMontaje.ID_CLIENTE < 0) or
     (not Assigned(AMontaje.Cliente)) or
     (AMontaje.Cliente.IsEmpty) then
    raise Exception.Create('Debe indicar el cliente de este montaje');

  // Asegurarse de valores en campos "automáticos"
  AMontaje.Edit;
  try
    AMontaje.USUARIO := dmUsuarios.LoginInfo.Usuario;

    if Assigned(AMontaje.Cliente) then
      AMontaje.ID_CLIENTE := AMontaje.Cliente.ID;

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

function TMontajesController.ValidarSituacion(ASituacion: String;
  AFechaIni: TDateTime; var AFechaFin: TDateTime): Boolean;
begin
  Result := False;
  if ASituacion = SITUACION_MONTAJE_EJECUCION then
     if (EsFechaVacia(AFechaFin)) then
         raise Exception.Create('Hay que indicar una fecha de inicio');

  if ASituacion = SITUACION_MONTAJE_TERMINADO then
  begin
    if (EsFechaVacia(AFechaFin)) then
      raise Exception.Create('Hay que indicar una fecha de finalización')
    else if (AFechaIni < AFechaFin) then
      raise Exception.Create('La fecha de finalización debe ser posterior a la fecha de inicio');
  end;
  Result := True;
end;

procedure TMontajesController.Ver(AMontaje: IBizMontaje);
var
  AEditor : IEditorDBItem;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    RecuperarObjetos(AMontaje);
    AsignarEditor(AEditor);

    with (AEditor as IEditorMontaje) do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Montaje := AMontaje;
    end;
  finally
    HideHourglassCursor;
  end;

  if Assigned(AEditor) then
    AEditor.ShowModal;
end;

procedure TMontajesController.VerTodos(AMontajes: IBizMontaje);
var
  AEditor : IEditorMontajes;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    CreateEditor('EditorMontajes', IEditorMontajes, AEditor);
    with AEditor do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Montajes := AMontajes;
    end;
  finally
    HideHourglassCursor;
  end;

  if Assigned(AEditor) then
    AEditor.ShowEmbedded;
end;

function TMontajesController._Vacio: IBizMontaje;
begin
  Result := Buscar(ID_NULO);
end;

procedure TMontajesController.Eliminar(const ID: Integer);
var
  AMontaje : IBizMontaje;
begin
  AMontaje := Buscar(ID);

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

  Eliminar(AMontaje);
  AMontaje := NIL;
end;

function TMontajesController.ElegirMontaje(AMontajes: IBizMontaje; AMensaje: String; AMultiSelect: Boolean): IBizMontaje;
var
  AEditor : IEditorElegirMontajes;
begin
  Result := NIL;

  CreateEditor('EditorElegirMontajes', IEditorElegirMontajes, AEditor);
  try
    with AEditor do
    begin
      Montajes := AMontajes;
      Controller := Self;
      MultiSelect := AMultiSelect;
      if IsPositiveResult(ShowModal) then
        Result := MontajesSeleccionados;
    end;
  finally
    AEditor := NIL;
  end;
end;

procedure TMontajesController.Eliminar(AMontaje: IBizMontaje);
begin
  if not Assigned(AMontaje) then
    raise Exception.Create ('Montaje no asignada');

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

    AMontaje.Delete;
    AMontaje.DataTable.ApplyUpdates;
  finally
    HideHourglassCursor;
  end;
end;

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

procedure TMontajesController.RecuperarCliente(AMontaje: IBizMontaje);
begin
  AMontaje.Cliente := (FClienteController.Buscar(AMontaje.ID_CLIENTE)  as IBizCliente);
end;

procedure TMontajesController.RecuperarObjetos(AMontaje: IBizMontaje);
begin
  if not Assigned(AMontaje.Cliente)
  or (AMontaje.ID_CLIENTE <> AMontaje.Cliente.ID) then
     RecuperarCliente(AMontaje);
end;

function TMontajesController.Existe(const ID: Integer): Boolean;
var
  AMontaje : IBizMontaje;
begin
  try
    AMontaje := Buscar(ID);
    Result := Assigned(AMontaje) and (AMontaje.ID = ID);
  finally
    AMontaje := NIL;
  end;
end;

function TMontajesController.ExtraerSeleccionados(AMontajes: IBizMontaje): IBizMontaje;
var
  ASeleccionados : IBizMontaje;
begin
  ASeleccionados := Self.Buscar(ID_NULO);
  CopyDataTable(AMontajes.DataTable, ASeleccionados.DataTable, True);
  Result := ASeleccionados;
end;

procedure TMontajesController.FiltrarEmpresa(AMontaje: IBizMontaje);
begin
  if AMontaje.DataTable.Active then
    AMontaje.DataTable.Active := False;

  // Filtrar los montajes actuales por empresa
  with AMontaje.DataTable.Where do
  begin
    if NotEmpty then
      AddOperator(opAND);
    AddCondition(fld_MontajesID_EMPRESA, cEqual, dmUsuarios.IDEmpresaActual);
  end;
end;

procedure TMontajesController.SetClienteController(const Value: IClientesController);
begin
  FClienteController := Value;
end;

procedure TMontajesController.Guardar(AMontaje: IBizMontaje);
var
  NuevoID: Integer;
begin
  if ValidarMontaje(AMontaje) then
  begin
    ShowHourglassCursor;
    try
      if (AMontaje.EsNuevo) then
          NuevoID := FDataModule.GetNextID(AMontaje.DataTable.LogicalName)
      else
          NuevoID := AMontaje.ID;

      AsignarID(AMontaje, NuevoID);
      AMontaje.DataTable.ApplyUpdates;
    finally
      HideHourglassCursor;
    end;
  end;
end;

function TMontajesController.Nuevo: IBizMontaje;
var
  AMontaje : IBizMontaje;
begin
  AMontaje := FDataModule.NewItem;
  FiltrarEmpresa(AMontaje);
  AMontaje.DataTable.Active := True;
  AMontaje.Insert;
  AMontaje.Cliente := (FClienteController.Nuevo as IBizCliente);  
  Result := AMontaje;
end;

procedure TMontajesController.Preview(AMontaje: IBizMontaje);
//var
//  AReportController : IMontajesReportController;
begin
{  AReportController := TMontajesReportController.Create;
  try
    AReportController.Preview(AMontaje.ID);
  finally
    AReportController := NIL;
  end;
}
end;

procedure TMontajesController.Print(AMontaje: IBizMontaje);
//var
//  AReportController : IMontajesReportController;
begin
{  AReportController := TMontajesReportController.Create;
  try
    AReportController.Print(AMontaje.ID);
  finally
    AReportController := NIL;
  end;
}
end;

function TMontajesController.GetClienteController: IClientesController;
begin
  Result := FClienteController;
end;

end.
