unit uGenerarAlbaranesCliUtils; interface uses Windows, SysUtils, Classes, pngimage, JSDialog, uBizContactos, uBizPedidosCliente, uBizAlbaranesCliente, uBizInventario; 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; //Metodos para albaranar articulos pendientes function GenerarAlbaranesCli(AArticulos : IBizDetalleSinAlbaran; var AAlbaranes: IBizAlbaranCliente; const IDAlmacen:Integer) : Boolean; overload; procedure InicializarAlbaran(var AAlbaranes: IBizAlbaranCliente; ACliente: IBizCliente; const IDAlmacen:Integer; AArticulos: IBizDetalleSinAlbaran); implementation {$R *.dfm} uses cxControls, uDialogUtils, uBizDetallesPedidoCliente, uBizDetallesAlbaranCliente, uPedidosClienteController, uAlbaranesClienteController, uClientesController, uDetallesAlbaranClienteController, uControllerDetallesBase, schPedidosClienteClient_Intf, uDADataTable, schAlbaranesClienteClient_Intf, schInventarioClient_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.TIPO := CTE_TIPO_ALBARAN; 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.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); 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; function GenerarAlbaranesCli(AArticulos : IBizDetalleSinAlbaran; var AAlbaranes: IBizAlbaranCliente; const IDAlmacen:Integer) : Boolean; overload; var ARespuesta : Integer; ACliente: IBizCliente; RefPedCliAux: String; I: Integer; begin Result := False; if not Assigned(AArticulos) then raise Exception.Create('AArticulos no asignado (GenerarAlbaranesCli)'); if not Assigned(APedidosClienteController) then Inicializar; ShowHourglassCursor; try //Preparamos el componente donde almacenaremos las referencias de los albaranes generados dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.CustomButtons.Clear; dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Content.Clear; dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Instruction.Text := 'Se han generado los albaranes'; // Ordenar por cliente y pedido AArticulos.DataTable.Sort([fld_AlbaranesClienteID_CLIENTE, fld_AlbaranesClienteID_PEDIDO], [uDADataTable.sdAscending, uDADataTable.sdAscending]); AArticulos.DataTable.First; //Inicializamos albaran ACliente := (AClientesController.Buscar(AArticulos.ID_CLIENTE) as IBizCliente); ACliente.DataTable.Active := True; AAlbaranes := AAlbaranesClienteController.Nuevo; InicializarAlbaran(AAlbaranes, ACliente, IDAlmacen, AArticulos); //Aqui no es necesario BeginUpdate y EndUpdate de los detalles porque siempre añadimos una linea al final. // Añado el título del pedido ya que siempre tendremos al menos un concepto de pedido ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_TITULO); with AAlbaranes.Detalles do begin Edit; RefPedCliAux := AArticulos.REFERENCIA_PEDIDO; CONCEPTO := 'Pedido ' + AArticulos.REFERENCIA_PEDIDO + ' (Ref.Cliente: ' + AArticulos.REFERENCIA_CLI_PEDIDO + ') del ' + DateToStr(AArticulos.FECHA_PEDIDO); Post; end; for I := 0 to AArticulos.DataTable.RecordCount - 1 do begin //En el caso que se cambie de pedido, cerramos detalles del pedido if (RefPedCliAux <> AArticulos.REFERENCIA_PEDIDO) then begin // Añado el resumen del pedido ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_SUBTOTAL); with AAlbaranes.Detalles do begin Edit; CONCEPTO := 'Total del pedido ' + RefPedCliAux; Post; end; // Añado una línea en blanco ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_CONCEPTO); with AAlbaranes.Detalles do begin Edit; CONCEPTO := ''; Post; end; //En el caso que cambie de pedido pero no de cliente volvemos a crear la cabecera del nuevo pedido if (ACliente.ID = AArticulos.ID_CLIENTE) then begin // Añado el título del pedido ya que siempre tendremos al menos un concepto de pedido ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_TITULO); with AAlbaranes.Detalles do begin Edit; RefPedCliAux := AArticulos.REFERENCIA_PEDIDO; CONCEPTO := 'Pedido ' + AArticulos.REFERENCIA_PEDIDO + ' (Ref.Cliente: ' + AArticulos.REFERENCIA_CLI_PEDIDO + ') del ' + DateToStr(AArticulos.FECHA_PEDIDO); Post; end; end; end; //En el caso que cambie el cliente se guarda el albaran actual y se crea uno nuevo if (ACliente.ID <> AArticulos.ID_CLIENTE) then begin AAlbaranesClienteController.RecalcularImportes(AAlbaranes); AAlbaranesClienteController.Guardar(AAlbaranes); dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Content.Add(Format('%s: %s' + #10#13, [AAlbaranes.REFERENCIA, ACliente.NOMBRE])); //Inicializamos albaran ACliente := (AClientesController.Buscar(AArticulos.ID_CLIENTE) as IBizCliente); ACliente.DataTable.Active := True; AAlbaranesClienteController.Anadir(AAlbaranes); InicializarAlbaran(AAlbaranes, ACliente, IDAlmacen, AArticulos); // Añado el título del pedido ya que siempre tendremos al menos un concepto de pedido ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_TITULO); with AAlbaranes.Detalles do begin Edit; RefPedCliAux := AArticulos.REFERENCIA_PEDIDO; CONCEPTO := 'Pedido ' + AArticulos.REFERENCIA_PEDIDO + ' (Ref.Cliente: ' + AArticulos.REFERENCIA_CLI_PEDIDO + ') del ' + DateToStr(AArticulos.FECHA_PEDIDO); Post; end; end; //Rellenamos el detalle del albarán ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_CONCEPTO); AAlbaranes.Detalles.Edit; AAlbaranes.Detalles.ID_PEDIDO := AArticulos.ID_PEDIDO; AAlbaranes.Detalles.REFERENCIA := AArticulos.REFERENCIA; AAlbaranes.Detalles.REFERENCIA_PROVEEDOR := AArticulos.REFERENCIA_PROVEEDOR; AAlbaranes.Detalles.ID_ARTICULO := AArticulos.ID_ARTICULO; AAlbaranes.Detalles.CONCEPTO := AArticulos.DESCRIPCION; AAlbaranes.Detalles.CANTIDAD := AArticulos.CANTIDAD_PENDIENTE; AAlbaranes.Detalles.IMPORTE_UNIDAD := AArticulos.PRECIO_COSTE; AAlbaranes.Detalles.DESCUENTO := AArticulos.DESCUENTO; AAlbaranes.Detalles.Post; //Pasamos al siguiente articulo AArticulos.DataTable.Next; end; //Finalmente cerraremos el último pedido del último albarán ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_SUBTOTAL); with AAlbaranes.Detalles do begin Edit; CONCEPTO := 'Total del pedido ' + RefPedCliAux; Post; end; // Añado una línea en blanco ADetallesAlbaranesCliController.Add(AAlbaranes.Detalles, TIPO_DETALLE_CONCEPTO); with AAlbaranes.Detalles do begin Edit; CONCEPTO := ''; Post; end; AAlbaranesClienteController.RecalcularImportes(AAlbaranes); AAlbaranesClienteController.Guardar(AAlbaranes); dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Content.Add(Format('%s: %s' + #10#13, [AAlbaranes.REFERENCIA, ACliente.NOMBRE])); finally HideHourglassCursor; //Visualizamos los albaranes generados dmGenerarAlbaranesCli.JsListaAlbaranesGenerados.Execute; if Assigned(APedidosClienteController) then Finalizar; end; end; procedure InicializarAlbaran(var AAlbaranes: IBizAlbaranCliente; ACliente: IBizCliente; const IDAlmacen:Integer; AArticulos: IBizDetalleSinAlbaran); begin //El albaran debe venir abierto y posicionado para la copia. AAlbaranes.Cliente := (ACliente as IBizCliente); AAlbaranes.TIPO := CTE_TIPO_ALBARAN; AAlbaranes.ID_ALMACEN := IDAlmacen; AAlbaranes.REFERENCIA_CLIENTE := AArticulos.REFERENCIA_CLI_PEDIDO; AAlbaranes.FECHA_PREVISTA_ENVIO := AArticulos.FECHA_PREVISTA_PEDIDO; AAlbaranes.CALLE := AArticulos.CALLE; AAlbaranes.CODIGO_POSTAL := AArticulos.CODIGO_POSTAL; AAlbaranes.POBLACION := AArticulos.POBLACION; AAlbaranes.PROVINCIA := AArticulos.PROVINCIA; AAlbaranes.PERSONA_CONTACTO := AArticulos.PERSONA_CONTACTO; AAlbaranes.TELEFONO := AArticulos.TELEFONO; AAlbaranes.IVA := AArticulos.IVA; AAlbaranes.ID_FORMA_PAGO := AArticulos.ID_FORMA_PAGO; end; end.