unit uCobrosClienteController;

interface


uses
  SysUtils, uDADataTable, uEditorDBItem, uControllerBase,
  uIDataModuleCobrosCliente, uClientesController, uBizCobrosCliente;

type
  ICobrosClienteController = interface
  ['{31D5F577-6DA2-4A8D-9EAF-ADA795F1FDDE}']
    function GetClienteController: IClientesController;
    procedure SetClienteController(const Value: IClientesController);
    property ClienteController: IClientesController read GetClienteController write SetClienteController;

    function Buscar(const ID: Integer): IBizCobroCliente;
    function BuscarTodos: IBizCobroCliente;
    procedure Ver(ACobro : IBizCobroCliente);
    procedure VerTodos(ACobros: IBizCobroCliente);
    function Nuevo : IBizCobroCliente;
    procedure Anadir(ACobro : IBizCobroCliente);
    procedure Eliminar(const ID : Integer); overload;
    procedure Eliminar(ACobro : IBizCobroCliente); overload;
    procedure Guardar(ACobro : IBizCobroCliente);
    procedure DescartarCambios(ACobro : IBizCobroCliente);
    function Existe(const ID: Integer) : Boolean;
    procedure RecuperarCliente(ACobro : IBizCobroCliente);
    function Duplicar(ACobro: IBizCobroCliente): IBizCobroCliente;
    procedure Preview(ACobro : IBizCobroCliente);
    procedure Print(ACobro : IBizCobroCliente);
  end;

  TCobrosClienteController = class(TObservador, ICobrosClienteController)
  protected
    FDataModule : IDataModuleCobrosCliente;
    FClienteController : IClientesController;

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

    //Estos son los tres métodos a sobre escribir si se desea heredar toda la logica de
    //este controller
    procedure AsignarDataModule; virtual;
    procedure RecuperarObjetos(ACobro: IBizCobroCliente); virtual;
    procedure AsignarEditor(out AEditor: IEditorDBItem); virtual;

    function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
    function _Vacio : IBizCobroCliente;
    procedure FiltrarEmpresa(ACobro: IBizCobroCliente);

    procedure AsignarID(ACobro: IBizCobroCliente; NuevoID: Integer);
    function ValidarCobro(ACobro: IBizCobroCliente): Boolean; virtual;

  public
    property ClienteController: IClientesController read GetClienteController write SetClienteController;

    constructor Create;
    destructor Destroy; override;

    procedure Eliminar(const ID : Integer); overload;
    procedure Eliminar(ACobro : IBizCobroCliente); overload;
    procedure Guardar(ACobro : IBizCobroCliente);
    procedure DescartarCambios(ACobro : IBizCobroCliente); virtual;
    function Existe(const ID: Integer) : Boolean; virtual;
    procedure Anadir(ACobro : IBizCobroCliente);
    function Buscar(const ID: Integer): IBizCobroCliente;
    function BuscarTodos: IBizCobroCliente;
    function Nuevo : IBizCobroCliente;
    procedure Ver(ACobro : IBizCobroCliente);
    procedure VerTodos(ACobros: IBizCobroCliente);
    function Duplicar(ACobro: IBizCobroCliente): IBizCobroCliente;
    procedure RecuperarCliente(ACobro : IBizCobroCliente);
    procedure Preview(ACobro : IBizCobroCliente); virtual;
    procedure Print(ACobro : IBizCobroCliente); virtual;
  end;

implementation

uses
  cxControls, DB, uEditorRegistryUtils, schCobrosClienteClient_Intf,
  uBizContactos, uIEditorCobrosCliente, uIEditorCobroCliente,
  uDataModuleCobrosCliente, uDataModuleUsuarios, uDAInterfaces,
  uDataTableUtils, uDateUtils, uROTypes, DateUtils;

{ TCobrosClienteController }

procedure TCobrosClienteController.Anadir(ACobro: IBizCobroCliente);
begin
  ACobro.Insert;
  ACobro.Cliente := (FClienteController.Nuevo as IBizCliente);  
end;

procedure TCobrosClienteController.AsignarDataModule;
begin
  FDataModule := TDataModuleCobrosCliente.Create(Nil);
end;

procedure TCobrosClienteController.AsignarEditor(out AEditor: IEditorDBItem);
begin
  CreateEditor('EditorCobroCliente', IEditorCobroCliente, AEditor);
end;

procedure TCobrosClienteController.AsignarID(ACobro: IBizCobroCliente;  NuevoID: Integer);
begin
  if not Assigned(ACobro) then
    raise Exception.Create ('Cobro no asignada');

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

function TCobrosClienteController.Buscar(const ID: Integer): IBizCobroCliente;
begin
  Result := (FDataModule as IDataModuleCobrosCliente).GetItem(ID);
  FiltrarEmpresa(Result);  
end;

function TCobrosClienteController.BuscarTodos: IBizCobroCliente;
begin
  Result := FDataModule.GetItems;
  FiltrarEmpresa(Result);  
end;

constructor TCobrosClienteController.Create;
begin
  AsignarDataModule;

  FClienteController := TClientesController.Create;
end;

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

procedure TCobrosClienteController.DescartarCambios(ACobro: IBizCobroCliente);
begin
  if not Assigned(ACobro) then
    raise Exception.Create ('Cobro no asignado');

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

    ACobro.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

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

function TCobrosClienteController.Duplicar(
  ACobro: IBizCobroCliente): IBizCobroCliente;
begin
  Result := Self._Vacio;
  ShowHourglassCursor;
  try
    DuplicarRegistros(ACobro.DataTable, Result.DataTable, mdrActual);

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

    Result.Post;
  finally
    HideHourglassCursor;
  end;
end;

function TCobrosClienteController.ValidarCobro(ACobro: IBizCobroCliente): Boolean;
var
  AFechaPagado : TDateTime;
begin
  Result := False;

  if not Assigned(ACobro) then
    raise Exception.Create ('Cobro no asignada');

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

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

  if (EsFechaVacia(ACobro.FECHA_COBRO)) then
    raise Exception.Create('Debe indicar la fecha de este cobro');

  if ACobro.IMPORTE = 0 then
    raise Exception.Create('Debe indicar el importe de este cobro');

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

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

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

procedure TCobrosClienteController.Ver(ACobro: IBizCobroCliente);
var
  AEditor : IEditorDBItem;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    RecuperarObjetos(ACobro);
    AsignarEditor(AEditor);

    with (AEditor as IEditorCobroCliente) do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Cobro := ACobro;
    end;
  finally
    HideHourglassCursor;
  end;

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

procedure TCobrosClienteController.VerTodos(ACobros: IBizCobroCliente);
var
  AEditor : IEditorCobrosCliente;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    CreateEditor('EditorCobrosCliente', IEditorCobrosCliente, AEditor);
    with AEditor do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Cobros := ACobros;
    end;
  finally
    HideHourglassCursor;
  end;

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

function TCobrosClienteController._Vacio: IBizCobroCliente;
begin
  Result := Buscar(ID_NULO);
end;

procedure TCobrosClienteController.Eliminar(const ID: Integer);
var
  ACobro : IBizCobroCliente;
begin
  ACobro := Buscar(ID);

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

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

procedure TCobrosClienteController.Eliminar(ACobro: IBizCobroCliente);
begin
  if not Assigned(ACobro) then
    raise Exception.Create ('Cobro no asignada');

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

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

procedure TCobrosClienteController.RecuperarCliente(ACobro: IBizCobroCliente);
begin
  ACobro.Cliente := (FClienteController.Buscar(ACobro.ID_CLIENTE)  as IBizCliente);
end;

procedure TCobrosClienteController.RecuperarObjetos(ACobro: IBizCobroCliente);
begin
  if not Assigned(ACobro.Cliente)
  or (ACobro.ID_CLIENTE <> ACobro.Cliente.ID) then
     RecuperarCliente(ACobro);
end;

function TCobrosClienteController.Existe(const ID: Integer): Boolean;
var
  ACobro : IBizCobroCliente;
begin
  try
    ACobro := Buscar(ID);
    Result := Assigned(ACobro) and (ACobro.ID = ID);
  finally
    ACobro := NIL;
  end;
end;

procedure TCobrosClienteController.FiltrarEmpresa(ACobro: IBizCobroCliente);
begin
  if ACobro.DataTable.Active then
    ACobro.DataTable.Active := False;

  // Filtrar las Cobros actuales por empresa
  with ACobro.DataTable.Where do
  begin
    if NotEmpty then
      AddOperator(opAND);
    AddCondition(fld_CobrosClienteID_EMPRESA, cEqual, dmUsuarios.IDEmpresaActual);
  end;
end;

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

procedure TCobrosClienteController.Guardar(ACobro: IBizCobroCliente);
var
  NuevoID: Integer;
begin
  if ValidarCobro(ACobro) then
  begin
    ShowHourglassCursor;
    try

      if (ACobro.EsNuevo) then
         NuevoID := FDataModule.GetNextID(ACobro.DataTable.LogicalName)
      else
         NuevoID := ACobro.ID;

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

function TCobrosClienteController.Nuevo: IBizCobroCliente;
var
  ACobro : IBizCobroCliente;
begin
  ACobro := FDataModule.NewItem;
  FiltrarEmpresa(ACobro);
  ACobro.DataTable.Active := True;
  ACobro.Insert;
  ACobro.Cliente := (FClienteController.Nuevo as IBizCliente);  
  Result := ACobro;
end;

procedure TCobrosClienteController.Preview(ACobro: IBizCobroCliente);
begin
//
end;

procedure TCobrosClienteController.Print(ACobro: IBizCobroCliente);
begin
//
end;

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

end.
