unit uEditorContratoCliente;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  uEditorDBItem, DB, uDADataTable, JvAppStorage,
  JvAppRegistryStorage, JvComponent, JvFormPlacement, ImgList,
  PngImageList, StdActns, ActnList, ComCtrls, TBX, TB2Item, TB2Dock,
  TB2Toolbar, ExtCtrls, JvExControls, JvNavigationPane,
  uCustomView, uViewBase, JvComponentBase,
  StdCtrls, pngimage, AppEvnts, cxControls, cxContainer, cxEdit, cxTextEdit, cxMemo, cxDBEdit,
  uViewIncidencias,
  uContratosClienteController,
  uViewDetallesBase, 
  dxLayoutLookAndFeels, JvExComCtrls, JvStatusBar, uViewTotales,
  uIEditorContratoCliente, uBizContratosCliente, uViewContratoCliente,
  uViewDetallesDTO, uViewDetallesArticulos, uViewDetallesContratoCliente,
  uDAInterfaces, cxRichEdit, cxDBRichEdit, JvGIF, cxPC,
  uViewDocumentos,
  uViewDocumentosContratoCliente, uViewClienteContrato,
  cxLabel, uBizTiposIVA, uTiposIVAController, dxLayoutControl;

type
  TfEditorContratoCliente = class(TfEditorDBItem, IEditorContratoCliente)
    pagContenido: TTabSheet;
    pagInicidencias: TTabSheet;
    frViewIncidenciasCli: TfrViewIncidencias;
    dxLayoutLookAndFeelList1: TdxLayoutLookAndFeelList;
    dxLayoutOfficeLookAndFeel1: TdxLayoutOfficeLookAndFeel;
    TBXSubmenuItem2: TTBXSubmenuItem;
    TBXItem7: TTBXItem;
    TBXSeparatorItem6: TTBXSeparatorItem;
    actEnviarPorEMail: TAction;
    TBXItem34: TTBXItem;
    TBXItem35: TTBXItem;
    pagDocumentos: TTabSheet;
    frViewDocumentosContratoCliente1: TfrViewDocumentosContratoCliente;
    frViewTotales1: TfrViewTotales;
    frViewDetallesContratoCliente1: TfrViewDetallesContratoCliente;
    pagCondiciones: TTabSheet;
    dxLayoutControl1: TdxLayoutControl;
    dxLayoutControl1Item1: TdxLayoutItem;
    memCondiciones: TcxDBMemo;
    pagCalidades: TTabSheet;
    dxLayoutControl2: TdxLayoutControl;
    memCalidades: TcxDBMemo;
    dxLayoutGroup1: TdxLayoutGroup;
    dxLayoutItem1: TdxLayoutItem;
    frViewContratoCliente1: TfrViewContratoCliente;
    eCampoLibre: TcxDBTextEdit;

    procedure FormShow(Sender: TObject);
    procedure CustomEditorClose(Sender: TObject; var Action: TCloseAction);
    procedure frViewTotales1ePortePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure pgPaginasChanging(Sender: TObject; var AllowChange: Boolean);
    procedure actEnviarPorEMailExecute(Sender: TObject);
    procedure actEnviarPorEMailUpdate(Sender: TObject);
    procedure actEliminarUpdate(Sender: TObject);
    procedure frViewTotales1bTiposIVAClick(Sender: TObject);
    procedure frViewTotales1eIVAPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure OnRecargoEquivalenciaPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
      var Error: Boolean);
    procedure pagDocumentosShow(Sender: TObject);
    procedure dsDataTableDataChange(Sender: TObject; Field: TField);
    procedure frViewClienteContrato1edtlNombrePropertiesEditValueChanged(
      Sender: TObject);
    procedure frViewClienteContrato1edtlNombrePropertiesChange(Sender: TObject); //Importante en este punto se deben de quitar los eventos que puedan afectar a la tabla una vez se cierre el editor.

  private
    //procedure RecalcularPortePorUnidad;

  protected
    FContrato: IBizContratoCliente;
    FTiposIVAController : ITiposIVAController;
    FTiposIVA: IBizTipoIVA;
    FViewContratoCliente: IViewContratoCliente;
    FViewClienteContrato :IViewDatosYSeleccionClienteContrato;
    FController : IContratosClienteController;

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

    function GetContrato: IBizContratoCliente;
    procedure SetContrato(const Value: IBizContratoCliente); virtual;

    function GetViewContratoCliente: IViewContratoCliente;
    procedure SetViewContratoCliente(const Value: IViewContratoCliente);

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

    property ViewContratoCliente: IViewContratoCliente read GetViewContratoCliente write SetViewContratoCliente;

    procedure OnClienteChanged(Sender : TObject);

    procedure PonerTitulos(const ATitulo: string = ''); override;
    function GetModified: Boolean; override;
    procedure SetModified(const Value : Boolean); override;
    
    function PuedoImprimir: Boolean; override;        

  public
    property Controller : IContratosClienteController read GetController write SetController;
    property Contrato: IBizContratoCliente read GetContrato write SetContrato;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

implementation

uses
  uViewDatosYSeleccionCliente, uDataModuleUsuarios, uClientesController,
  uBizDireccionesContacto, uDialogUtils, uFactuGES_App, uDataTableUtils,
  Dialogs;

{$R *.dfm}

{ TfEditorContratoCliente }

{
**************************** TfEditorContratoCliente ****************************
}

constructor TfEditorContratoCliente.Create(AOwner: TComponent);
begin
  inherited;
  pgPaginas.ActivePageIndex := 0;
  ViewContratoCliente := frViewContratoCliente1;

  FTiposIVAController := TTiposIVAController.Create;
end;

procedure TfEditorContratoCliente.CustomEditorClose(Sender: TObject;
  var Action: TCloseAction);
begin
  inherited;
  //GESTION_DOCUMENTOS
  //Este método eliminará el directorio temporal si se ha creado
  frViewDocumentosContratoCliente1.actEliminarTodo.Execute;

  dsDataTable.DataTable := NIL;
  frViewTotales1.DADataSource.DataTable := NIL;
  frViewTotales1.cbRecargoEquivalencia.Properties.OnValidate := nil;

  FViewContratoCliente := NIL;
  FViewClienteContrato := NIL;
  FTiposIVA := NIL;
  FTiposIVAController := Nil;
  FContrato := NIL;
end;

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

procedure TfEditorContratoCliente.dsDataTableDataChange(Sender: TObject;
  Field: TField);
begin
  inherited;
  if Assigned(FContrato) and (not (FContrato.DataTable.Fetching) or
    not (FContrato.DataTable.Opening) or not (FContrato.DataTable.Closing)) then
    PonerTitulos;
end;

procedure TfEditorContratoCliente.EliminarInterno;
begin
  if (ShowConfirmMessage('¿Desea borrar este contrato de cliente?', '') = IDYES) then
  begin
    FController.Eliminar(FContrato);
    inherited
  end
end;

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

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

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

  frViewTotales1.cbRecargoEquivalencia.Properties.OnValidate := OnRecargoEquivalenciaPropertiesValidate;

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

procedure TfEditorContratoCliente.frViewClienteContrato1edtlNombrePropertiesChange(
  Sender: TObject);
begin
  inherited;
  PonerTitulos;
end;

procedure TfEditorContratoCliente.frViewClienteContrato1edtlNombrePropertiesEditValueChanged(
  Sender: TObject);
begin
  inherited;
  with (Sender as TcxDBTextEdit) do
    Enabled := (FContrato.ID <> 0)
end;

procedure TfEditorContratoCliente.frViewTotales1bTiposIVAClick(
  Sender: TObject);
begin
  inherited;
  FTiposIVAController.VerTodos(FTiposIVA);
end;

procedure TfEditorContratoCliente.frViewTotales1eIVAPropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  inherited;
  Contrato.Edit;
  Contrato.ID_TIPO_IVA := FTiposIVA.ID; // ((frViewTotales1.dsTiposIVA.DataTable) as IBizTipoIVA).ID;
end;

procedure TfEditorContratoCliente.frViewTotales1ePortePropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  inherited;
{  if (not VarIsNull(DisplayValue)) and (Length(DisplayValue) > 0) then
    FContrato.IMPORTE_PORTE := DisplayValue
  else
    FContrato.IMPORTE_PORTE := 0;
}
//  RecalcularPortePorUnidad; En los documentos de cliente no se desglosa el porte por articulo
end;

function TfEditorContratoCliente.GetController: IContratosClienteController;
begin
  Result := FController;
end;

function TfEditorContratoCliente.GetModified: Boolean;
begin
  // inherited;  <- No llamar al padre porque queremos tratamiento especial.
  if ReadOnly then
     Result := False
  else begin
    Result := DataTableModified(dsDataTable.DataTable);

    if not Result then
      Result := frViewDocumentosContratoCliente1.Modified;
  end;
end;

function TfEditorContratoCliente.GetContrato: IBizContratoCliente;
begin
  Result := FContrato;
end;

function TfEditorContratoCliente.GetViewContratoCliente: IViewContratoCliente;
begin
  Result := FViewContratoCliente;
end;

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

  ShowHourglassCursor;
  frViewDetallesContratoCliente1.SaveGridStatus;
  frViewDetallesContratoCliente1.BeginUpdate;
  try
    bEsNuevo := FContrato.EsNuevo;

    if not bEsNuevo then
      if (FContrato.FECHA_ULT_PRESENTACION_CLIENTE < Date) then
        if ShowConfirmMessage('Cambio fecha actualización', '¿Desea cambiar la fecha de última actualización del presupuesto por la de hoy?') = IDYES then
           Controller.FechaUltimaActualizacionToday(FContrato);

    //GESTION_DOCUMENTOS
    if FController.Guardar(FContrato) then
       frViewDocumentosContratoCliente1.actActualizarServidor.Execute;

  finally
    frViewDetallesContratoCliente1.EndUpdate;
    frViewDetallesContratoCliente1.RestoreGridStatus;
    HideHourglassCursor;
  end;

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

  Modified := False;
end;

procedure TfEditorContratoCliente.ImprimirInterno;
var
  FVerCondiciones : Boolean;
begin
  inherited;
  if not Modified then
  begin
    FVerCondiciones := ShowConfirmMessage('Previsualizar presupuesto', '¿Desea previsualizar Montadores/Enganches?') = IDYES;
    FController.Print(FContrato, False, FVerCondiciones);
  end;
end;

procedure TfEditorContratoCliente.OnClienteChanged(Sender: TObject);
var
  AClientesController : IClientesController;
  ADireccion : IBizDireccionesContacto;
begin
  if Assigned(FContrato) then
  begin
  	FContrato.Cliente := frViewContratoCliente1.frViewClienteContrato1.Cliente;

    if not (FContrato.DataTable.State in dsEditModes) then
       FContrato.DataTable.Edit;

    // En el caso de tener direcciones asociadas, se debe dar la posibilidad de elegir la dirección principal o las secundarias para la factura
    AClientesController := TClientesController.Create;
    try
      case FContrato.Cliente.Direcciones.RecordCount of
        0   : //No hay direcciones secundarias asociadas
        else  ADireccion := AClientesController.ElegirDireccion(FContrato.Cliente, 'Seleccione la dirección del cliente que quiere utilizar como dirección fiscal de este contrato.');
      end;

      // Si hay dirección de envio, copiarla a la factura y poner el coste del porte
      if Assigned(ADireccion) then
      begin
        if not ADireccion.IDIsNull then
          try
           FContrato.Edit;
           FContrato.IMPORTE_PORTE := ADireccion.PORTE;
           FController.CopiarDireccion(ADireccion, FContrato);
          finally
           ADireccion := NIL;
          end;
      end
    finally
      AClientesController := Nil;
    end;


    //Desactivado porque en Contratos no utilizan el catálogo de clientes
    //    if (FContrato.Detalles.RecordCount > 0) then
    //      FController.DetallesController.ActualizarDetalles(FContrato.Detalles, FContrato.Cliente);
  end;
end;

procedure TfEditorContratoCliente.OnRecargoEquivalenciaPropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin

  if frViewTotales1.cbRecargoEquivalencia.Checked then
     Contrato.RECARGO_EQUIVALENCIA := 1
  else
     Contrato.RECARGO_EQUIVALENCIA := 0;
end;

procedure TfEditorContratoCliente.pagDocumentosShow(Sender: TObject);
begin
  inherited;
  //GESTION_DOCUMENTOS
  frViewDocumentosContratoCliente1.Contrato := FContrato;
end;

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

procedure TfEditorContratoCliente.PonerTitulos(const ATitulo: string);
var
  FTitulo : String;
begin
  FTitulo := ATitulo;
  if (FTitulo = '') and Assigned(FContrato) then
  begin
    if FContrato.EsNuevo then
            FTitulo := 'Nuevo presupuesto de cliente' //FTitulo := 'Nuevo Contrato de cliente'
    else
      FTitulo := 'Presupuesto de cliente'  + ' - ' + FContrato.Cliente.Nombre + ' - ' + FContrato.SITUACION;
  end;

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

procedure TfEditorContratoCliente.PrevisualizarInterno;
var
  FVerCondiciones : Boolean;

begin
  inherited;
  if not Modified then
  begin
    FVerCondiciones := ShowConfirmMessage('Previsualizar presupuesto', '¿Desea previsualizar Montadores/Enganches?') = IDYES;
    FController.Preview(FContrato, False, FVerCondiciones);
  end;
end;

{procedure TfEditorContratoCliente.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(FContrato.IMPORTE_PORTE, FContrato.Detalles)
end;}

procedure TfEditorContratoCliente.SetController(const Value: IContratosClienteController);
begin
  FController := Value;

  if Assigned(FController) then
  begin
    ViewContratoCliente.Controller := FController;
    frViewDetallesContratoCliente1.Controller := Controller.DetallesController;

    //GESTION_DOCUMENTOS
    frViewDocumentosContratoCliente1.Controller := Controller;

//    frViewTotales1.Controller := FController;
  end;
end;

procedure TfEditorContratoCliente.SetModified(const Value: Boolean);
begin
  inherited;
  frViewDocumentosContratoCliente1.Modified := Value;
end;

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

procedure TfEditorContratoCliente.SetContrato(const Value: IBizContratoCliente);
begin
  FContrato := Value;

  if Assigned(FContrato) then
  begin
    dsDataTable.DataTable := FContrato.DataTable;

    frViewIncidenciasCli.DADataSource.DataTable := dsDataTable.DataTable;
    frViewTotales1.DADataSource.DataTable := FContrato.DataTable;

    FTiposIVA := FTiposIVAController.BuscarTodos;
    frViewTotales1.dsTiposIVA.DataTable := FTiposIVA.DataTable;
    FTiposIVA.DataTable.Active := True;

    if Assigned(FViewContratoCliente) then
    begin
      frViewContratoCliente1.frViewClienteContrato1.Cliente := FContrato.Cliente;
      frViewContratoCliente1.frViewClienteContrato1.OnClienteChanged := NIL;
      try
        ViewContratoCliente.Contrato := FContrato;
        frViewDetallesContratoCliente1.Detalles := FContrato.Detalles;
        frViewDetallesContratoCliente1.Contrato := FContrato; //Para poder sacar los descuento del articulos segun el cliente seleccionado

      finally
        frViewContratoCliente1.frViewClienteContrato1.OnClienteChanged := OnClienteChanged;
      end;
    end
  end
  else begin
    frViewContratoCliente1.frViewClienteContrato1.OnClienteChanged := NIL;
    frViewContratoCliente1.frViewClienteContrato1.Cliente := NIL;
    dsDataTable.DataTable := NIL;
    frViewTotales1.DADataSource.DataTable := NIL;
    frViewTotales1.dsTiposIVA.DataTable := NIL;
  end
end;

procedure TfEditorContratoCliente.SetViewContratoCliente(const Value: IViewContratoCliente);
begin
  FViewContratoCliente := Value;

  if Assigned(FViewContratoCliente) and Assigned(Contrato) then
      FViewContratoCliente.Contrato := Contrato;
end;


procedure TfEditorContratoCliente.actEliminarUpdate(Sender: TObject);
begin
  inherited;
  if (Sender as TAction).Enabled then
     (Sender as TAction).Enabled := (FContrato.SITUACION = SITUACION_Contrato_PENDIENTE);
end;

procedure TfEditorContratoCliente.actEnviarPorEMailExecute(Sender: TObject);
begin
  inherited;
  FController.EnviarContratoPorEMail(Contrato);
end;

procedure TfEditorContratoCliente.actEnviarPorEMailUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos;
end;

end.
