unit uEditorReciboProveedor;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uEditorDBItem, JvAppStorage, JvAppRegistryStorage, DB, uDADataTable,
  JvComponentBase, JvFormPlacement, ImgList, PngImageList, StdActns, ActnList,
  ComCtrls, JvExComCtrls, JvStatusBar, TBX, TB2Item, TB2Dock, TB2Toolbar,
  pngimage, ExtCtrls, JvExControls, JvComponent, JvNavigationPane, uIEditorReciboProveedor,
  uCustomView, uViewBase, uViewReciboProveedor, uRecibosProveedorController,
  uBizRecibosProveedor, uViewPagosProveedor, dxLayoutLookAndFeels, cxCustomData,
  uViewDetallesGenerico, uViewRecibosProvCompensados, uViewReciboProvImportes,
  uDAInterfaces, StdCtrls;

type
  TfEditorReciboProveedor = class(TfEditorDBItem, IEditorReciboProveedor)
    DADataSource1: TDADataSource;
    frViewReciboProveedor1: TfrViewReciboProveedor;
    pagPagos: TTabSheet;
    pagCompensados: TTabSheet;
    frViewRecibosProvCompensados1: TfrViewRecibosProvCompensados;
    frViewReciboProvImportes1: TfrViewReciboProvImportes;
    frViewPagosProveedor1: TfrViewPagosProveedor;
    procedure FormShow(Sender: TObject);
    procedure dsDataTableDataChange(Sender: TObject; Field: TField);
    procedure CustomEditorClose(Sender: TObject; var Action: TCloseAction);
    procedure frViewReciboProveedor1eImportePropertiesValidate(Sender: TObject;
      var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);

    procedure frViewPagosProveedor1actAnadirExecute(Sender: TObject);
    procedure frViewPagosProveedor1actEliminarExecute(Sender: TObject);
    procedure frViewPagosProveedor1actEliminarUpdate(Sender: TObject);
    procedure frViewPagosProveedor1actModificarUpdate(Sender: TObject);
    procedure frViewPagosProveedor1actModificarExecute(Sender: TObject);

    procedure HabilitarRecibo;
    procedure DeshabilitarRecibo;
    procedure JvFormStorageRestorePlacement(Sender: TObject);
    procedure JvFormStorageSavePlacement(Sender: TObject);
    procedure frViewReciboProvImportes1eImportePropertiesEditValueChanged(Sender: TObject);
    procedure frViewRecibosProvCompensados1cxGridViewDataControllerSummaryAfterSummary(ASender: TcxDataSummary);
    procedure frViewPagosProveedor1actAnadirUpdate(Sender: TObject);

  private
    FController : IRecibosProveedorController;
    FRecibo: IBizRecibosProveedor;
    FViewRecibo : IViewReciboProveedor;
    FImporteRestante : Double;

    function GetController : IRecibosProveedorController;
    procedure SetController (const Value : IRecibosProveedorController); virtual;
    function GetRecibo: IBizRecibosProveedor;
    procedure SetRecibo(const Value: IBizRecibosProveedor);
    function GetViewRecibo: IViewReciboProveedor;
    procedure SetViewRecibo(const Value: IViewReciboProveedor);
    property ViewRecibo: IViewReciboProveedor read GetViewRecibo write SetViewRecibo;
    procedure CalcularTotal;

  protected
    procedure PrevisualizarInterno; override;
    procedure ImprimirInterno; override;
    procedure GuardarInterno; override;

    procedure PonerTitulos(const ATitulo: string = ''); override;
    procedure OnProveedorChanged(Sender: TObject);

  public
    property Recibo: IBizRecibosProveedor read GetRecibo write SetRecibo;
    constructor Create(AOwner: TComponent); override;
  end;

implementation

uses schRecibosProveedorClient_Intf, uEditorFechaPagoProveedor, uEditorBase, uFactuGES_App, uBizEjercicios,
  uProveedoresController, uBizDireccionesContacto, uViewProveedorRecibo;

{$R *.dfm}

procedure TfEditorReciboProveedor.CalcularTotal;
var
  ImporteAux: Double;
begin

  ImporteAux := 0;
  if not VarIsNull(frViewRecibosProvCompensados1.cxGridView.DataController.Summary.FooterSummaryValues[0]) then
     ImporteAux := frViewRecibosProvCompensados1.cxGridView.DataController.Summary.FooterSummaryValues[0];

  frViewReciboProvImportes1.eImporteTotalRecibo.Value := frViewReciboProvImportes1.eImporte.Value + frViewReciboProvImportes1.eOtrosGastos.Value + ImporteAux;
end;

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

  //RECIBOS COMPENSADOS DESHABILITADOS
  pagCompensados.TabVisible := False;
  pagPagos.TabVisible := False;
  
  ViewRecibo := frViewReciboProveedor1;
end;

procedure TfEditorReciboProveedor.CustomEditorClose(Sender: TObject;
  var Action: TCloseAction);
begin
  inherited;
  dsDataTable.DataTable := NIL;
  FViewRecibo := NIL;
  FRecibo := NIL;
end;

procedure TfEditorReciboProveedor.DeshabilitarRecibo;
begin
  frViewReciboProveedor1.eReferenciaProveedor.Enabled := False;
  frViewReciboProveedor1.edtFechaVencimiento.Enabled := False;
  frViewReciboProvImportes1.eImporte.Enabled := False;
  frViewReciboProvImportes1.eOtrosGastos.Enabled := False;
end;

procedure TfEditorReciboProveedor.dsDataTableDataChange(Sender: TObject; Field: TField);
begin
  inherited;

  if Assigned(FRecibo) and (not (FRecibo.DataTable.Fetching) or
    not (FRecibo.DataTable.Opening) or not (FRecibo.DataTable.Closing)) then
    PonerTitulos;
end;

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

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

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

  Recibo.DataTable.Active := True;
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actAnadirExecute(Sender: TObject);
var
  AFechaPago: String;
  AIgnorarContabilidad: Integer;
  AIdSubCuenta: Integer;
  ASubCuenta: String;

begin
  inherited;

  if (Length(Recibo.REFERENCIA_REMESA) = 0) or
    (Application.MessageBox(PChar('Este recibo está remesado en la remesa de referencia ' + Recibo.REFERENCIA_REMESA + '.' + #10#13 + 'Si añade una devolución, el recibo quedará libre y podrá ser incluido en otra remesa diferente.' + #10#13 + '¿Desea continuar?'), 'Atención', MB_YESNO) = IDYES) then
  begin
    with TfEditorFechaPagoProveedor.Create(Nil) do
    begin

			//En el caso de que el proveedor del recibo no tenga aignada subcuenta contable el pago no podrá contabilizar
      if (Recibo.Proveedor.SubCuentas.ID < 1) then
      begin
         IgnorarContabilidad := 1;
         DeshabilitarContabilidad;
      end;

      if (ShowModal = mrOk) then
      begin
        AFechaPago := DateToStr(FechaPago);
        AIgnorarContabilidad := IgnorarContabilidad;
        AIdSubCuenta := IdSubcuenta;
        ASubCuenta := frViewListaSubcuentas1.cbSubCuentas.Text;
        Release;
      end
      else
      begin
        //Operación cancelada
        Release;
        exit;
      end;
    end;
  end;

  FController.AnadirPago(Recibo, AFechaPago, AIgnorarContabilidad, AIdSubCuenta, ASubCuenta);

  //Solo podremos modificar el recibo si esta pendiente o devuelto
  if (Recibo.SITUACION = CTE_PAGADO) then
     DeshabilitarRecibo
  else
     HabilitarRecibo;

  frViewPagosProveedor1.ListaPagosProveedorDBTableView1.DataController.GotoLast;     
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actAnadirUpdate(
  Sender: TObject);
begin
  //El recibo solo podrá tener un único pago
  if Assigned(FRecibo) and Assigned(FRecibo.Pagos) then
     frViewPagosProveedor1.actAnadir.Enabled := (FRecibo.Pagos.DataTable.RecordCount < 1)
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actEliminarExecute(Sender: TObject);
begin
  inherited;
  //En el caso de eliminar un pago el recibo queda como devuelto o pendiente y por tanto se puede modificar
  if (FController.EliminarPago(Recibo)) then
  begin
    FRecibo.Edit;
    if FRecibo.Pagos.DataTable.RecordCount > 0 then
       FRecibo.SITUACION := CTE_DEVUELTO
    else
       FRecibo.SITUACION := CTE_PENDIENTE;
    HabilitarRecibo;
  end
  //No podremos modificar si anulamos una devolución porque el recibo queda cobrado
  else
  begin
    FRecibo.Edit;
    FRecibo.SITUACION := CTE_PAGADO;
    DeshabilitarRecibo;
  end;

  frViewPagosProveedor1.ListaPagosProveedorDBTableView1.DataController.GotoLast;
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actEliminarUpdate(Sender: TObject);
begin
  //Si el ejercicio al que pertenece la factura esta cerrado no se podrá eliminar
  if Assigned(FRecibo) and Assigned(FRecibo.Pagos) then
     frViewPagosProveedor1.actEliminar.Enabled := (FRecibo.Pagos.DataTable.RecordCount > 0)
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actModificarExecute(Sender: TObject);
var
  AFechaPago: String;
  AIgnorarContabilidad: Integer;
  AIdSubCuenta: Integer;
  ASubCuenta: String;

begin
  inherited;

  with TfEditorFechaPagoProveedor.Create(Nil) do
  begin
    FechaPago := Recibo.Pagos.FECHA_PAGO;
    IgnorarContabilidad := Recibo.Pagos.IGNORAR_CONTABILIDAD;
    if IgnorarContabilidad = 0 then
       IdSubCuenta := StrToInt(Recibo.Pagos.CUENTA);

    //En el caso de que el proveedor del recibo no tenga aignada subcuenta contable el pago no podrá contabilizarse
    if (Recibo.Proveedor.SubCuentas.ID < 1) then
    begin
       IgnorarContabilidad := 1;
       DeshabilitarContabilidad;
    end;

    //En el caso de que el ejercicio asociado al asiento del pago este cerrado o el asiento punteado
    //se podrá o no modificar el pago.
    if (Recibo.Pagos.ESTADO_EJERCICIO = CTE_CERRADO) then
    begin
      Comentario := 'El asiento asociado a este pago tiene el ejercicio cerrado, por lo que no se puede modificar';
      SoloLectura := true;
    end
    else if (Recibo.Pagos.ASIENTO_PUNTEADO > 0) then
    begin
      Comentario := 'El asiento asociado a este pago esta punteado, por lo que no se puede modificar';
      SoloLectura := true;
    end;

    if (ShowModal = mrOk) then
    begin
      AFechaPago := DateToStr(FechaPago);
      AIgnorarContabilidad := IgnorarContabilidad;
      AIdSubCuenta := IdSubcuenta;
      ASubCuenta := frViewListaSubcuentas1.cbSubCuentas.Text;
      if not SoloLectura then
         FController.ModificarPago(Recibo, AFechaPago, AIgnorarContabilidad, AIdSubCuenta, ASubCuenta);
    end;

    Release;
  end;
end;

procedure TfEditorReciboProveedor.frViewPagosProveedor1actModificarUpdate(Sender: TObject);
begin
  inherited;
  //Si el ejercicio al que pertenece la factura esta cerrado no se podrá eliminar
  if Assigned(FRecibo) and Assigned(FRecibo.Pagos) then
     frViewPagosProveedor1.actModificar.Enabled := (FRecibo.Pagos.DataTable.RecordCount > 0)
end;

procedure TfEditorReciboProveedor.frViewReciboProvImportes1eImportePropertiesEditValueChanged(
  Sender: TObject);
begin
  inherited;
  CalcularTotal;
end;

procedure TfEditorReciboProveedor.frViewReciboProveedor1eImportePropertiesValidate(
  Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption;
  var Error: Boolean);
begin
  inherited;

  if (DisplayValue > frViewReciboProvImportes1.eImporte.DataBinding.Field.Value) then
  begin
     DisplayValue := frViewReciboProvImportes1.eImporte.DataBinding.Field.Value;
     ErrorText := 'El importe debe ser menor o igual que el actual';
     Error := True;
  end;
end;

procedure TfEditorReciboProveedor.frViewRecibosProvCompensados1cxGridViewDataControllerSummaryAfterSummary(ASender: TcxDataSummary);
begin
  inherited;
  CalcularTotal;
end;

function TfEditorReciboProveedor.GetController: IRecibosProveedorController;
begin
  Result := FController;
end;

function TfEditorReciboProveedor.GetRecibo: IBizRecibosProveedor;
begin
  Result := FRecibo;
end;

function TfEditorReciboProveedor.GetViewRecibo: IViewReciboProveedor;
begin
  Result := FViewRecibo;
end;

procedure TfEditorReciboProveedor.GuardarInterno;
begin
  inherited;
  FController.Guardar(FRecibo);
  Modified := False;
end;

procedure TfEditorReciboProveedor.HabilitarRecibo;
begin
//Si el recibo tiene sociado una remesa no se podrá cambiar nada
  frViewReciboProveedor1.eReferenciaProveedor.Enabled := True;
  frViewReciboProveedor1.edtFechaVencimiento.Enabled := True;
  frViewReciboProvImportes1.eImporte.Enabled := True;
  frViewReciboProvImportes1.eOtrosGastos.Enabled := True;
end;

procedure TfEditorReciboProveedor.ImprimirInterno;
begin
{
  inherited;
  FController.Print(FRecibo);
}  
end;

procedure TfEditorReciboProveedor.JvFormStorageRestorePlacement(Sender: TObject);
begin
  inherited;
  frViewPagosProveedor1.ListaPagosProveedor.ActiveView.RestoreFromRegistry(JvAppRegistryStorage.Root);
end;

procedure TfEditorReciboProveedor.JvFormStorageSavePlacement(Sender: TObject);
begin
  inherited;
  frViewPagosProveedor1.ListaPagosProveedor.ActiveView.StoreToRegistry(JvAppRegistryStorage.Root);
end;

procedure TfEditorReciboProveedor.OnProveedorChanged(Sender: TObject);
var
  AProveedoresController : IProveedoresController;
  ADireccion : IBizDireccionesContacto;

begin
  FRecibo.Proveedor := frViewReciboProveedor1.frViewProveedorRecibo1.Proveedor;

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

  // En el caso de tener direcciones asociadas, se debe dar la posibilidad de elegir la dirección principal o las secundarias para el recibo
  AProveedoresController := TProveedoresController.Create;
  try
    case FRecibo.Proveedor.Direcciones.RecordCount of
      0   : //No hay direcciones secundarias asociadas
      else  ADireccion := AProveedoresController.ElegirDireccion(FRecibo.Proveedor, 'Seleccione la dirección del proveedor que quiere utilizar como dirección fiscal de este recibo.');
    end;

    // Si hay dirección seleccionada, copiarla al albarán y poner el coste del porte
    if Assigned(ADireccion) then
    begin
    	if not ADireccion.IDIsNull then
        try
          FRecibo.Edit;
          FController.CopiarDireccion(ADireccion, FRecibo);
        finally
          ADireccion := NIL;
        end;
    end
  finally
    AProveedoresController := Nil;
  end;
end;

procedure TfEditorReciboProveedor.PonerTitulos(const ATitulo: string);
var
  FTitulo : String;
begin
  if Assigned(Recibo) then
  begin
    if Recibo.EsNuevo then
    begin
      if Recibo.SinFactura then
        FTitulo := 'Nuevo recibo libre de proveedor'
      else
        FTitulo := 'Nuevo recibo de factura de proveedor'
    end
    else begin
      if Recibo.SinFactura then
        FTitulo := 'Recibo libre de cliente'
      else
        FTitulo := 'Recibo de factura de cliente'
    end;

    if (Recibo.ID_RECIBO_COMPENSADO > 0) then
       FTitulo := FTitulo + ' (compensado)';

    if Length(Recibo.NOMBRE_PROVEEDOR) > 0 then
       FTitulo := FTitulo + ' - ' + Recibo.NOMBRE_PROVEEDOR;
  end;

  inherited PonerTitulos(FTitulo);
end;

procedure TfEditorReciboProveedor.PrevisualizarInterno;
begin
{
  inherited;
  FController.Preview(FRecibo);
}  
end;

procedure TfEditorReciboProveedor.SetController(const Value: IRecibosProveedorController);
begin
  FController := Value;
  if Assigned(FController) then
  begin
     frViewRecibosProvCompensados1.Controller := FController;
    (ViewRecibo as IViewReciboProveedor).Controller := (FController as IRecibosProveedorController);
  end;
end;

procedure TfEditorReciboProveedor.SetRecibo(const Value: IBizRecibosProveedor);
begin
  FRecibo := Value;
  dsDataTable.DataTable := FRecibo.DataTable;

  if Assigned(FViewRecibo) and Assigned(Recibo) then
  begin
    FViewRecibo.Recibo := Recibo;
    frViewReciboProveedor1.frViewProveedorRecibo1.Proveedor := FRecibo.Proveedor;
    frViewReciboProveedor1.frViewProveedorRecibo1.OnProveedorChanged := OnProveedorChanged;

    frViewPagosProveedor1.Pagos := Recibo.Pagos;
    frViewRecibosProvCompensados1.ReciboProveedor := FRecibo;

    if FRecibo.EsNuevo and FRecibo.SinFactura then
       FRecibo.FECHA_VENCIMIENTO := Date;
    
    if (FRecibo.SITUACION = CTE_PAGADO) then
      DeshabilitarRecibo
    else
      HabilitarRecibo;
  end;
end;

procedure TfEditorReciboProveedor.SetViewRecibo(const Value: IViewReciboProveedor);
begin
  FViewRecibo := Value;

  if Assigned(FViewRecibo) and Assigned(Recibo) then
    FViewRecibo.Recibo := Recibo;
end;

end.
