unit uComisionesController;

interface


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

type
  IComisionesController = interface(IControllerBase)
  ['{0C281A5D-9DF9-46BD-99CB-1150A536EFA1}']
    function BuscarTodos: IBizComisiones;
    function Buscar(const ID: Integer): 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 Preview(AComision : IBizComisiones; AllItems: Boolean = false);
    procedure Print(AComision : IBizComisiones; AllItems: Boolean = false);
    function ExtraerSeleccionados(AComisiones: IBizComisiones) : IBizComisiones;
    function ElegirFacturasComision(AComision : IBizComisiones): Boolean;
    function ElegirVendedoresComision(AComision : IBizComisiones): Boolean;
    procedure RecalcularComisiones(AComision : IBizComisiones; Const ImporteTotal: Variant);
    procedure AsignarImporteTotal(AComision : IBizComisiones; Const ImporteTotal: Variant);
  end;

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

    procedure FiltrarEmpresa(AComisiones: IBizComisiones);

  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 AsignarDataModule; virtual;

  public
    constructor Create; override;
    destructor Destroy; override;

    function Eliminar(AComision : IBizComisiones): Boolean;
    function Guardar(AComision : IBizComisiones): Boolean;
    function Anadir(AComision : IBizComisiones): Boolean;
    function BuscarTodos: IBizComisiones;
    function Buscar(const ID: Integer): IBizComisiones;
    procedure VerTodos(AComision: IBizComisiones);
    procedure Ver(AComision: IBizComisiones);
    procedure Preview(AComision : IBizComisiones; AllItems: Boolean = false);
    procedure Print(AComision : IBizComisiones; AllItems: Boolean = false);
    function ExtraerSeleccionados(AComisiones: IBizComisiones) : IBizComisiones;
    function ElegirFacturasComision(AComision : IBizComisiones): Boolean;
    function ElegirVendedoresComision(AComision : IBizComisiones): Boolean;
    procedure RecalcularComisiones(AComision : IBizComisiones; Const ImporteTotal: Variant);
    procedure AsignarImporteTotal(AComision : IBizComisiones; Const ImporteTotal: Variant);
  end;

implementation

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

  uBizContactos, uVendedoresController, uBizFacturasCliente, uFacturasClienteController;

{ 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);
var
  EnEdicion: Boolean;
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
      EnEdicion:= AComision.DataTable.Editing;
      if not EnEdicion then
         AComision.DataTable.Edit;

      AComision.IMPORTE_TOTAL := ImporteTotal;
      AComision.DataTable.Post;

      if EnEdicion then
         AComision.DataTable.Edit;

//      Recalcular
    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.Buscar(const ID: Integer): IBizComisiones;
begin
  Result := (FDataModule as IDataModuleComisiones).GetItem(ID);
  FiltrarEmpresa(Result);
end;

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

constructor TComisionesController.Create;
begin
  inherited;
  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;

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;

  //Tambien hacemos post de sus tablas hija
  if (AComision.Facturas.DataTable.State in dsEditModes) then
      AComision.Facturas.DataTable.Post;

  if (AComision.Vendedores.DataTable.State in dsEditModes) then
      AComision.Vendedores.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 := AppFactuGES.UsuarioActivo.UserName;
    Result := True;
  finally
    AComision.Post;
  end;
end;

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

  CreateEditor('EditorComision', IEditorComision, AEditor);
  if Assigned(AEditor) then
    try
       AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
       AEditor.Comision := AComision;
       AEditor.ShowModal;
    finally
       AEditor.Release;
       AEditor := NIL;
    end;
end;

procedure TComisionesController.VerTodos(AComision: IBizComisiones);
var
  AEditor : IEditorComisiones;
begin
  AEditor := NIL;

  CreateEditor('EditorComisiones', IEditorComisiones, AEditor);
  if Assigned(AEditor) then
     with AEditor do
     begin
       Controller := Self; //OJO ORDEN MUY IMPORTANTE
       Comisiones := AComision;
       ShowEmbedded;
     end;
end;

function TComisionesController.ElegirFacturasComision(AComision: IBizComisiones): Boolean;
var
  AFacturasSeleccionadas : IBizFacturaCliente;
  AFacturasController: IFacturasClienteController;
  Cadena: TStringList;

begin
  Result := False;

  if Assigned(AComision.Facturas) then
  begin
    //Recogemos los id de las facturas que ya tiene asociada la liquidación
    with AComision.Facturas.DataTable do
    begin
      if not Active then Active := True;
      First;
      Cadena := TStringList.Create;
      While not Eof do
      begin
        Cadena.Add(IntToStr(AComision.Facturas.ID));
        Next;
      end;
    end;

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

      if Assigned(AFacturasSeleccionadas) then
      begin
        ShowHourglassCursor;
        try
          //Copia las facturas desglosadas de las facturas seleccionadas
          DuplicarRegistros(AFacturasSeleccionadas.DataTable, AComision.Facturas.DataTable, mdrTodos, True, True, True);
          Result := True;
        finally
          HideHourglassCursor;
        end;
      end;

    finally
      Cadena.Free;
      AFacturasController := Nil;
      AFacturasSeleccionadas := Nil;
    end;
  end;
end;


function TComisionesController.ElegirVendedoresComision(AComision: IBizComisiones): Boolean;
var
  AVendedoresSeleccionados : IBizContacto;
  AVendedoresController : IVendedoresController;
  Cadena: TStringList;

begin
  Result := False;

  if Assigned(AComision.Vendedores) then
  begin
    //Recogemos los id de los vendedores que ya tiene asociada la liquidación
    with AComision.Vendedores.DataTable do
    begin
      if not Active then Active := True;
      First;
      Cadena := TStringList.Create;
      While not Eof do
      begin
        Cadena.Add(IntToStr(AComision.Vendedores.ID_VENDEDOR));
        Next;
      end;
    end;

    AVendedoresController := TVendedoresController.Create;
    try
      AVendedoresSeleccionados := AVendedoresController.BuscarTodos(Cadena.CommaText);
      AVendedoresSeleccionados := AVendedoresController.ElegirContacto(AvendedoresSeleccionados, 'Elija los vendedores de la comision', True);

      if Assigned(AVendedoresSeleccionados) then
      begin
        ShowHourglassCursor;
        try
          //Copia los vendedores seleccionados
          DuplicarRegistros(AVendedoresSeleccionados.DataTable, AComision.Vendedores.DataTable, mdrTodos, True, True, False);

          //Copiamos el ID de los vendedores seleccionados en ID_VENDEDOR de la tabla detalle
          AVendedoresSeleccionados.DataTable.First;
          AComision.Vendedores.DataTable.First;
          while not AVendedoresSeleccionados.DataTable.EOF do
          begin
            if not AComision.Vendedores.DataTable.Editing then
               AComision.Vendedores.DataTable.Edit;

            AComision.Vendedores.ID_VENDEDOR := AVendedoresSeleccionados.ID;
            AComision.Vendedores.DataTable.Post;

            AVendedoresSeleccionados.DataTable.Next;
            AComision.Vendedores.DataTable.Next;
          end;
          AComision.Vendedores.DataTable.First;

          Result := True;
        finally
          HideHourglassCursor;
        end;
      end;
    finally
      Cadena.Free;
      AVendedoresController := Nil;
      AVendedoresSeleccionados := Nil;
    end;
  end;
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;

function TComisionesController.ExtraerSeleccionados(AComisiones: IBizComisiones): IBizComisiones;
var
  ASeleccionados : IBizComisiones;
begin
  ASeleccionados := (Self.Buscar(ID_NULO) as IBizComisiones);
  CopyDataTableDA5(AComisiones.DataTable, ASeleccionados.DataTable, True);
  Result := ASeleccionados;

end;

procedure TComisionesController.FiltrarEmpresa(AComisiones: IBizComisiones);
var
  Condicion: TDAWhereExpression;
begin
  if AComisiones.DataTable.Active then
     AComisiones.DataTable.Active := False;

  // Filtrar las facturas actuales por empresa
  with AComisiones.DataTable.DynamicWhere do
  begin
    // (ID_EMPRESA >= ID)
    Condicion := NewBinaryExpression(NewField('', fld_ComisionesID_EMPRESA), NewConstant(AppFactuGES.EmpresaActiva.ID, datInteger), dboEqual);

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

procedure TComisionesController.RecalcularComisiones(AComision: IBizComisiones; const ImporteTotal: Variant);
begin
  if Assigned(AComision)
  and Assigned(AComision.Vendedores)
  and (not AComision.Vendedores.IsEmpty) then
  begin
    AComision.Vendedores.DataTable.DisableControls;
    try
      AComision.Vendedores.DataTable.First;
      while not AComision.Vendedores.DataTable.EOF do
      begin
        AComision.Vendedores.Edit;
        AComision.Vendedores.IMPORTE_TOTAL := ((AComision.Vendedores.COMISION / 100) * ImporteTotal);
        AComision.Vendedores.Post;
        AComision.Vendedores.DataTable.Next;
      end;
    finally
      AComision.Vendedores.DataTable.EnableControls;
    end;
  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 ('Comision no asignada');

  if ValidarComision(AComision) then
  begin
    ShowHourglassCursor;
    try
      AComision.DataTable.ApplyUpdates;

      Result := True;
    finally
      HideHourglassCursor;
    end;
  end;
end;
procedure TComisionesController.Preview(AComision: IBizComisiones; AllItems: Boolean = false);
var
  AReportController : IComisionesReportController;
  ID_Comisiones: TStringList;

begin
  AReportController := TComisionesReportController.Create;
  try
   ID_Comisiones := TStringList.Create;

   //Si deseamos previsualizar todos los items del objeto comision
   if AllItems then
   begin
     with AComision.DataTable do
     begin
       First;
       while not EOF do
       begin
         ID_Comisiones.Add(IntToStr(AComision.ID));
         Next;
       end;
     end;
   end
   //Solo previsualizamos el item seleccionado
   else
     ID_Comisiones.Add(IntToStr(AComision.ID));

    AReportController.Preview(ID_Comisiones.CommaText);

  finally
    AReportController := NIL;
    ID_Comisiones.Free;
  end;
end;

procedure TComisionesController.Print(AComision: IBizComisiones; AllItems: Boolean = false);
var
  AReportController : IComisionesReportController;
  ID_Comisiones: TStringList;

begin
  AReportController := TComisionesReportController.Create;
  try
   ID_Comisiones := TStringList.Create;

   //Si deseamos previsualizar todos los items del objeto comision
   if AllItems then
   begin
     with AComision.DataTable do
     begin
       First;
       while not EOF do
       begin
         ID_Comisiones.Add(IntToStr(AComision.ID));
         Next;
       end;
     end;
   end
   //Solo previsualizamos el item seleccionado
   else
     ID_Comisiones.Add(IntToStr(AComision.ID));

    AReportController.Print(ID_Comisiones.CommaText);

  finally
    AReportController := NIL;
    ID_Comisiones.Free;
  end;
end;

end.
