unit uEditorFacturaProveedor;

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, 
  uCustomView, uViewBase, uViewTotales,
  StdCtrls, pngimage, AppEvnts, JvComponentBase,
  uBizFacturasProveedor, uIEditorFacturaProveedor, uFacturasProveedorController, uViewDetallesBase,
  dxLayoutLookAndFeels, JvExComCtrls, JvStatusBar, uBizTiposIVA,
  uViewDetallesDTO, uViewDetallesArticulos, uTiposIVAController,
  uViewDetallesFacturaProveedor, uViewFacturaProveedor, uDAInterfaces,
  uViewDetallesGenerico, uViewPedidosFacturaProveedor, cxControls, cxContainer,
  cxEdit, cxLabel;


type
  TfEditorFacturaProveedor = class(TfEditorDBItem, IEditorFacturaProveedor)
    frViewTotales1: TfrViewTotales;
    frViewFacturaProveedor1: TfrViewFacturaProveedor;
    frViewDetallesFacturaProveedor1: TfrViewDetallesFacturaProveedor;
    pagPedidos: TTabSheet;
    frViewPedidosFacturaProveedor1: TfrViewPedidosFacturaProveedor;
    procedure FormShow(Sender: TObject);
    procedure frViewProveedorFactura1edtlNombrePropertiesEditValueChanged(
      Sender: TObject);
    procedure dsDataTableDataChange(Sender: TObject; Field: TField);
    procedure CustomEditorClose(Sender: TObject; var Action: TCloseAction);
    procedure frViewProveedorFacturaedtlNombrePropertiesChange(Sender: TObject);
    procedure pgPaginasChanging(Sender: TObject; var AllowChange: Boolean);
    procedure frViewTotales1edtDescuentoPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure frViewTotales1bTiposIVAClick(Sender: TObject);
    procedure frViewTotales1eIVAPropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure frViewTotales1cbRecargoEquivalenciaPropertiesEditValueChanged(Sender: TObject);
    procedure frViewTotales1ePortePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
    procedure frViewTotales1ePorteEditing(Sender: TObject; var CanEdit: Boolean);

  private
    procedure RecalcularPortePorUnidad;

  protected
    FController : IFacturasProveedorController;
    FFactura: IBizFacturaProveedor;
    FViewFactura: IViewFacturaProveedor;
    FTiposIVAController : ITiposIVAController;
    FTiposIVA: IBizTipoIVA;
    function GetController : IFacturasProveedorController;
    procedure SetController (const Value : IFacturasProveedorController);
    function GetFactura: IBizFacturaProveedor;
    procedure SetFactura(const Value: IBizFacturaProveedor);

    function GetViewFactura: IViewFacturaProveedor;
    procedure SetViewFactura(const Value: IViewFacturaProveedor);

    property ViewFacturaProveedor: IViewFacturaProveedor read GetViewFactura write SetViewFactura;

    procedure OnProveedorChanged(Sender: TObject);

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

    procedure PonerTitulos(const ATitulo: string = ''); override;
  public
    destructor Destroy; override;
    property Controller : IFacturasProveedorController read GetController write SetController;
    property Factura: IBizFacturaProveedor read GetFactura write SetFactura;
    constructor Create(AOwner: TComponent); override;
  end;

implementation
{$R *.dfm}

uses
  cxDBEdit, uBizContactos, uDataModuleUsuarios, uFactuGES_App,
  uDetallesFacturaProveedorController, uDialogUtils, uDataTableUtils,
  uGenerarAlbaranesProvFacProvUtils;


{ TfEditorFacturaProveedor }

{
**************************** TfEditorFacturaProveedor ****************************
}
constructor TfEditorFacturaProveedor.Create(AOwner: TComponent);
begin
  inherited;
  pgPaginas.ActivePageIndex := 0;
  ViewFacturaProveedor := frViewFacturaProveedor1;
  FTiposIVAController := TTiposIVAController.Create;
end;

procedure TfEditorFacturaProveedor.CustomEditorClose(Sender: TObject;
  var Action: TCloseAction);
begin
  inherited;
  dsDataTable.DataTable := NIL;
  frViewTotales1.DADataSource.DataTable := NIL;

  FTiposIVA := NIL;
  FTiposIVAController := Nil;
  FController := NIL;
  FViewFactura := NIL;
  Factura := NIL;
end;

destructor TfEditorFacturaProveedor.Destroy;
begin
  inherited;
end;

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

procedure TfEditorFacturaProveedor.EliminarInterno;
var
  AMensaje : String;
begin
  if FFactura.TIPO = CTE_TIPO_ABONO then
    AMensaje := '¿Desea borrar esta factura de proveedor?'
  else
    AMensaje := '¿Desea borrar este abono de proveedor?';

  if (Application.MessageBox(PChar(AMensaje), 'Atención', MB_YESNO) = IDYES) then
  begin
    //Es el caso de querer borrar una factura pendiente cuyos recibos tienen devoluciones
    if not FController.Eliminar(Factura) then
       Application.MessageBox('La factura no ha podido ser eliminada porque tiene recibos con pagos o devoluciones emitidas.', 'Atención', MB_OK);
    inherited;
  end;
end;

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

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

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

  Factura.DataTable.Active := True;
end;

procedure TfEditorFacturaProveedor.frViewProveedorFactura1edtlNombrePropertiesEditValueChanged(Sender: TObject);
begin
  inherited;
  with (Sender as TcxDBTextEdit) do
    Enabled := (FFactura.ID <> 0)
end;

procedure TfEditorFacturaProveedor.frViewProveedorFacturaedtlNombrePropertiesChange(
  Sender: TObject);
begin
  inherited;
  PonerTitulos;
end;

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

procedure TfEditorFacturaProveedor.frViewTotales1cbRecargoEquivalenciaPropertiesEditValueChanged(
  Sender: TObject);
begin
  inherited;
{  if frViewTotales1.cbRecargoEquivalencia.Checked then
    Factura.RECARGO_EQUIVALENCIA := 1
  else
    Factura.RECARGO_EQUIVALENCIA := 0;}
end;

procedure TfEditorFacturaProveedor.frViewTotales1edtDescuentoPropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  inherited;
  Factura.DESCUENTO := DisplayValue;
end;

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

procedure TfEditorFacturaProveedor.frViewTotales1ePorteEditing(Sender: TObject; var CanEdit: Boolean);
begin
  inherited;
  if FFactura.TIPO = CTE_TIPO_ABONO then
     CanEdit := False;
end;

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

  RecalcularPortePorUnidad;
end;

function TfEditorFacturaProveedor.GetController: IFacturasProveedorController;
begin
  Result := FController;
end;

function TfEditorFacturaProveedor.GetFactura: IBizFacturaProveedor;
begin
  Result := FFactura;
end;

function TfEditorFacturaProveedor.GetViewFactura: IViewFacturaProveedor;
begin
  Result := FViewFactura;
end;

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

  ShowHourglassCursor;
  //frViewDetallesFacturaProveedor1.SaveGridStatus; // Para guardar estado del grid
  frViewDetallesFacturaProveedor1.BeginUpdate;  // Para que no se mueva el foco
  try
    bEsNuevo := FFactura.EsNuevo;

    FController.Guardar(FFactura);
  finally
    frViewDetallesFacturaProveedor1.EndUpdate;
    //frViewDetallesFacturaProveedor1.RestoreGridStatus;
    HideHourglassCursor;
  end;

  if bEsNuevo then
  begin
    if FFactura.TIPO = CTE_TIPO_FACTURA then
       ShowInfoMessage('La factura se ha dado de alta con el código ' + FFactura.REFERENCIA)
    else
    begin
       ShowInfoMessage('El abono se ha dado de alta con el código ' + FFactura.REFERENCIA);
       //Preguntamos is desea hacer una orden de devolución asociada
       if (Application.MessageBox('¿Desea crear una orden de devolución para el abono?', 'Atención', MB_YESNO) = IDYES) then
          GenerarAlbaranProv(FFactura);
    end;  
  end;
  Modified := False;
end;

procedure TfEditorFacturaProveedor.ImprimirInterno;
begin
  inherited;
  FController.Print(FFactura);
end;

procedure TfEditorFacturaProveedor.OnProveedorChanged(Sender: TObject);
var
  FDetallesController : IDetallesFacturaProveedorController;
begin
  FFactura.Proveedor := frViewFacturaProveedor1.frViewProveedorFactura.Proveedor;

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

  // Actualizar IVA y RE a partir del tipo de IVA del proveedor.
  Factura.IVA := FTiposIVA.IVA; //((frViewTotales1.dsTiposIVA.DataTable) as IBizTipoIVA).IVA;
//  if FFactura.Proveedor.RECARGO_EQUIVALENCIA = 1 then
//    Factura.RE := ((frViewTotales1.dsTiposIVA.DataTable) as IBizTipoIVA).RE
//  else
//    Factura.RE := 0;

  // Si la factura tiene detalles hay que mirar si los descuentos y otros campos
  // para los artículos hay que cambiarlos.
  if (FFactura.Detalles.RecordCount > 0) then
     FController.DetallesController.ActualizarDetalles(FFactura.Detalles, FFactura.Proveedor);

  // Si la factura tiene pedidos asociados hay que mirar si pertenecen al proveedor seleccionado si no es así se eliminan
//  if (FFactura.Pedidos.RecordCount > 0) then
//  begin
//    showmessage('Comprobar si los pedidos pertenecen al nuevo proveedor');
//  end;
end;

procedure TfEditorFacturaProveedor.pgPaginasChanging(Sender: TObject;
  var AllowChange: Boolean);
var
  AMensaje : String;
begin
  inherited;
  if (not Assigned(FFactura)) or (FFactura.ID_PROVEEDOR = ID_NULO) then
  begin
    if FFactura.TIPO = CTE_TIPO_FACTURA then
      AMensaje := 'Antes debe elegir un proveedor para esta factura'
    else
      AMensaje := 'Antes debe elegir un proveedor para este abono';
    ShowWarningMessage(AMensaje);
    AllowChange := False;
  end;
end;

procedure TfEditorFacturaProveedor.PonerTitulos(const ATitulo: string);
var
  FTitulo : String;
begin
  FTitulo := ATitulo;
  if (FTitulo = '') and Assigned(Factura) then
  begin
    if Factura.EsNuevo then
       if Factura.TIPO = CTE_TIPO_FACTURA then
          FTitulo := 'Nueva factura de proveedor'
       else
          FTitulo := 'Nuevo abono de proveedor'
    else
       if Factura.TIPO = CTE_TIPO_FACTURA then
          FTitulo := 'Factura de proveedor'  + ' - ' + FFactura.Proveedor.Nombre
       else
          FTitulo := 'Abono de proveedor'  + ' - ' + FFactura.Proveedor.Nombre
  end;

  inherited PonerTitulos(FTitulo);

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

procedure TfEditorFacturaProveedor.PrevisualizarInterno;
begin
  inherited;
  FController.Preview(FFactura);
end;

procedure TfEditorFacturaProveedor.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(FFactura.IMPORTE_PORTE, FFactura.Detalles)
end;

procedure TfEditorFacturaProveedor.SetController(const Value: IFacturasProveedorController);
begin
  FController := Value;

  if Assigned(FController) then
  begin
     ViewFacturaProveedor.Controller := Controller;
     frViewDetallesFacturaProveedor1.Controller := Controller.DetallesController;
  end;
end;

procedure TfEditorFacturaProveedor.SetFactura(const Value: IBizFacturaProveedor);
begin
  FFactura := Value;

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

    frViewTotales1.DADataSource.DataTable := FFactura.DataTable;

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

    if Assigned(FViewFactura) then
    begin
      frViewFacturaProveedor1.frViewProveedorFactura.Proveedor := FFactura.Proveedor;
      frViewFacturaProveedor1.frViewProveedorFactura.OnProveedorChanged := OnProveedorChanged;

      FViewFactura.Factura := FFactura;
      frViewPedidosFacturaProveedor1.Pedidos := FFactura.Pedidos;
      frViewDetallesFacturaProveedor1.Detalles := FFactura.Detalles;
      frViewDetallesFacturaProveedor1.Factura := FFactura; //Para poder sacar los descuento del articulos segun el proveedor seleccionado
    end;
  end
  else begin
    frViewFacturaProveedor1.frViewProveedorFactura.OnProveedorChanged := NIL;
    frViewFacturaProveedor1.frViewProveedorFactura.Proveedor := NIL;
    dsDataTable.DataTable := NIL;
    frViewTotales1.DADataSource.DataTable := NIL;
    frViewTotales1.dsTiposIVA.DataTable := NIL;
  end
end;

procedure TfEditorFacturaProveedor.SetViewFactura(const Value: IViewFacturaProveedor);
begin
  FViewFactura := Value;

  if Assigned(FViewFactura) and Assigned(Factura) then
    FViewFactura.Factura := Factura;
end;

end.
  