unit uComisionesController;

interface


uses
  Classes, SysUtils, uDADataTable, uControllerBase, uIDataModuleComisiones,
  //uDetallesFacturaClienteController,
  uBizComisiones;

type
  IComisionesController = interface(IControllerBase)
  ['{A6452334-2891-4CF4-A018-E7E8BE3B11E7}']

    function Buscar(const ID: Integer): IBizComision;
    function BuscarTodos: IBizComision; overload;
//    function BuscarTodos(const AID_Cliente: Integer): IBizComision; overload;
    procedure Ver(AComision : IBizComision);
    procedure VerTodos(AComisiones: IBizComision;
      const AVerModal : Boolean = False; const AWindowCaption: String = '';
      const AHeaderText: String = '');
    function Nuevo (withInsert: Boolean = True) : IBizComision;
    function Anadir(AComision : IBizComision) : Boolean; overload;
    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AComision : IBizComision; AllItems: Boolean = false): Boolean; overload;
    function Guardar(AComision : IBizComision): Boolean;
    procedure DescartarCambios(AComision : IBizComision);
    function Existe(const ID: Integer) : Boolean;

    procedure Preview(AComision : IBizComision; AllItems: Boolean = false);
    procedure Print(AComision : IBizComision; AllItems: Boolean = false);

    procedure RecalcularImportes(AComision: IBizComision);
    function EsModificable(AComision: IBizComision): Boolean;
    function EsEliminable(AComision: IBizComision): Boolean;

    function ElegirFacturasComision(AComision : IBizComision): Boolean;
    function ExtraerSeleccionados(AComisiones: IBizComision) : IBizComision;

    function DarListaAnosComisiones: TStringList;
    procedure FiltrarAno(AComision: IBizComision; ADynWhereDataTable: WideString; const Ano: String);
  end;

  TComisionesController = class(TControllerBase, IComisionesController)
  private
    FDataModule : IDataModuleComisiones;

    function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
    function _Vacio : IBizComision;

    procedure FiltrarEmpresa(AComision: IBizComision);
    function ValidarComision(AComision: IBizComision): Boolean;

  protected
    procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override;

  public
    constructor Create; override;
    destructor Destroy; override;

    function Eliminar(const ID : Integer): Boolean; overload;
    function Eliminar(AComision : IBizComision; AllItems: Boolean = false): Boolean; overload;
    function Guardar(AComision : IBizComision): Boolean;
    procedure DescartarCambios(AComision : IBizComision); virtual;
    function Existe(const ID: Integer) : Boolean; virtual;
    function Anadir(AComision : IBizComision): Boolean; overload;
//    function Anadir(AComisions : IBizComision; AListaAlbaranes : IBizAlbaranCliente): Boolean; overload;
//    function Anadir(AComision : IBizComision; const IDPedido : Integer): Boolean; overload;
    function Buscar(const ID: Integer): IBizComision;
    function BuscarTodos: IBizComision; overload;
//    function BuscarTodos(const AID_Cliente: Integer): IBizComision; overload;
//    function BuscarTodasPendientesComision(IdAgente: Integer; IdComision: Integer; IdFacturasAsociadas: String): IBizComision;
    function Nuevo (withInsert: Boolean = True) : IBizComision;
    procedure Ver(AComision : IBizComision);
    procedure VerTodos(AComisiones: IBizComision;
      const AVerModal : Boolean = False; const AWindowCaption: String = '';
      const AHeaderText: String = '');

    procedure Preview(AComision : IBizComision; AllItems: Boolean = false);
    procedure Print(AComision : IBizComision; AllItems: Boolean = false);

    procedure RecalcularImportes(AComision: IBizComision);
    function EsModificable(AComision: IBizComision): Boolean;
    function EsEliminable(AComision: IBizComision): Boolean;

    function ElegirFacturasComision(AComision : IBizComision): Boolean;
    function ExtraerSeleccionados(AComisiones: IBizComision) : IBizComision;

    function DarListaAnosComisiones: TStringList;
    procedure FiltrarAno(AComision: IBizComision; ADynWhereDataTable: WideString; const Ano: String);
  end;

implementation

uses
  Dialogs, uDialogUtils, Windows, Controls, cxControls, DB, uEditorRegistryUtils, schComisionesClient_Intf,
  uBizContactos, uIEditorComisiones, uIEditorComision, uFactuGES_App,
  uDataModuleComisiones, uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uDateUtils, uNumUtils,
  uROTypes, DateUtils, Forms, uIntegerListUtils, uSistemaFunc, uDialogElegirEMail, uEMailUtils, uStringsUtils,
  uROXMLIntf, uBizFacturasCliente, uFacturasClienteController, uComisionesReportController;


{procedure CopiarArticulosPedido(AOrigen: IBizDetallesPedidoCliente;
  ADestino : IBizDetallesFacturaCliente);
var
  i : integer;
  ADetallesController : IDetallesFacturaClienteController;
begin
  if not Assigned(AOrigen) then
    raise Exception.Create ('Origen no asignado (CopiarArticulosPedido)');

  if not Assigned(ADestino) then
    raise Exception.Create ('Destino no asignado (CopiarArticulosPedido)');

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

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

  ADetallesController := TDetallesFacturaClienteController.Create;
  try
      //OJO IMPORTANTE
      //Siempre que vayamos a trabajar con los detalles debemos hacer un beginupdate de los mismos y un endupdate para
      //obligarle siempre a recalcular los detalles una sola vez
      ADetallesController.BeginUpdate(ADestino);

    AOrigen.DataTable.First;
    for i := 0 to AOrigen.DataTable.RecordCount - 1 do
    begin
      ADetallesController.Add(ADestino, TIPO_DETALLE_CONCEPTO);
      ADestino.Edit;
      ADestino.REFERENCIA := AOrigen.REFERENCIA;
      if AOrigen.ID_ARTICULO > 0 then
         ADestino.ID_ARTICULO := AOrigen.ID_ARTICULO;
      ADestino.CONCEPTO := AOrigen.CONCEPTO;
      ADestino.CANTIDAD := AOrigen.CANTIDAD;
      ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_UNIDAD;
      ADestino.IMPORTE_TOTAL := AOrigen.IMPORTE_TOTAL;
      ADestino.DESCUENTO := AOrigen.DESCUENTO;
      ADestino.IMPORTE_PORTE := AOrigen.IMPORTE_PORTE;
      ADestino.VISIBLE := AOrigen.VISIBLE;
      ADestino.REFERENCIA_PROVEEDOR := AOrigen.REFERENCIA_PROVEEDOR;
      ADestino.Post;
      AOrigen.Next;
    end;
  finally
      ADetallesController.EndUpdate(ADestino);
    ADetallesController := NIL;
  end;
end;}



{ TComisionesController }

function TComisionesController.Anadir(AComision: IBizComision) : Boolean;
begin
  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignada (Anadir)');
  AComision.Insert;
  Result := True;
end;

{
function TComisionesController.Anadir(AComisions: IBizComision;
  AListaAlbaranes: IBizAlbaranCliente): Boolean;
var
  AComisionActual : IBizComision;
  AAlbaranesController : IAlbaranesClienteController;
  I: Integer;
  bEnEdicion : Boolean;
begin
  // ATENCIÓN!!! AComisions tiene que estar vacio para no pisar facturas
  // ya generadas.
  if not Assigned(AComisions) then
    raise Exception.Create ('Factura no asignada (Anadir)');

  if not Assigned(AListaAlbaranes) then
    raise Exception.Create ('Albaranes no asignados (Anadir)');

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

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

  ShowHourglassCursor;
  Application.ProcessMessages;

  AAlbaranesController := TAlbaranesClienteController.Create;
  try
    // Ordenar por fecha de albaran
    AListaAlbaranes.DataTable.Sort([fld_AlbaranesClienteFECHA_ALBARAN], [uDADataTable.sdAscending]);
    AListaAlbaranes.First;
    for I := 0 to AListaAlbaranes.DataTable.RecordCount - 1 do
    begin
      AListaAlbaranes._Cliente := NIL;
      AComisionActual := NIL;

      // Busco si hay alguna factura ya hecha de ese cliente
      AComisions.DataTable.First;
      if AComisions.DataTable.Locate(fld_ComisionesID_CLIENTE, AListaAlbaranes.ID_CLIENTE, []) then
      begin
        AComisionActual := AComisions;
        RecuperarCliente(AComisionActual);
        AComisionActual.Cliente.DataTable.Active := True;
      end
      else begin
        // No hay factura de ese cliente. Creo una nueva
        Anadir(AComisions);
        AAlbaranesController.RecuperarCliente(AListaAlbaranes);
        AListaAlbaranes.Cliente.DataTable.Active := True;
        AComisions.Cliente := AListaAlbaranes.Cliente;

        //Si el albaran es de tipo devolución hacemos la factura de tipo abono
        if (AListaAlbaranes.TIPO = CTE_TIPO_ALBARAN_DEV) then
        begin
          bEnEdicion := (AComisions.DataTable.State in dsEditModes);
          if not bEnEdicion then
             AComisions.Edit;
          AComisions.TIPO := CTE_TIPO_ABONO;
          AComisions.Post;
          if bEnEdicion then
             AComisions.Edit;
        end;

        AComisionActual := AComisions;
      end;

      // Ya tengo la factura. Le añado los conceptos del albarán
      AComisionActual.Detalles.DataTable.Last;
      // Añado el título
      Self.DetallesController.Add(AComisionActual.Detalles, TIPO_DETALLE_TITULO);
      with AComisionActual.Detalles do
      begin
        Edit;
        CONCEPTO := 'Albarán ' + AListaAlbaranes.REFERENCIA + ' del ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN);
        Post;
      end;
      // Añado el contenido del albarán
      CopiarArticulosAlbaran(AListaAlbaranes.Detalles, AComisionActual.Detalles);

      Self.DetallesController.Add(AComisionActual.Detalles, TIPO_DETALLE_CONCEPTO);
      with AComisionActual.Detalles do
      begin
        Edit;
        CONCEPTO := 'Porte del albarán';
        CANTIDAD := 1;
        IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_PORTE;
        Post;
      end;

      // Añado el resumen
      Self.DetallesController.Add(AComisionActual.Detalles, TIPO_DETALLE_SUBTOTAL);
      with AComisionActual.Detalles do
      begin
        Edit;
        CONCEPTO := 'Total del albarán ' + AListaAlbaranes.REFERENCIA;
        Post;
      end;

      // Añado una línea en blanco
      Self.DetallesController.Add(AComisionActual.Detalles, TIPO_DETALLE_CONCEPTO);
      with AComisionActual.Detalles do
      begin
        Edit;
        CONCEPTO := '';
        Post;
      end;

      // Guardo la factura que acabo de generar o editar
      AComisionActual.CalcularImporteTotal;
      Self.Guardar(AComisionActual);
      // Asocio la factura con el albarán
      AListaAlbaranes.Edit;
      AListaAlbaranes.ID_FACTURA := AComisionActual.ID;
      AListaAlbaranes.Post;
      AAlbaranesController.Guardar(AListaAlbaranes);

      AListaAlbaranes.Next;
    end;
    Result := True;
  finally
    AAlbaranesController := NIL;
    HideHourglassCursor
  end;
end;
}

{function TComisionesController.Anadir(AComision: IBizComision;
  const IDPedido: Integer): Boolean;
var
  APedidosController : IPedidosClienteController;
  APedido : IBizPedidoCliente;
begin
  Result := False;
  if not Assigned(AComision) then
    raise Exception.Create ('Factura no asignada (Anadir)');

  if (IDPedido < 0) or (IDPedido = 0) then
    raise Exception.Create (Format('ID de pedido (%d) incorrecto (Anadir)', [IDPedido]));

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

  ShowHourglassCursor;
  Application.ProcessMessages;

  APedido := NIL;
  APedidosController := TPedidosClienteController.Create;
  try
    APedido := APedidosController.Buscar(IDPedido);

    if not Assigned(APedido) then
      raise Exception.Create (Format('No se ha encontrado un pedido de cliente con ID %d (Anadir)', [IDPedido]));

    APedido.DataTable.Active := True;
    APedidosController.RecuperarCliente(APedido);
    Self.Anadir(AComision);
    AComision.Cliente := APedido.Cliente;

    CopiarArticulosPedido(APedido.Detalles, AComision.Detalles);

    // Guardo la factura que acabo de generar
    AComision.CalcularImporteTotal;
    Self.Guardar(AComision);

    Result := True;
  finally
    APedido := NIL;
    APedidosController := NIL;
    HideHourglassCursor;
    Application.ProcessMessages;
  end;
end;}


function TComisionesController.Buscar(const ID: Integer): IBizComision;
begin
  Result := (FDataModule as IDataModuleComisiones).GetItem(ID);
  FiltrarEmpresa(Result);
end;

{
function TComisionesController.BuscarTodasPendientesComision(IdAgente:Integer; IdComision: Integer; IdFacturasAsociadas: String): IBizComision;
var
  Condicion: TDAWhereExpression;
begin
  ShowHourglassCursor;
  try
    Result := BuscarTodos;
    with Result.DataTable.DynamicWhere do
    begin
      //Todas las facturas de un agente determinado
      Condicion := NewBinaryExpression(NewField('', fld_ComisionesID_AGENTE), NewConstant(IdAgente, datInteger), dboEqual);

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

    with Result.DataTable.DynamicWhere do
    begin
      //Todas aquellas que no esten asociadas a ninguna comisión o asociadas a la comisión,
      //pero no asociadas en el editor de la comision, esto es porque se puede agregar y quitar
      //facturas y todos los cambios estan el cache y por lo tanto al pedir las facturas a seleccionar
      //debemos tener en cuenta dichso cambios en cache
      Condicion := NewBinaryExpression(NewField('', fld_ComisionesID_COMISION_LIQUIDADA), NewNull(), dboEqual);

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

{REPASARRRRRRR
    //Quitamos aquellas que ya están asociadas
    if length(IdFacturasAsociadas) > 0 then
       with Result.DataTable.DynamicWhere do
       begin
         Condicion := NewBinaryExpression(NewField('', fld_ComisionesID), ' not in (' + IdFacturasAsociadas + ')');, dboEqual);

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

    with Result.DataTable.Where do
    begin

        CLOSEBraket;
        AddOperator(opOR);

        OpenBraket;
          //En caso de ser facturas ya asociadas lo limitamos a la comision actual
          //ya que no debemos poder elegir facturas asociadas a otras comisiones
          OpenBraket;
          AddText(fld_ComisionesID_COMISION_LIQUIDADA + ' = ' + IntToStr(IdComision));
          CloseBraket;
          //En el caso de que halla facturas asociadas
          if length(IdFacturasAsociadas) > 0 then
          begin
            AddOperator(opAND);
            OpenBraket;
            AddText(fld_ComisionesID + ' not in (' + IdFacturasAsociadas + ')');
            CloseBraket;
          end;
        CloseBraket;

      CloseBraket;
    end;

  finally
    HideHourglassCursor;
  end;
end;
}

{
function TComisionesController.BuscarTodos(
  const AID_Cliente: Integer): IBizComision;
var
  Condicion: TDAWhereExpression;
begin
  ShowHourglassCursor;
  try
    Result := BuscarTodos;

    with Result.DataTable.DynamicWhere do
    begin
      // ID_CLIENTE
      Condicion := NewBinaryExpression(NewField('', fld_ComisionesID_CLIENTE), NewConstant(AID_Cliente, datInteger), dboEqual);

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

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

constructor TComisionesController.Create;
begin
  inherited;
  FDataModule := TDataModuleComisiones.Create(Nil);
//  FDetallesController := TDetallesFacturaClienteController.Create;
//  FDetallesController.addObservador(Self);
end;

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

function TComisionesController.DarListaAnosComisiones: TStringList;
begin
  Result := FDataModule.GetAnosItems;
end;

procedure TComisionesController.DescartarCambios(AComision: IBizComision);
begin
  if not Assigned(AComision) then
    raise Exception.Create ('Comision no asignada');

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

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

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

function TComisionesController.ValidarComision(AComision: IBizComision): Boolean;
begin
  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.FacturasComision.DataTable.State in dsEditModes) then
      AComision.FacturasComision.DataTable.Post;

  if (AComision.ID_AGENTE < 0) or (AComision.ID_AGENTE = 0) then
  // No comprobar el objeto Cliente por que puede fallar la validación
  // cuando se generan facturas automáticamente.
{     (not Assigned(AComision.Cliente)) or
     (AComision.Cliente.IsEmpty) then}
    raise Exception.Create('Debe indicar el vendedor de esta comision');

  if (EsFechaVacia(AComision.FECHA)) then
    raise Exception.Create('Debe indicar la fecha de esta comision');

  if (AComision.FacturasComision.DataTable.RecordCount = 0) then
    raise Exception.Create('La comisión debe tener al menos una factura en su contenido');

  { Asegurarse de valores en campos "automáticos" tanto
    en MODIFICACIÓN como en INSERCIÓN. }
  AComision.Edit;
  try
    AComision.USUARIO := AppFactuGES.UsuarioActivo.UserName;
    Result := True;
  finally
    AComision.Post;
  end;
end;

procedure TComisionesController.Ver(AComision: IBizComision);
var
  AEditor : IEditorComision;
begin
  AEditor := NIL;

  CreateEditor('EditorComision', IEditorComision, AEditor);

  if Assigned(AEditor) then
    try
        AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
        AEditor.Comision := AComision;

        //MODO CONSULTAR
        if not EsModificable(AComision) then
        begin
           SetDataTableReadOnly(AComision.DataTable, True);
           AEditor.ReadOnly := True;
        end;

        AEditor.ShowModal;

        //MODO CONSULTAR (Se deja la tabla como estaba)
        if AEditor.ReadOnly then
           SetDataTableReadOnly(AComision.DataTable, False);
    finally
      AEditor.Release;
      AEditor := NIL;
    end;
end;

procedure TComisionesController.VerTodos(AComisiones: IBizComision;
  const AVerModal : Boolean = False; const AWindowCaption: String = '';
  const AHeaderText: String = '');
var
  AEditor : IEditorComisiones;
begin
  AEditor := NIL;

  CreateEditor('EditorComisiones', IEditorComisiones, AEditor);
  if Assigned(AEditor) then
    try
      if not EsCadenaVacia(AWindowCaption) then
        AEditor.WindowCaption := AWindowCaption;

      if not EsCadenaVacia(AHeaderText) then
        AEditor.HeaderText := AHeaderText;

      AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
      AEditor.Comisiones := AComisiones;
      AEditor.MultiSelect := True;
      if AVerModal then
        AEditor.ShowModal
      else
        AEditor.ShowEmbedded;
    finally
      if AVerModal then
        AEditor.Release;
      AEditor := Nil;
    end;
end;

function TComisionesController._Vacio: IBizComision;
begin
  Result := Buscar(ID_NULO);
end;

function TComisionesController.Eliminar(const ID: Integer): Boolean;
var
  AComision : IBizComision;
begin
  AComision := Buscar(ID);

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

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

{
function TComisionesController.ElegirComisiones(AComisions: IBizComision; AMensaje: String;
  AMultiSelect: Boolean): IBizComision;
var
  AEditor : IEditorElegirComisiones;
begin
  Result := NIL;

  CreateEditor('EditorElegirComisiones', IEditorElegirComisiones, AEditor);
  if Assigned(AEditor) then
    try
       AEditor.Controller := Self;
       AEditor.Facturas := AComisions;
       AEditor.MultiSelect := AMultiSelect;
       AEditor.Mensaje := AMensaje;
       if IsPositiveResult(AEditor.ShowModal) then
          Result := AEditor.ComisionesSeleccionados;
    finally
       AEditor.Release;
       AEditor := NIL;
    end;
end;
}

function TComisionesController.ElegirFacturasComision(AComision: IBizComision): Boolean;
var
  AFacturasClienteController: IFacturasClienteController;
  AFacturasAgente : IBizFacturaCliente;
  AFacturasSeleccionadas : IBizFacturaCliente;
  Cadena: String;
  
begin
  Result := False;

  if (AComision.ID_AGENTE <> 0) then
  begin

    if Assigned(AComision.FacturasComision) then
    begin
      with AComision.FacturasComision.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.FacturasComision.ID);
          Next;
        end;
      end;
    end;

    AFacturasClienteController := TFacturasClienteController.Create;
    AFacturasAgente := AFacturasClienteController.BuscarTodasPendientesComision(AComision.ID_AGENTE, AComision.ID, Cadena);
    AFacturasSeleccionadas := (AFacturasClienteController.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
         //Copia las facturas seleccionadas de las facturas de la comision
         DuplicarRegistros(AFacturasSeleccionadas.DataTable, AComision.FacturasComision.DataTable, mdrTodos, True, True, True);
         Result := True;
       finally
         HideHourglassCursor;
       end;
    end;

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

function TComisionesController.Eliminar(AComision: IBizComision; AllItems: Boolean = false): Boolean;
//En el caso de eliminar almenos un elemento del conjunto se devuelve true
var
  bEliminado: Boolean;

begin
//Importante revisar que existe la FK_FACTURAS_CLIENTE_COMISION ya que cuando se elimina la cabecera es lo que funciona
//no funciona el comando deletefacturascomision por business

  bEliminado := False;

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

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

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

    //Siempre eliminaremos el seleccionado
    if EsEliminable(AComision) then
    begin
      AComision.Delete;
      bEliminado := True;
    end;

    //En el caso de querer eliminar todos los items del objeto AAlbaran
    if AllItems then
    begin
       with AComision.DataTable do
       begin
         First;
         while not EOF do
         begin
           if EsEliminable(AComision) then
           begin
              AComision.Delete;
              bEliminado := True
           end
           else Next;
         end;
       end;
    end;

    if bEliminado then
    begin
      try
      AComision.DataTable.ApplyUpdates;
      Result := True
      except
        //En el caso de una factura que tiene recibos con devoluciones hechas no se puede borrar aunque la factura este en situacion de pendiente
        AComision.DataTable.CancelUpdates;
        Result := False;        
      end;
    end
    else
       Result := False;

  finally
    HideHourglassCursor;
  end;
end;

function TComisionesController.EsEliminable(AComision: IBizComision): Boolean;
begin
  Result := EsModificable(AComision);
end;

function TComisionesController.EsModificable(AComision: IBizComision): Boolean;
begin
  Result := True;
end;

procedure TComisionesController.RecalcularImportes(
  AComision: IBizComision);
var
  bEnEdicion : Boolean;
  ADetallePosAct : Integer;
begin
{
  if not Assigned(AComision) then
    raise Exception.Create ('Factura no asignado (RecalcularImportes)');

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

  { Hay que guardar la posición en la que estamos en los detalles por que
    la asignación de valores a los campos IMPORTE_NETO e IMPORTE_PORTE
    (ver más adelante) colocan el puntero en la tabla detalle al principio.
    No he encontrado la razón por la que mueve el puntero. }
{
  ADetallePosAct := AComision.Detalles.POSICION;

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

  ShowHourglassCursor;
  try
    AComision.IMPORTE_NETO := FDetallesController.DarTotalImporteTotal(AComision.Detalles);
    AComision.IMPORTE_PORTE := FDetallesController.DarTotalPorteTotal(AComision.Detalles);

    if not bEnEdicion then
      AComision.Post;
  finally
    HideHourglassCursor;
    // Restaurar la posición que teníamos en los detalles.
    FDetallesController.LocalizarPosicion(AComision.Detalles, ADetallePosAct);
  end;
}  
end;

procedure TComisionesController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable);
var
  AComision : IBizComision;
  AFacturasComision : IBizFacturasComision;
begin
  inherited;

  if Supports(ADataTable, IBizFacturasComision, AFacturasComision) and
     Supports(AFacturasComision.DataTable.MasterSource.DataTable, IBizComision, AComision) then
  begin
    RecalcularImportes(AComision);
  end;
end;

function TComisionesController.Existe(const ID: Integer): Boolean;
var
  AComision : IBizComision;
begin
  try
    AComision := Buscar(ID);
    Result := Assigned(AComision) and (AComision.ID = ID);
  finally
    AComision := NIL;
  end;
end;

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

procedure TComisionesController.FiltrarAno(AComision: IBizComision; ADynWhereDataTable: WideString; const Ano: String);
var
  Condicion: TDAWhereExpression;
  FechaIni: String;
  FechaFin: String;

begin
  AComision.DataTable.DynamicWhere.Clear;
  AComision.DataTable.DynamicWhere.Xml := ADynWhereDataTable;

  if (Ano <> 'Todos') then
  begin
    // Filtrar las facturas actuales por empresa
    FechaIni := '01/01/' + Ano;
    FechaFin := '31/12/' + Ano;
    with AComision.DataTable.DynamicWhere do
    begin
      // (FECHA_INICIO between FECHA_FIN)
      Condicion := NewBinaryExpression(NewField('', fld_ComisionesFECHA), NewConstant(FechaIni, datString), dboGreaterOrEqual);
      Condicion := NewBinaryExpression(NewBinaryExpression(NewField('', fld_ComisionesFECHA), NewConstant(FechaFin, datString), dboLessOrEqual), Condicion, dboAnd);

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

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

  // Filtrar las comisiones actuales por empresa
  with AComision.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;

function TComisionesController.Guardar(AComision: IBizComision): Boolean;
begin
  Result := False;

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

  if ValidarComision(AComision) then
  begin
    ShowHourglassCursor;

    // Asegurarnos de que todos los importes están bien.
    RecalcularImportes(AComision);

    try
      AComision.DataTable.ApplyUpdates;

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

function TComisionesController.Nuevo(withInsert: Boolean = True): IBizComision;
var
  AComision : IBizComision;
begin
  AComision := FDataModule.NewItem;
  FiltrarEmpresa(AComision);
  AComision.DataTable.Active := True;
  if WithInsert then
     AComision.Insert;
  Result := AComision;
end;

procedure TComisionesController.Preview(AComision: IBizComision; AllItems: Boolean = false);
var
  AReportController : IComisionesReportController;
  ID_Comisiones: TIntegerList;

begin
  AReportController := TComisionesReportController.Create;
  ID_Comisiones := TIntegerList.Create;

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

    AReportController.Preview(ID_Comisiones);

  finally
    AReportController := NIL;
    FreeANDNIL(ID_Comisiones);
  end;
end;

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

begin
  AReportController := TComisionesReportController.Create;
  ID_Comisiones := TIntegerList.Create;

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

    AReportController.Print(ID_Comisiones);

  finally
    AReportController := NIL;
    FreeANDNIL(ID_Comisiones);
  end;
end;

end.
