unit uEditorPedidoCliente;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uEditorDBItem, DB, uDADataTable, JvAppStorage,
  JvAppRegistryStorage, JvComponent, JvFormPlacement, ImgList,
  PngImageList, StdActns, ActnList, ComCtrls, TBX, TB2Item, TB2Dock,
  TB2Toolbar, ExtCtrls, JvExControls, JvNavigationPane,
  uViewPedidoCliente, uCustomView, uViewBase, JvComponentBase,
  StdCtrls, pngimage, AppEvnts, cxControls, cxContainer, cxEdit, cxTextEdit, cxMemo, cxDBEdit,
  uViewIncidencias,
  uBizPedidosCliente, uIEditorPedidoCliente, uPedidosClienteController,
  uViewDetallesBase, uViewDetallesPedidoCliente,
  dxLayoutLookAndFeels, JvExComCtrls, JvStatusBar, uViewTotales,
  uViewDetallesDTO, uViewDetallesArticulos, uDAInterfaces, cxLabel;

type
  TfEditorPedidoCliente = class(TfEditorDBItem, IEditorPedidoCliente)
    pagContenido: TTabSheet;
    pagInicidencias: TTabSheet;
    frViewIncidenciasProv: TfrViewIncidencias;
    dxLayoutLookAndFeelList1: TdxLayoutLookAndFeelList;
    dxLayoutOfficeLookAndFeel1: TdxLayoutOfficeLookAndFeel;
    frViewTotales1: TfrViewTotales;
    TBXSubmenuItem2: TTBXSubmenuItem;
    TBXItem7: TTBXItem;
    actEnviarEMail: TAction;
    TBXSeparatorItem6: TTBXSeparatorItem;
    TBXItem33: TTBXItem;
    frViewDetallesPedidoCliente1: TfrViewDetallesPedidoCliente;
    frViewPedidoCliente1: TfrViewPedidoCliente;

    procedure FormShow(Sender: TObject); 
    procedure CustomEditorClose(Sender: TObject; var Action: TCloseAction);
    procedure pgPaginasChanging(Sender: TObject; var AllowChange: Boolean);
    procedure frViewTotales1ePortePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure actEnviarEMailUpdate(Sender: TObject);
    procedure actEnviarEMailExecute(Sender: TObject);
  private
    procedure RecalcularPortePorUnidad;

  protected
    FPedido: IBizPedidoCliente;
    FViewPedido: IViewPedidoCliente;
    FController : IPedidosClienteController;

    function GetController : IPedidosClienteController;
    procedure SetController (const Value : IPedidosClienteController); virtual;

    function GetPedido: IBizPedidoCliente;
    procedure SetPedido(const Value: IBizPedidoCliente); virtual;

    function GetViewPedido: IViewPedidoCliente;
    procedure SetViewPedido(const Value: IViewPedidoCliente);

    procedure GuardarInterno; override;
    procedure EliminarInterno; override;
    procedure PrevisualizarInterno; override;
    procedure ImprimirInterno; override;

    procedure OnClienteChanged(Sender : TObject);
    function PuedoImprimir: Boolean; override;
    function PuedoEnviar: Boolean; virtual;
    
    //Si queremos crear otra vista para el editor heredado solo tendriamos que
    //sobreescribir este metodo
    procedure AsignarVista; virtual;

    property ViewPedido: IViewPedidoCliente read GetViewPedido write SetViewPedido;
    
  public
    procedure PonerTitulos(const ATitulo: string = ''); override;
    property Controller : IPedidosClienteController read GetController write SetController;
    property Pedido: IBizPedidoCliente read GetPedido write SetPedido;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

implementation

uses
  uViewDatosYSeleccionCliente, uDataModuleUsuarios, uGridStatusUtils, uDialogUtils,
  uFactuGES_App, uDialogOpcionesImpresionPedidosCliente;

{$R *.dfm}

{ TfEditorPedidoCliente }

{
**************************** TfEditorPedidoCliente ****************************
}

procedure TfEditorPedidoCliente.actEnviarEMailExecute(Sender: TObject);
begin
  if actEnviarEMail.Enabled then
  begin
    if Modified then
    begin
      if (ShowConfirmMessage('Se han producido cambios', 'Se han producido cambios y no se puede enviar por email hasta que no se guarden.' + #10#13 +
        '¿Desea guardarlos ahora?') = IDYES) then
      begin
        GuardarInterno;
        FController.EnviarPedidoPorEMail(Pedido);
      end
      else
        ShowInfoMessage('Recuerde guardar los cambios si quiere enviar por email.');
    end
    else
     FController.EnviarPedidoPorEMail(Pedido);
  end;
end;

procedure TfEditorPedidoCliente.actEnviarEMailUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos and PuedoEnviar;
end;

procedure TfEditorPedidoCliente.AsignarVista;
begin
  ViewPedido := frViewPedidoCliente1;
end;

constructor TfEditorPedidoCliente.Create(AOwner: TComponent);
begin
  inherited;
  pgPaginas.ActivePageIndex := 0;

  AsignarVista;
end;

procedure TfEditorPedidoCliente.CustomEditorClose(Sender: TObject;
  var Action: TCloseAction);
begin
  inherited;
  FViewPedido := NIL;
  FPedido := NIL;
end;

destructor TfEditorPedidoCliente.Destroy;
begin
  // Utilizar mejor OnClose;
  inherited;
end;

procedure TfEditorPedidoCliente.EliminarInterno;
begin
  if (Application.MessageBox('¿Desea borrar este pedido de cliente?', 'Atención', MB_YESNO) = IDYES) then
  begin
    FController.Eliminar(FPedido);
    inherited
  end
end;

procedure TfEditorPedidoCliente.FormShow(Sender: TObject);
begin
  inherited;

  if not Assigned(FViewPedido) then
    raise Exception.Create('No hay ninguna vista asignada');

  if not Assigned(Pedido) then
    raise Exception.Create('No hay ningún pedido asignado');

  Pedido.DataTable.Active := True;
  pgPaginas.ActivePage := pagGeneral;
end;

procedure TfEditorPedidoCliente.frViewTotales1ePortePropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  inherited;
  if (not VarIsNull(DisplayValue)) and (length(DisplayValue) > 0) then
    FPedido.IMPORTE_PORTE := DisplayValue
  else
    FPedido.IMPORTE_PORTE := 0;

//  RecalcularPortePorUnidad;
end;

function TfEditorPedidoCliente.GetController: IPedidosClienteController;
begin
  Result := FController;
end;

function TfEditorPedidoCliente.GetPedido: IBizPedidoCliente;
begin
  Result := FPedido;
end;

function TfEditorPedidoCliente.GetViewPedido: IViewPedidoCliente;
begin
  Result := FViewPedido;
end;

procedure TfEditorPedidoCliente.GuardarInterno;
var
  bEsNuevo : Boolean;
begin
  inherited;

  ShowHourglassCursor;
//  frViewDetallesPedidoCliente1.SaveGridStatus; // Para guardar estado del grid
  frViewDetallesPedidoCliente1.BeginUpdate;  // Para que no se mueva el foco
  try
    bEsNuevo := FPedido.EsNuevo;
    FController.Guardar(FPedido);
  finally
    frViewDetallesPedidoCliente1.EndUpdate;
//    frViewDetallesPedidoCliente1.RestoreGridStatus;
    HideHourglassCursor;    
  end;

  if bEsNuevo then
    ShowInfoMessage('El pedido se ha dado de alta con el código ' + FPedido.REFERENCIA);

  Modified := False;
end;

procedure TfEditorPedidoCliente.ImprimirInterno;
var
  AllItems: Boolean;
  FImprimirPrecios : Boolean;
  FImprimirRefCliente : Boolean;
begin
  inherited;
  AllItems := False;
  FImprimirPrecios := True;
  FImprimirRefCliente := True;

  if ElegirOpcionesImpresionPedidoCliente(FImprimirPrecios, FImprimirRefCliente) then
    FController.Print(FPedido, AllItems, FImprimirPrecios, FImprimirRefCliente);
end;

function TfEditorPedidoCliente.PuedoEnviar: Boolean;
begin
  Result := not Pedido.Cliente.IDIsNull;
end;

function TfEditorPedidoCliente.PuedoImprimir: Boolean;
begin
  Result := inherited PuedoImprimir and (not Pedido.Cliente.IDIsNull);
end;

procedure TfEditorPedidoCliente.OnClienteChanged(Sender: TObject);
begin
	if Assigned(FPedido) then
	begin
	  FPedido.Cliente := ViewPedido.ViewClientePedido.Cliente;
    frViewPedidoCliente1.frViewDireccionEntregaPedidoCli1.RefrescarControles;

    if FPedido.Cliente.Direcciones.RecordCount = 0 then
    begin
       MessageBox(0, '¡Atención! Este cliente no tiene ' + #10#13 + 'ninguna dirección de envío en su ficha', 'Atención', MB_ICONWARNING or MB_OK);
       FPedido.Edit;
       FPedido.IMPORTE_PORTE := 0;
    end;

    if not Controller.ClienteController.TieneDatosBancarios(FPedido.Cliente) then
       MessageBox(0, 'Este cliente no tiene datos bancarios en su ficha', 'Atención', MB_ICONWARNING or MB_OK);

	  // Si el pedido tiene detalles hay que mirar si los descuentos y otros campos
	  // para los artículos hay que cambiarlos.
	  if (FPedido.Detalles.RecordCount > 0) then
	     FController.DetallesController.ActualizarDetalles(FPedido.Detalles, FPedido.Cliente);
	end;
end;

procedure TfEditorPedidoCliente.pgPaginasChanging(Sender: TObject; var AllowChange: Boolean);
begin
  inherited;
  if (not Assigned(FPedido))
  or (FPedido.ID_CLIENTE = 0) then
  begin
    ShowWarningMessage('Antes de introducir conceptos debe elegir un cliente para este pedido');
    AllowChange := False;
  end;
end;

procedure TfEditorPedidoCliente.PonerTitulos(const ATitulo: string);
var
  FTitulo : String;
begin
  FTitulo := ATitulo;
  if (FTitulo = '') and Assigned(FPedido) then
  begin
    if FPedido.EsNuevo then
      FTitulo := 'Nuevo pedido de cliente'
    else
      FTitulo := 'Pedido de cliente'  + ' - ' + FPedido.Cliente.Nombre + ' - (' + FPedido.SITUACION + ')';
  end;

  inherited PonerTitulos(FTitulo);

  Self.Caption := FTitulo + ' (' + AppFactuGES.EmpresaActiva.NOMBRE + ')';
end;

procedure TfEditorPedidoCliente.PrevisualizarInterno;
var
  AllItems: Boolean;
  FImprimirPrecios : Boolean;
  FImprimirRefProveedor : Boolean;
begin
  inherited;
  AllItems := False;
  FImprimirPrecios := True;
  FImprimirRefProveedor := True;

  if ElegirOpcionesImpresionPedidoCliente(FImprimirPrecios, FImprimirRefProveedor) then
     FController.Preview(FPedido, AllItems, FImprimirPrecios, FImprimirRefProveedor);
end;

procedure TfEditorPedidoCliente.RecalcularPortePorUnidad;
begin
  //Esta lógica se llamará en el editor porque es para facilitar el rellenado de información del documento
  //no puede ir en la clase de negocio porque no es una lógica que tenga sentido fuera del editor.
  if Assigned(Controller)
  and Assigned(Controller.DetallesController) then
      Controller.DetallesController.DesglosarPorteDetalles(FPedido.IMPORTE_PORTE, FPedido.Detalles)
end;

procedure TfEditorPedidoCliente.SetController(const Value: IPedidosClienteController);
begin
  FController := Value;

  if Assigned(FController) then
  begin
    if Assigned(FViewPedido) then
       FViewPedido.Controller := Controller;

    frViewDetallesPedidoCliente1.Controller := Controller.DetallesController;
  end;
end;

procedure TfEditorPedidoCliente.SetPedido(const Value: IBizPedidoCliente);
begin
  FPedido := Value;

  if Assigned(FPedido) then
  begin
    dsDataTable.DataTable := FPedido.DataTable;
    frViewTotales1.DADataSource.DataTable := dsDataTable.DataTable;
    frViewIncidenciasProv.DADataSource.DataTable := dsDataTable.DataTable;

    if Assigned(FViewPedido) then
    begin
      ViewPedido.ViewClientePedido.OnClienteChanged := NIL;
      try
        FViewPedido.Pedido := FPedido;
        frViewDetallesPedidoCliente1.Detalles := FPedido.Detalles;
        frViewDetallesPedidoCliente1.Pedido := FPedido; //Para poder sacar los articulos del cliente seleccionado
      finally
        ViewPedido.ViewClientePedido.OnClienteChanged := OnClienteChanged;
      end;
    end;
  end;
end;

procedure TfEditorPedidoCliente.SetViewPedido(const Value: IViewPedidoCliente);
begin
  FViewPedido := Value;

  if Assigned(FViewPedido) and Assigned(Pedido) then
    FViewPedido.Pedido := Pedido;
end;

end.
  