Skip to main content

I am developing a new processing to process web orders that can be pushed straight through to creating a shipment.  I have the process set up that assigns the owner and creates the shipment but I’m not sure how to automatically send the shipment confirmation report to a specific printer on devicehub.

The code I have which works to the point of creating the shipment and storing the shipment number is below.

using System;
using PX.Data;
using PX.Objects.SO;
using PX.Data.BQL.Fluent;
using PX.TM;
using PX.Common;
using System.Collections.Generic;
using PX.Objects.CR;
using PX.SM;
using PX.Reports;

namespace PPCustomOrderProcess
{

public class AIProcessOrdersCust : PXGraph<AIProcessOrdersCust>
{

public class wOOrderType: PX.Data.BQL.BqlString.Constant<wOOrderType> {
public wOOrderType() : base("WO") { }
}

public class paymentMethodAFFIRM: PX.Data.BQL.BqlString.Constant<paymentMethodAFFIRM> {
public paymentMethodAFFIRM() : base("AFFIRM") { }
}

public class paymentMethodAFTERPAY: PX.Data.BQL.BqlString.Constant<paymentMethodAFTERPAY> {
public paymentMethodAFTERPAY() : base("AFTERPAY") { }
}

public class paymentMethodPAYPAL: PX.Data.BQL.BqlString.Constant<paymentMethodPAYPAL> {
public paymentMethodPAYPAL() : base("PAYPAL") { }
}

public class paymentMethodCCARD: PX.Data.BQL.BqlString.Constant<paymentMethodCCARD> {
public paymentMethodCCARD() : base("CCARD") { }
}

public class dropShipStart: PX.Data.BQL.BqlString.Constant<dropShipStart> {
public dropShipStart() : base("DS%") { }
}

public class signatureWaived: PX.Data.BQL.BqlString.Constant<signatureWaived> {
public signatureWaived() : base("%SIGNATURE WAIVED%") { }
}

public class orderTotalMaxSpend: PX.Data.BQL.BqlDecimal.Constant<orderTotalMaxSpend> {
public orderTotalMaxSpend() : base(500m) { }
}

public PXCancel<SOOrder> Cancel;

// Create an alias for clarity
public class OuterSOOrder : SOOrder { }

public SelectFrom<SOOrder>
.LeftJoin<Note>.On<SOOrder.noteID.IsEqual<Note.noteID>>
.Where<
SOOrder.orderType.IsEqual<wOOrderType>
.And<
SOOrder.shipVia.IsNotLike<dropShipStart>
>
.And<
SOOrder.status.IsEqual<SOOrderStatus.open>
.Or<
SOOrder.status.IsEqual<SOOrderStatus.awaitingPayment>
>
>
.And<
Note.noteID.IsNull
.Or<Note.noteText.IsNull>
.Or<Note.noteText.IsEqual<Empty>>
.Or<Note.noteText.IsLike<signatureWaived>>
>
.And<
SOOrder.curyOrderTotal.IsLessEqual<orderTotalMaxSpend>
>
.And<
SOOrder.paymentMethodID.IsEqual<paymentMethodAFFIRM>
.Or<SOOrder.paymentMethodID.IsEqual<paymentMethodPAYPAL>>
.Or<SOOrder.paymentMethodID.IsEqual<paymentMethodAFTERPAY>>
.Or<
SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>
.And<
Exists<SelectFrom<SOOrder>
.Where<
SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>
.And<
SOOrder.customerID.IsEqual<OuterSOOrder.customerID>
>
.And<
SOOrder.status.IsEqual<SOOrderStatus.shipping> // Change shipping to completed before final publish
>
>
>
>
>
>
>
.ProcessingView AISOOrder;

public AIProcessOrdersCust()
{
AISOOrder.SetProcessCaption("Assign");
AISOOrder.SetProcessAllCaption("Assign All");

AISOOrder.SetProcessDelegate(ProcessOrder);
}

public PXFilter<DetailsTable> DetailsView;

Serializable]
public class DetailsTable : IBqlTable
{

}

/// <summary>
/// Processing Method to Assign Owner to Logged-in User
/// </summary>
private static void ProcessOrder(SOOrder order)
{
var graph = PXGraph.CreateInstance<SOOrderEntry>();

// Select the order
graph.Document.Current = graph.Document.Search<SOOrder.orderNbr>(order.OrderNbr, order.OrderType);

if (graph.Document.Current != null)
{
int? currentUserContactID = PXAccess.GetContactID();
if (currentUserContactID != null)
{
graph.Document.Cache.SetValueExt<SOOrder.ownerID>(graph.Document.Current, currentUserContactID);
graph.Document.Cache.MarkUpdated(graph.Document.Current);

// Log the new OwnerID for verification
PXTrace.WriteInformation($"Setting OwnerID to {currentUserContactID} for Order {order.OrderNbr}");

// Save the changes
graph.Actions.PressSave();

// Create a shipment for the order

bool shipmentCreated = CreateShipmentFromButton(graph);

// Confirm the shipmnent is created before pressing the new button

if (shipmentCreated)
{
// Retrieve the Shipment Number
var shipmentNbr = GetShipmentNumber(order);

if (!string.IsNullOrEmpty(shipmentNbr))
{
// Load shipment graph and print the shipment confirmation
var shipmentGraph = PXGraph.CreateInstance<SOShipmentEntry>();
var shipment = shipmentGraph.Document.Search<SOShipment.shipmentNbr>(shipmentNbr);

if (shipment != null)
{
bool printedShipmentConfirmation = PrintShipmentConfirmation(shipmentGraph, shipmentNbr);

if (printedShipmentConfirmation)
{
PXProcessing<SOOrder>.SetInfo($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID} and shipment {shipmentNbr} printed.");
}
else
{
PXProcessing<SOOrder>.SetInfo($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID} and shipment {shipmentNbr} created but not printed.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID}, but shipment could not be retrieved to print.");
}
}
else
{
PXProcessing<SOOrder>.SetWarning($"Shipment created, but no shipment number found for Order {order.OrderNbr}.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID}, but shipment could not be created.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Failed to assign OwnerID: No ContactID found for current user.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} not found.");
}
}

private static bool PrintShipmentConfirmation(SOShipmentEntry shipmentGraph, string shipmentNbr)
{
bool success = false;

if (string.IsNullOrEmpty(shipmentNbr))
{
throw new PXException("Shipment Number is required for printing.");
}

try
{
////// THIS IS WHERE I AM STUCK ON HOW TO PRINT TO THE PRINTER AUTOMATICALLY //////

PXTrace.WriteInformation($"Shipment Confirmation for {shipmentNbr} has been sent to the printer '{printerName}'.");
success = true;
}
catch (Exception ex)
{
PXTrace.WriteError($"Failed to print Shipment Confirmation for {shipmentNbr}. Error: {ex.Message}");
throw new PXException($"Failed to print Shipment Confirmation for {shipmentNbr}. Please check the printer configuration.");
}

return success;

}

/// <summary>
/// Retrieves the Shipment Number associated with the order.
/// </summary>
private static string GetShipmentNumber(SOOrder order)
{
var shipment = PXSelect<SOOrderShipment,
Where<SOOrderShipment.orderType, Equal<Required<SOOrderShipment.orderType>>,
And<SOOrderShipment.orderNbr, Equal<Required<SOOrderShipment.orderNbr>>>>>
.SelectWindowed(new PXGraph(), 0, 1, order.OrderType, order.OrderNbr);

return shipment != null ? ((SOOrderShipment)shipment).ShipmentNbr : null;
}

private static bool CreateShipmentFromButton(SOOrderEntry graph)
{

// Trigger the "Create Shipment" action on the graph (simulate button click)
PXAction<SOOrder> createShipmentAction = graph.Actionso"CreateShipment"] as PXAction<SOOrder>;
if (createShipmentAction != null)
{
// If the button exists, press it programmatically
PXTrace.WriteInformation($"Pressing button for create shipment");

createShipmentActionPress(graph);

return true;
}
else
{
PXTrace.WriteError("Create Shipment action not found.");
}
return false;

}

private static void createShipmentActionPress(SOOrderEntry graph)
{
try
{
PXAction<SOOrder> createShipmentAction = graph.Actionso"CreateShipment"] as PXAction<SOOrder>;
createShipmentAction?.Press();
}
catch (Exception ex)
{
PXTrace.WriteError("Error pressing Create Shipment button: " + ex.Message);
}
}

}
}

Thanks for any advice,

 

Phil

I can now print to a specific named printer on the device hub.  Code is below:

 

using System;
using PX.Data;
using PX.Objects.SO;
using PX.Data.BQL.Fluent;
using PX.TM;
using PX.Common;
using System.Collections.Generic;
using PX.Objects.CR;
using PX.SM;
using PX.Reports;
using System.Threading.Tasks;
using System.Threading;

namespace PPCustomOrderProcess
{

public class AIProcessOrdersCust : PXGraph<AIProcessOrdersCust>
{

PXString]
PXUIField(DisplayName = "Printer")]
PXSelector(
typeof(Search<SMPrinter.printerID>),
typeof(SMPrinter.printerName),
typeof(SMPrinter.description),
SubstituteKey = typeof(SMPrinter.printerName),
DescriptionField = typeof(SMPrinter.description))]
public virtual Guid? SelectedPrinter { get; set; }
public abstract class selectedPrinter : PX.Data.BQL.BqlGuid.Field<selectedPrinter> { }

public class wOOrderType: PX.Data.BQL.BqlString.Constant<wOOrderType> {
public wOOrderType() : base("WO") { }
}

public class paymentMethodAFFIRM: PX.Data.BQL.BqlString.Constant<paymentMethodAFFIRM> {
public paymentMethodAFFIRM() : base("AFFIRM") { }
}

public class paymentMethodAFTERPAY: PX.Data.BQL.BqlString.Constant<paymentMethodAFTERPAY> {
public paymentMethodAFTERPAY() : base("AFTERPAY") { }
}

public class paymentMethodPAYPAL: PX.Data.BQL.BqlString.Constant<paymentMethodPAYPAL> {
public paymentMethodPAYPAL() : base("PAYPAL") { }
}

public class paymentMethodCCARD: PX.Data.BQL.BqlString.Constant<paymentMethodCCARD> {
public paymentMethodCCARD() : base("CCARD") { }
}

public class dropShipStart: PX.Data.BQL.BqlString.Constant<dropShipStart> {
public dropShipStart() : base("DS%") { }
}

public class signatureWaived: PX.Data.BQL.BqlString.Constant<signatureWaived> {
public signatureWaived() : base("%SIGNATURE WAIVED%") { }
}

public class intlShipVia: PX.Data.BQL.BqlString.Constant<intlShipVia> {
public intlShipVia() : base("%intl%") { }
}

public class orderTotalMaxSpend: PX.Data.BQL.BqlDecimal.Constant<orderTotalMaxSpend> {
public orderTotalMaxSpend() : base(500m) { }
}

public PXCancel<SOOrder> Cancel;

// Create an alias for clarity
public class OuterSOOrder : SOOrder { }

public SelectFrom<SOOrder>
.LeftJoin<Note>.On<SOOrder.noteID.IsEqual<Note.noteID>>
.Where<
SOOrder.orderType.IsEqual<wOOrderType>
.And<
SOOrder.shipVia.IsNotLike<intlShipVia>
>
.And<
SOOrder.shipVia.IsNotLike<dropShipStart>
>
.And<
SOOrder.status.IsEqual<SOOrderStatus.open>
>
.And<
Note.noteID.IsNull
.Or<Note.noteText.IsNull>
.Or<Note.noteText.IsEqual<Empty>>
.Or<Note.noteText.IsLike<signatureWaived>>
>
.And<
SOOrder.curyOrderTotal.IsLessEqual<orderTotalMaxSpend>
>
.And<
SOOrder.paymentMethodID.IsEqual<paymentMethodAFFIRM>
.Or<SOOrder.paymentMethodID.IsEqual<paymentMethodPAYPAL>>
.Or<SOOrder.paymentMethodID.IsEqual<paymentMethodAFTERPAY>>
.Or<
SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>
.And<
Exists<SelectFrom<SOOrder>
.Where<
SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>
.And<
SOOrder.customerID.IsEqual<OuterSOOrder.customerID>
>
.And<
SOOrder.status.IsEqual<SOOrderStatus.shipping> // Change shipping to completed before final publish
>
>
>
>
>
>
>
.ProcessingView AISOOrder;


public AIProcessOrdersCust()
{
AISOOrder.SetProcessCaption("Assign");
AISOOrder.SetProcessAllCaption("Assign All");

AISOOrder.SetProcessDelegate(ProcessOrder);
}

public PXFilter<DetailsTable> DetailsView;

Serializable]
public class DetailsTable : IBqlTable
{

}

/// <summary>
/// Processing Method to Assign Owner to Logged-in User
/// </summary>
private static void ProcessOrder(SOOrder order)
{
var graph = PXGraph.CreateInstance<SOOrderEntry>();

// Select the order
graph.Document.Current = graph.Document.Search<SOOrder.orderNbr>(order.OrderNbr, order.OrderType);

if (graph.Document.Current != null)
{
int? currentUserContactID = PXAccess.GetContactID();
if (currentUserContactID != null)
{
graph.Document.Cache.SetValueExt<SOOrder.ownerID>(graph.Document.Current, currentUserContactID);
graph.Document.Cache.MarkUpdated(graph.Document.Current);

// Log the new OwnerID for verification
PXTrace.WriteInformation($"Setting OwnerID to {currentUserContactID} for Order {order.OrderNbr}");

// Save the changes
graph.Actions.PressSave();

// Create a shipment for the order

bool shipmentCreated = CreateShipmentFromButton(graph);

// Confirm the shipmnent is created before pressing the new button

if (shipmentCreated)
{
// Retrieve the Shipment Number
var shipmentNbr = GetShipmentNumber(order);

if (!string.IsNullOrEmpty(shipmentNbr))
{
// Load shipment graph and print the shipment confirmation
var shipmentGraph = PXGraph.CreateInstance<SOShipmentEntry>();
var shipment = shipmentGraph.Document.Search<SOShipment.shipmentNbr>(shipmentNbr);

if (shipment != null)
{
bool printedShipmentConfirmation = PrintShipmentConfirmation(shipmentGraph, shipmentNbr);

if (printedShipmentConfirmation)
{
PXProcessing<SOOrder>.SetInfo($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID} and shipment {shipmentNbr} printed.");
}
else
{
PXProcessing<SOOrder>.SetInfo($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID} and shipment {shipmentNbr} created but not printed.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID}, but shipment could not be retrieved to print.");
}
}
else
{
PXProcessing<SOOrder>.SetWarning($"Shipment created, but no shipment number found for Order {order.OrderNbr}.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID}, but shipment could not be created.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Failed to assign OwnerID: No ContactID found for current user.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} not found.");
}
}


private static Guid GetPrinterIdByName(string printerName, PXGraph printGraph)
{
// Query the SMPrinter table for a printer with the specified printerName
var printer = PXSelect<SMPrinter,
Where<SMPrinter.printerName, Equal<Required<SMPrinter.printerName>>>>.Select(printGraph, printerName);

if (printer != null && printer.Count > 0)
{
SMPrinter smPrinter = printere0];

if (smPrinter.PrinterID.HasValue)
{
return smPrinter.PrinterID.Value; // Return the PrinterID as a non-nullable Guid
}
else
{
// Handle the case where PrinterID is null
throw new Exception($"Printer '{printerName}' has a null PrinterID.");
}
}

// Handle the case where the printer wasn't found
throw new Exception($"Printer '{printerName}' not found.");
}

private static bool PrintShipmentConfirmation(SOShipmentEntry shipmentGraph, string shipmentNbr)
{
bool success = false;

if (string.IsNullOrEmpty(shipmentNbr))
{
throw new PXException("Shipment Number is required for printing.");
}

try
{
const string reportID = "SO642000";
const string description = "Shipment Confirmation";

var parametersDictionary = new Dictionary<string, string>
{
{ "ShipmentNbr", shipmentNbr },
// Add other parameters if necessary
};

PXGraph printGraph = PXGraph.CreateInstance<SMPrintJobMaint>();
// Step 2: Define the print settings
PrintSettings printSettings = new PrintSettings()
{
PrinterID = GetPrinterIdByName("W2PDFHUB", printGraph), // Replace with logic to get the printer ID from field on processing screen
NumberOfCopies = 1,
PrintWithDeviceHub = true,
DefinePrinterManually = true
};

// Step 3: Create the print job
PXGraph.CreateInstance<SMPrintJobMaint>().CreatePrintJob(printSettings, reportID, parametersDictionary, "Shipment Confirmation", CancellationToken.None);

// Log or handle any post-print actions
PXTrace.WriteInformation("Shipment Confirmation print job initiated.");

}
catch (Exception ex)
{
PXTrace.WriteError($"Failed to print Shipment Confirmation for {shipmentNbr}. Error: {ex.Message}");
throw new PXException($"Failed to print Shipment Confirmation for {shipmentNbr}. Please check the printer configuration.");
}
finally
{
success = true;
}
return success;
}

/// <summary>
/// Retrieves the Shipment Number associated with the order.
/// </summary>
private static string GetShipmentNumber(SOOrder order)
{
var shipment = PXSelect<SOOrderShipment,
Where<SOOrderShipment.orderType, Equal<Required<SOOrderShipment.orderType>>,
And<SOOrderShipment.orderNbr, Equal<Required<SOOrderShipment.orderNbr>>>>>
.SelectWindowed(new PXGraph(), 0, 1, order.OrderType, order.OrderNbr);

return shipment != null ? ((SOOrderShipment)shipment).ShipmentNbr : null;
}

private static bool CreateShipmentFromButton(SOOrderEntry graph)
{

// Trigger the "Create Shipment" action on the graph (simulate button click)
PXAction<SOOrder> createShipmentAction = graph.Actionsn"CreateShipment"] as PXAction<SOOrder>;
if (createShipmentAction != null)
{
// If the button exists, press it programmatically
PXTrace.WriteInformation($"Pressing button for create shipment");

createShipmentActionPress(graph);

return true;
}
else
{
PXTrace.WriteError("Create Shipment action not found.");
}
return false;

}

private static void createShipmentActionPress(SOOrderEntry graph)
{
try
{
PXAction<SOOrder> createShipmentAction = graph.Actionsn"CreateShipment"] as PXAction<SOOrder>;
createShipmentAction?.Press();
}
catch (Exception ex)
{
PXTrace.WriteError("Error pressing Create Shipment button: " + ex.Message);
}
}

}
}

I’m now trying to get a field in the top of the processing screen that lists all printers on the devicehub and allows the user to pick one to print to when processing the Orders.

Any help or advice from anyone on how to do that would be gratefully received,

Phil


Reply