unit uComisionesController;

interface


uses
  Classes, SysUtils, uDADataTable, uControllerBase, uEditorDBItem,
  uIDataModuleComisiones, uBizComisiones, uFacturasClienteController, uBizFacturasCliente;

type
  IComisionesController = interface(IObservador)
  ['{0C281A5D-9DF9-46BD-99CB-1150A536EFA1}']
    function BuscarTodos: IBizComisiones;
    procedure VerTodos(AComision: IBizComisiones);
    procedure Ver(AComision: IBizComisiones);
    function Anadir(AComision : IBizComisiones): Boolean;
    function Eliminar(AComision : IBizComisiones): Boolean;
    function Guardar(AComision : IBizComisiones): Boolean;
    procedure DescartarCambios(AComision : IBizComisiones);
    procedure Preview(AComision : IBizComisiones; const DesglosadoProv: Boolean);
    procedure Print(AComision : IBizComisiones; const DesglosadoProv: Boolean);

    function ElegirFacturasComision(AComision : IBizComisiones): Boolean;
    procedure EliminarFactura(AComision : IBizComisiones);
    procedure AsignarImporteTotal(AComision : IBizComisiones; Const ImporteTotal: Variant);
  end;

  TComisionesController = class(TObservador, IComisionesController)
  private
    function BuscarFacturasDesglosadas(AFacturas: IBizFacturaCliente): IBizFacturasComision;
//    procedure QuitarExistentes(AFacturas: IBizFacturaCliente; AFacturasComision: IBizFacturasComision);

  protected
    FDataModule : IDataModuleComisiones;
    FFacturasClienteController: IFacturasClienteController;

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

    function ValidarComision(AComision: IBizComisiones): Boolean;
    procedure AsignarID(AComision: IBizComisiones; const IDNuevo: Integer);
    procedure AsignarIDDetalles(AFacturasComision: IBizFacturasComision; IDComision: Integer; AEsNuevo: Boolean);
    //Estos son los tres métodos a sobre escribir si se desea heredar toda la logica de
    //este controller
    procedure AsignarDataModule; virtual;

  public
    constructor Create; virtual;
    destructor Destroy; override;

    function Eliminar(AComision : IBizComisiones): Boolean;
    function Guardar(AComision : IBizComisiones): Boolean;
    procedure DescartarCambios(AComision : IBizComisiones);
    function Anadir(AComision : IBizComisiones): Boolean;
    function BuscarTodos: IBizComisiones;
    procedure VerTodos(AComision: IBizComisiones);
    procedure Ver(AComision: IBizComisiones);
    procedure Preview(AComision : IBizComisiones; const DesglosadoProv: Boolean);
    procedure Print(AComision : IBizComisiones; const DesglosadoProv: Boolean);
    function ElegirFacturasComision(AComision : IBizComisiones): Boolean;
    procedure EliminarFactura(AComision : IBizComisiones);
    procedure AsignarImporteTotal(AComision : IBizComisiones; Const ImporteTotal: Variant);
  end;

implementation

uses
  Variants, Dialogs, cxControls, DB, uEditorRegistryUtils, schComisionesClient_Intf,
  uIEditorComisiones, uDataModuleComisiones, uDataModuleUsuarios,
  uDAInterfaces, uDataTableUtils, uIEditorComision, uComisionesReportController,
  uDateUtils, uROTypes, DateUtils, Controls, Windows, uDialogUtils;

{ TComisionesController }

function TComisionesController.Anadir(AComision: IBizComisiones): Boolean;
begin
  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignado (Anadir)');

  if not AComision.DataTable.Active then
    AComision.DataTable.Active := True;

  AComision.Insert;
  Result := True;
end;

procedure TComisionesController.AsignarDataModule;
begin
  FDataModule := TDataModuleComisiones.Create(Nil);
end;

procedure TComisionesController.AsignarID(AComision: IBizComisiones; const IDNuevo: Integer);
begin
  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignado');

  AsignarIDDetalles(AComision.Facturas, IDNuevo, AComision.EsNuevo);

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

procedure TComisionesController.AsignarIDDetalles(AFacturasComision: IBizFacturasComision; IDComision: Integer; AEsNuevo: Boolean);
begin
  with AFacturasComision do
  begin
    DataTable.DisableControls;
    try
      begin
        if not DataTable.Active then
          DataTable.Active := True;

        { ¡¡¡¡ 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ón de la relacion:
            Master.ID = Detail.ID_PRESUPUESTO.

          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 a 0 quiere decir que hemos
          tratado todos los detalles.

          El bucle cambia en el caso de ser llamada esta funcion desde modificar
          un presupuesto ya que en ese caso si que hay que hacer un recorrido
          total de las tuplas de detalle.
        }

      if AEsNuevo then
      begin
        while RecordCount > 0 do
        begin
          DataTable.First;
          Edit;
          ID_COMISION_LIQUIDADA := IdComision;
          Post
        end
      end
      else
      begin
        DataTable.First;
        while not DataTable.EOF do
        begin
          if ID_COMISION_LIQUIDADA < 0  then
          begin
            Edit;
            ID_COMISION_LIQUIDADA := IdComision;
            Post
          end;
          DataTable.Next
        end;
      end;
    end;
    finally
      DataTable.EnableControls;
    end;
  end;
end;

procedure TComisionesController.AsignarImporteTotal(AComision: IBizComisiones; const ImporteTotal: Variant);
begin
  if Assigned(AComision) then
  begin
    if (not VarIsNull(ImporteTotal))
    and (AComision.DataTable.FieldByName(fld_ComisionesIMPORTE_TOTAL).IsNull or (AComision.IMPORTE_TOTAL <> ImporteTotal)) then
    begin
      AComision.Edit;
      AComision.IMPORTE_TOTAL := ImporteTotal;
      AComision.Post;
    end;
  end;
end;

function TComisionesController.BuscarFacturasDesglosadas(AFacturas: IBizFacturaCliente): IBizFacturasComision;
var
  Cadena: String;
begin
  if Assigned(AFacturas) then
  begin
    with AFacturas.DataTable do
    begin
      if not Active then Active := True;
      First;
      Cadena := '';
      While not Eof do
      begin
        if (Length(Cadena) > 0) then
          Cadena := Cadena + ', ';
        Cadena := Cadena + IntToStr(AFacturas.ID);
        Next;
      end;
    end;
  end;

//  Showmessage(Cadena);
  Result := FDataModule.GetFacturasDesglosadas;
  with Result.DataTable.Where do
  begin
    if NotEmpty then
       AddOperator(opAND);
    OpenBraket;
    AddText('ID_FACTURA in (' + Cadena + ')');
    CloseBraket;
  end;
end;

function TComisionesController.BuscarTodos: IBizComisiones;
begin
  Result := FDataModule.GetItems;
end;

constructor TComisionesController.Create;
begin
  AsignarDataModule;
  FFacturasClienteController := TFacturasClienteController.Create;  
end;

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

procedure TComisionesController.DescartarCambios(AComision: IBizComisiones);
begin
  if not Assigned(AComision) then
    raise Exception.Create ('Almacen no asignado');

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

    AComision.DataTable.CancelUpdates;
  finally
    HideHourglassCursor;
  end;
end;

destructor TComisionesController.Destroy;
begin
  FFacturasClienteController := Nil;
  FDataModule := Nil;
  inherited;
end;

function TComisionesController.ValidarComision(AComision: IBizComisiones): Boolean;
var
  AFechaPagado : TDateTime;
begin
  Result := False;

  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignada');

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

  if AComision.DataTable.FieldByName(fld_ComisionesID_AGENTE).IsNull then
     raise Exception.Create('Debe indicar el agente de esta liquidación de comisiones.');

  if AComision.DataTable.FieldByName(fld_ComisionesFECHA).IsNull then
     raise Exception.Create('Debe indicar la fecha de esta liquidación de comisiones.');

  if AComision.DataTable.FieldByName(fld_ComisionesDESCRIPCION).IsNull then
     raise Exception.Create('Debe indicar una descripción para la liquidación de comisión.');

  // Asegurarse de valores en campos "automáticos"
  AComision.Edit;
  try
    AComision.USUARIO := dmUsuarios.LoginInfo.Usuario;
    Result := True;
  finally
    AComision.Post;
  end;
end;

procedure TComisionesController.Ver(AComision: IBizComisiones);
var
  AEditor : IEditorComision;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
//    RecuperarObjetos(ARemesaCliente);

    CreateEditor('EditorComision', IEditorComision, AEditor);
    with (AEditor as IEditorComision) do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Comision := AComision;
    end;
  finally
    HideHourglassCursor;
  end;

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

procedure TComisionesController.VerTodos(AComision: IBizComisiones);
var
  AEditor : IEditorComisiones;
begin
  AEditor := NIL;
  ShowHourglassCursor;
  try
    CreateEditor('EditorComisiones', IEditorComisiones, AEditor);
    with AEditor do
    begin
      Controller := Self; //OJO ORDEN MUY IMPORTANTE
      Comisiones := AComision;
    end;
  finally
    HideHourglassCursor;
  end;

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

function TComisionesController.ElegirFacturasComision(AComision: IBizComisiones): Boolean;
var
  AFacturasAgente : IBizFacturaCliente;
  AFacturasSeleccionadas : IBizFacturaCliente;
  AFacturasDesglosadas: IBizFacturasComision;
  Cadena: String;
begin
  Result := False;

  if (AComision.ID_AGENTE <> 0) then
  begin

    if Assigned(AComision.Facturas) then
    begin
      with AComision.Facturas.DataTable do
      begin
        if not Active then Active := True;
        First;
        Cadena := '';
        While not Eof do
        begin
          if (Length(Cadena) > 0) then
            Cadena := Cadena + ', ';
          Cadena := Cadena + IntToStr(AComision.Facturas.ID_FACTURA);
          Next;
        end;
      end;
    end;

    AFacturasAgente := FFacturasClienteController.BuscarTodasPendientesComision(AComision.ID_AGENTE, AComision.ID, Cadena);
    AFacturasSeleccionadas := (FFacturasClienteController.ElegirFacturas(AFacturasAgente, 'Elija uno o más facturas para incluirlos en esta liquidación de comisiones', True) as IBizFacturaCliente);

    if Assigned(AFacturasSeleccionadas) then
    begin
       ShowHourglassCursor;
       try
         AFacturasDesglosadas := BuscarFacturasDesglosadas(AFacturasSeleccionadas);

         //Copia las facturas desglosadas de las facturas seleccionadas
         DuplicarRegistros(AFacturasDesglosadas.DataTable, AComision.Facturas.DataTable, mdrTodos, True, True, False);

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

    AFacturasAgente := Nil;
    AFacturasSeleccionadas := Nil;
    AFacturasDesglosadas := Nil;
  end
  else
    ShowWarningMessage('Debe elegir primero el agente asociado a la liquidación');
end;

function TComisionesController.Eliminar(AComision: IBizComisiones): Boolean;
begin
  Result := False;

  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignada');

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

    AComision.Delete;
    AComision.DataTable.ApplyUpdates;
    HideHourglassCursor;
    Result := True;
  finally
    HideHourglassCursor;
  end;
end;

procedure TComisionesController.EliminarFactura(AComision: IBizComisiones);
var
  IdFactura: Variant;
begin
  IdFactura := AComision.Facturas.ID_FACTURA;

  AComision.Facturas.First;
  while AComision.Facturas.DataTable.Locate('ID_FACTURA', IdFactura,[]) do
  begin
    AComision.Facturas.Delete;
    AComision.Facturas.First;
  end;
end;

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

function TComisionesController.Guardar(AComision: IBizComisiones): Boolean;
var
  NuevoID: Integer;
begin
  Result := False;

  if not Assigned(AComision) then
    raise Exception.Create ('Almacen no asignada');

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

      AsignarID(AComision, NuevoID);
      AComision.DataTable.ApplyUpdates;
      //Si todo ha ido bien, asignamos la comision a las facturas asociadas
      //Como no están declarados como maestro-detalles debemos hacer el applyupdates nosotros
//      RecibosClienteController.AsignarRemesa(ARemesaCliente.Recibos, NuevoID);
//      ARemesaCliente.Recibos.DataTable.ApplyUpdates; //En este applyupdates tambien se realizarán todos los cambios acumulados sobre los recibos asociados (EliminarReciboCliente/ ElegirRecibosCliente)

      Result := True;
    finally
      HideHourglassCursor;
    end;
  end;
end;
procedure TComisionesController.Preview(AComision: IBizComisiones; const DesglosadoProv: Boolean);
var
  AReportController : IComisionesReportController;
begin
  AReportController := TComisionesReportController.Create;
  try
    if Assigned(AComision) then
      AReportController.Preview(AComision.ID, DesglosadoProv)
    else
      AReportController.Preview(Null, DesglosadoProv)
  finally
    AReportController := NIL;
  end;
end;

procedure TComisionesController.Print(AComision: IBizComisiones; const DesglosadoProv: Boolean);
var
  AReportController : IComisionesReportController;
begin
  AReportController := TComisionesReportController.Create;
  try
    if Assigned(AComision) then
      AReportController.Preview(AComision.ID, DesglosadoProv)
    else
      AReportController.Preview(Null, DesglosadoProv);
  finally
    AReportController := NIL;
  end;
end;

end.
