unit uGenerarAlbaranesCliUtils;

interface

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

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

  function GenerarAlbaranCli(const IDPedido : Integer; var IDAlbaran: Integer) : Boolean; overload;
  function GenerarAlbaranCli(APedido : IBizPedidoCliente; var AAlbaran: IBizAlbaranCliente) : Boolean; overload;
  function ElegirPedidoYGenerarAlbaranCli(var IDAlbaran: Integer) : Boolean;

implementation

{$R *.dfm}

uses
  uDialogUtils, uBizDetallesPedidoCliente, uBizDetallesAlbaranCliente,
  uPedidosClienteController, uAlbaranesClienteController, uClientesController,
  uDetallesAlbaranClienteController, uControllerDetallesBase,
  uBizContactos, schPedidosClienteClient_Intf,
  schAlbaranesClienteClient_Intf;

var
  dmGenerarAlbaranesCli: TdmGenerarAlbaranesCli;
  APedidosClienteController : IPedidosClienteController;
  AAlbaranesClienteController : IAlbaranesClienteController;
  ADetallesAlbaranesCliController : IDetallesAlbaranClienteController;
  AClientesController : IClientesController;

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

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

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

  // El albarán tiene que venir ya abierto y posicionado donde hay que copiar
  AAlbaran.ID_CLIENTE := APedido.ID_CLIENTE;
  AAlbaran.ID_PEDIDO := APedido.ID;
  AAlbaran.REFERENCIA_CLIENTE := APedido.REFERENCIA_CLIENTE;
  AAlbaran.CALLE := APedido.CALLE;
  AAlbaran.CODIGO_POSTAL := APedido.CODIGO_POSTAL;
  AAlbaran.POBLACION := APedido.POBLACION;
  AAlbaran.PROVINCIA := APedido.PROVINCIA;
  AAlbaran.PERSONA_CONTACTO := APedido.PERSONA_CONTACTO;
  AAlbaran.TELEFONO := APedido.TELEFONO;
  AAlbaran.IMPORTE_NETO := APedido.IMPORTE_NETO;
  AAlbaran.IMPORTE_PORTE := APedido.IMPORTE_PORTE;
  AAlbaran.DESCUENTO := APedido.DESCUENTO;
  AAlbaran.IMPORTE_DESCUENTO := APedido.IMPORTE_DESCUENTO;
  AAlbaran.BASE_IMPONIBLE := APedido.BASE_IMPONIBLE;
  AAlbaran.IVA := APedido.IVA;
  AAlbaran.IMPORTE_IVA := APedido.IMPORTE_IVA;
  AAlbaran.IMPORTE_TOTAL := APedido.IMPORTE_TOTAL;
  AAlbaran.DataTable.FieldByName(fld_AlbaranesClienteOBSERVACIONES).AsVariant := APedido.DataTable.FieldByName(fld_PedidosClienteOBSERVACIONES).AsVariant;
  AAlbaran.ID_FORMA_PAGO := APedido.ID_FORMA_PAGO;
  AAlbaran.FECHA_PREVISTA_ENVIO := APedido.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.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);
  APedidosClienteController := TPedidosClienteController.Create;
  AAlbaranesClienteController := TAlbaranesClienteController.Create;
  ADetallesAlbaranesCliController := TDetallesAlbaranClienteController.Create;
  AClientesController := TClientesController.Create;
end;

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


function GenerarAlbaranCli(const IDPedido : Integer;
  var IDAlbaran: Integer) : Boolean; overload;
var
  APedido : IBizPedidoCliente;
  AAlbaran : IBizAlbaranCliente;
begin
  Result := False;
  IDAlbaran := -1;
  
  try
    if not Assigned(APedidosClienteController) then
       Inicializar;

    APedido := APedidosClienteController.Buscar(IDPedido);
    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 GenerarAlbaranCli(APedido : IBizPedidoCliente; var AAlbaran: IBizAlbaranCliente) : Boolean; overload;
var
  ARespuesta : Integer;
  AuxAlbaran : IBizAlbaranCliente;
  AArticulosPendientes: IBizPedidoClienteArticulosPend;
begin
  Result := False;
  AAlbaran := NIL;

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

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

  if not Assigned(APedidosClienteController) then
     Inicializar;

  try
    AArticulosPendientes := APedidosClienteController.ArticulosPendientes(APedido.ID);
    if not Assigned(AArticulosPendientes) then
      raise Exception.Create('Error al recuperar los artículos sin albarán del pedido (GenerarAlbaranCli)');

    AArticulosPendientes.DataTable.Active := True;
    if AArticulosPendientes.DataTable.RecordCount = 0 then
    begin
      ShowWarningMessage('Generar albarán a partir del pedido', 'Todos los artículos de este pedido ya figuran en uno o más albaranes de cliente. Por lo que no se pueden generar nuevos albaranes para este pedido');
        Exit; // Aunque es un exit, se ejecuta la parte del finally antes de salir.
    end;

    AuxAlbaran := AAlbaranesClienteController.Nuevo;
    CopiarPedidoAAlbaran(APedido, AuxAlbaran);
    CopiarArticulosPendAAlbaran(APedido, AuxAlbaran, AArticulosPendientes);

    //Sustituir por if de guardar
    if AAlbaranesClienteController.Guardar(AuxAlbaran) then
    begin
      AAlbaran := AuxAlbaran;
      with dmGenerarAlbaranesCli.JsListaAlbaranesGenerados do
      begin
        Instruction.Text := 'Se ha generado el albarán';

        Content.Clear;
        Content.Add(Format('Se ha generado correctamente el albarán %s a partir del pedido de cliente' + #10#13, [AuxAlbaran.REFERENCIA]));
        Execute;

        ARespuesta := CustomButtonResult;
        case ARespuesta of
          100 : begin
                  // Ver el albarán
                  AAlbaranesClienteController.Ver(AuxAlbaran);
                end;
          200 : // Continuar;
        end;
      end;
    end;

    Result := True;
  finally
    AArticulosPendientes := NIL;
    if Assigned(APedidosClienteController) 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;

end.
