unit uGenerarAlbaranesCliUtils;

interface

uses
 Windows, SysUtils, Classes, pngimage, JSDialog,
 uBizPresupuestosCliente, uBizAlbaranesCliente;

type
  TdmGenerarAlbaranesCli = class(TDataModule)
    JsListaAlbaranesGenerados: TJSDialog;
  end;

  function GenerarAlbaranCli(const IDPresupuesto : Integer) : Boolean; overload;
  function GenerarAlbaranCli(APresupuesto : IBizPresupuestoCliente) : Boolean; overload;
//  function ElegirPedidoYGenerarAlbaranCli(var IDAlbaran: Integer) : Boolean;

//  function GenerarAlbaranes(AAlbaranes : IBizAlbaraneCliente; AListaPresupuestos : IBizPresupuestoCliente): Boolean;

implementation

{$R *.dfm}

uses
  uDialogUtils, uBizDetallesPresupuestoCliente, uBizDetallesAlbaranCliente,
  uPresupuestosClienteController, uAlbaranesClienteController, uClientesController,
  uDetallesAlbaranClienteController, uControllerDetallesBase,
  uBizContactos, schPresupuestosClienteClient_Intf,
  schAlbaranesClienteClient_Intf;

var
  dmGenerarAlbaranesCli: TdmGenerarAlbaranesCli;
  APresupuestosClienteController : IPresupuestosClienteController;
  AAlbaranesClienteController : IAlbaranesClienteController;
  ADetallesAlbaranesCliController : IDetallesAlbaranClienteController;
  AClientesController : IClientesController;

{ Métodos auxiliares }
procedure CopiarPresupuestoAAlbaran(APresupuesto: IBizPresupuestoCliente; AAlbaran : IBizAlbaranCliente);
begin
  if not Assigned(AAlbaran) then
    raise Exception.Create ('Albarán no asignado (CopiarPresupuestoAAlbaran)');

  if not Assigned(APresupuesto) then
    raise Exception.Create ('Pedido no asignado (CopiarPresupuestoAAlbaran)');

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

  // El albarán tiene que venir ya abierto y posicionado donde hay que copiar
  AAlbaran.ID_CLIENTE := APresupuesto.ID_CLIENTE;
  AAlbaran.ID_PEDIDO := APresupuesto.ID;
  AAlbaran.REFERENCIA_CLIENTE := APresupuesto.REFERENCIA_CLIENTE;
//  AAlbaran.CALLE := APresupuesto.CALLE;
//  AAlbaran.CODIGO_POSTAL := APresupuesto.CODIGO_POSTAL;
//  AAlbaran.POBLACION := APresupuesto.POBLACION;
//  AAlbaran.PROVINCIA := APresupuesto.PROVINCIA;
//  AAlbaran.PERSONA_CONTACTO := APresupuesto.PERSONA_CONTACTO;
//  AAlbaran.TELEFONO := APresupuesto.TELEFONO;
  AAlbaran.IMPORTE_NETO := APresupuesto.IMPORTE_NETO;
  AAlbaran.IMPORTE_PORTE := APresupuesto.IMPORTE_PORTE;
  AAlbaran.DESCUENTO := APresupuesto.DESCUENTO;
  AAlbaran.IMPORTE_DESCUENTO := APresupuesto.IMPORTE_DESCUENTO;
  AAlbaran.BASE_IMPONIBLE := APresupuesto.BASE_IMPONIBLE;
  AAlbaran.IVA := APresupuesto.IVA;
  AAlbaran.IMPORTE_IVA := APresupuesto.IMPORTE_IVA;
  AAlbaran.IMPORTE_TOTAL := APresupuesto.IMPORTE_TOTAL;
  AAlbaran.DataTable.FieldByName(fld_AlbaranesClienteOBSERVACIONES).AsVariant := APresupuesto.DataTable.FieldByName(fld_PresupuestosClienteOBSERVACIONES).AsVariant;
  AAlbaran.ID_FORMA_PAGO := APresupuesto.ID_FORMA_PAGO;
//  AAlbaran.FECHA_PREVISTA_ENVIO := APresupuesto.FECHA_PREVISTA_ENVIO;
end;

{
procedure CopiarArticulosPendAAlbaran(
  APedido: IBizPedidoCliente;
  AAlbaran: IBizAlbaranCliente;
  AArticulosPendientes: IBizPedidoClienteArticulosPend);
var
  i : integer;
  ADetalles : IBizDetallesAlbaranCliente;
  ADetallesController : IDetallesAlbaranClienteController;
begin
  if not Assigned(AAlbaran) then
    raise Exception.Create ('Albarán no asignado (CopiarArticulosPendAAlbaran)');

  if not Assigned(APedido) then
    raise Exception.Create ('Pedido no asignado (CopiarArticulosPendAAlbaran)');

  if not Assigned(AArticulosPendientes) then
    raise Exception.Create ('Artículos pendientes no asignado (CopiarArticulosPendAAlbaran)');

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

  // El albarán tiene que venir ya abierto y posicionado donde hay que copiar

  ADetalles := AAlbaran.Detalles;
  ADetallesController := TDetallesAlbaranClienteController.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(ADetalles);

    AArticulosPendientes.DataTable.First;
    for i := 0 to AArticulosPendientes.DataTable.RecordCount - 1 do
    begin
      APedido.Detalles.First;
      if (APedido.Detalles.Locate('ID_ARTICULO', AArticulosPendientes.ID_ARTICULO, [])) then
        if (AArticulosPendientes.CANTIDAD_PENDIENTE > 0) then
        begin
          ADetallesController.Add(ADetalles, TIPO_DETALLE_CONCEPTO);
          ADetalles.Edit;
          ADetalles.ID_PEDIDO := APedido.Detalles.ID_PEDIDO;
          ADetalles.REFERENCIA := APedido.Detalles.REFERENCIA;
          ADetalles.ID_ARTICULO := APedido.Detalles.ID_ARTICULO;
          ADetalles.CONCEPTO := APedido.Detalles.CONCEPTO;
          ADetalles.CANTIDAD := AArticulosPendientes.CANTIDAD_PENDIENTE;
          ADetalles.IMPORTE_UNIDAD := APedido.Detalles.IMPORTE_UNIDAD;
          ADetalles.IMPORTE_TOTAL := APedido.Detalles.IMPORTE_TOTAL;
          ADetalles.DESCUENTO := APedido.Detalles.DESCUENTO;
          ADetalles.IMPORTE_PORTE := APedido.Detalles.IMPORTE_PORTE;
          ADetalles.VISIBLE := APedido.Detalles.VISIBLE;
          ADetalles.REFERENCIA_PROVEEDOR := APedido.Detalles.REFERENCIA_PROVEEDOR;
          ADetalles.Post;
          AArticulosPendientes.Next;
        end;
    end;
  finally
    ADetallesController.EndUpdate(ADetalles);
    ADetallesController := NIL;
  end;
end;
}

procedure Inicializar;
begin
  dmGenerarAlbaranesCli := TdmGenerarAlbaranesCli.Create(nil);
  APresupuestosClienteController := TPresupuestosClienteController.Create;
  AAlbaranesClienteController := TAlbaranesClienteController.Create;
  ADetallesAlbaranesCliController := TDetallesAlbaranClienteController.Create;
  AClientesController := TClientesController.Create;
end;

procedure Finalizar;
begin
  FreeAndNIL(dmGenerarAlbaranesCli);
  APresupuestosClienteController := nil;
  AAlbaranesClienteController := nil;
  ADetallesAlbaranesCliController := nil;
  AClientesController := nil;
end;


function GenerarAlbaranCli(const IDPresupuesto : Integer) : Boolean; overload;
var
  APresupuesto : IBizPresupuestoCliente;

begin
  Result := False;

  try
    if not Assigned(APresupuestosClienteController) then
       Inicializar;

    APresupuesto := APresupuestosClienteController.Buscar(IDPresupuesto);

    if Assigned(APresupuesto) then
      Result := GenerarAlbaranCli(APresupuesto);

    if Assigned(APresupuestosClienteController) then
       Finalizar;

  finally
    APresupuesto := NIL;
  end;
end;


function GenerarAlbaranCli(APresupuesto : IBizPresupuestoCliente) : Boolean; overload;
var
  i: Integer;
  AlbaranesNuevos: IBizAlbaranCliente;

begin
  Result := False;
{
  if not Assigned(APresupuesto) then
    raise Exception.Create('Presupuesto de cliente no asignado (GenerarAlbaranCli)');

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

  if not Assigned(APresupuestosClienteController) then
     Inicializar;
     
  try
    AlbaranesNuevos := AAlbaranesClienteController.Nuevo(False);
    if GenerarAlbaranes(AlbaranesNuevos, APresupuesto) then
    begin
      if AlbaranesNuevos.DataTable.RecordCount = 1 then
         ShowInfoMessage('El albarán se ha dado de alta con el código ' + AlbaranesNuevos.REFERENCIA)
      else begin
         with dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Content do
         begin
           Clear;
           AlbaranesNuevos.DataTable.Last;
           for i := 0 to AlbaranesNuevos.DataTable.RecordCount - 1 do
           begin
             if Length(AlbaranesNuevos.REFERENCIA) > 0 then
                Add(AlbaranesNuevos.REFERENCIA + ': ' + AlbaranesNuevos.NOMBRE);
             AlbaranesNuevos.DataTable.Prior;
           end;
         end;
         dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Execute;
      end;

      Result := True;
    end;

   finally
     AlbaranesNuevos := NIL;
     if Assigned(APresupuestosClienteController) then
        Finalizar;
   end;
}   
end;

{
function ElegirPedidoYGenerarAlbaranCli(var IDAlbaran: Integer) : Boolean; overload;
var
  APedido : IBizPedidoCliente;
  AAlbaran : IBizAlbaranCliente;
begin
  Result := False;
  IDAlbaran := -1;

  AAlbaran := NIL;
  try
    if not Assigned(APedidosClienteController) then
      Inicializar;

    APedido := APedidosClienteController.ElegirPedidos(APedidosClienteController.BuscarPendientes,
                  'Elija el pedido de cliente que desea utilizar para dar de alta el albarán de cliente.'
                  , False);

    if Assigned(APedido) then
    begin
      Result := GenerarAlbaranCli(APedido, AAlbaran);
      if Result then
        IDAlbaran := AAlbaran.ID;
    end;
  finally
    if Assigned(APedidosClienteController) then
      Finalizar;
  end;
end;
}

{function GenerarAlbaranes(AAlbaranes : IBizAlbaraneCliente; AListaPresupuestos : IBizPresupuestoCliente): Boolean;
var
  AAlbaranActual : IBizAlbaranCliente;
  APresupuestosController : IPresupuestosClienteController;
  I: Integer;
  bEnEdicion : Boolean;

begin
    // ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas
    // ya generadas.
{    if not Assigned(AAlbaranes) then
      raise Exception.Create ('Albaran no asignado (Anadir)');

    if not Assigned(AListaPresupuestos) then
      raise Exception.Create ('Presupuestos no asignados (Anadir)');



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

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

  //  ShowHourglassCursor;
  //  Application.ProcessMessages;

    APresupuestosController := TPresupuestosClienteController.Create;
    try
      // Ordenar por fecha de albaran
      AListaPresupuestos.DataTable.Sort([fld_PresupuestosClienteFECHA_PRESUPUESTO], [uDADataTable.sdAscending]);
      AListaPresupuestos.First;
      for I := 0 to AListaPresupuestos.DataTable.RecordCount - 1 do
      begin
        AListaPresupuestos._Cliente := NIL;
        AAlbaranActual := NIL;

        // Busco si hay alguna factura ya hecha de ese Proveedor
        AAlbaranes.DataTable.First;
        if AAlbaranes.DataTable.Locate(fld_AlbaranesClienteID_Cliente, AListaPresupuestos.ID_Cliente, []) then
        begin
          AAlbaranActual := AAlbaranes;
          AAlbaranesClienteController.RecuperarProveedor(AAlbaranActual);
          AAlbaranActual.Proveedor.DataTable.Active := True;
        end
        else begin
          // No hay factura de ese Proveedor. Creo una nueva
          AAlbaranesClienteController.Anadir(AAlbaranes);
          APresupuestosController.RecuperarProveedor(AListaPresupuestos);
          AAlbaranes.Proveedor := AListaPresupuestos.Proveedor;

          //Siempre asignaremos por defecto la referencia de factura de proveedor que tenga el primer albaran del proveedor
          bEnEdicion := (AAlbaranes.DataTable.State in dsEditModes);
          if not bEnEdicion then
             AAlbaranes.Edit;
          AAlbaranes.REFERENCIA_PROVEEDOR := AListaPresupuestos.REF_FACTURA_PROV;
          AAlbaranes.Post;
          if bEnEdicion then
             AAlbaranes.Edit;

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

          AAlbaranActual := AAlbaranes;
        end;

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

  {En los albaranes a proveedor el porte es a nivel del artículo
        Self.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_CONCEPTO);
        with AAlbaranActual.Detalles do
        begin
          Edit;
          CONCEPTO := 'Porte del albarán';
          CANTIDAD := 1;
          IMPORTE_UNIDAD := AListaPresupuestos.IMPORTE_PORTE;
          Post;
        end;
  }

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

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

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

        AListaPresupuestos.Next;
      end;
      Result := True;
    finally
      APresupuestosController := NIL;
//      HideHourglassCursor
    end;
  end;
}

end.
