Skip to main content
Answer

In a new order processing screen how can I only include orders where the customer has ordered with a credit card before?

  • January 2, 2025
  • 4 replies
  • 79 views

Forum|alt.badge.img+1

I am trying to create a new processing screen which only shows sales orders with specific criteria.

I have the following at the moment which works and allows me to process sales orders to assign the current user as owner. This is the start of a more complex process but I just need to get the basics working currently:

 

using System;
using PX.Data;
using PX.Objects.SO;
using PX.Data.BQL.Fluent;
using PX.TM;

namespace PPCustomOrderProcess
{

public class AIProcessOrdersCust : PXGraph<AIProcessOrdersCust>
{

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

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

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

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

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

public PXCancel<SOOrder> Cancel;

public PXProcessing<SOOrder,
Where<SOOrder.orderType, Equal<wOOrderType>,
And<
Where<
SOOrder.paymentMethodID, Equal<paymentMethodAFFIRM>,
Or<SOOrder.paymentMethodID, Equal<paymentMethodPAYPAL>,
Or<SOOrder.paymentMethodID, Equal<paymentMethodAFTERPAY>,
Or<SOOrder.paymentMethodID, Equal<paymentMethodCCARD>
>
>
>
>
>
>
> AISOOrder;

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

AISOOrder.SetProcessDelegate(ProcessOrder);
}

public PXFilter<DetailsTable> DetailsView;

[Serializable]
public class DetailsTable : IBqlTable
{

}

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();

PXProcessing<SOOrder>.SetInfo($"Order {order.OrderNbr} successfully assigned to user with ContactID: {currentUserContactID}");
}
else
{
PXProcessing<SOOrder>.SetError($"Failed to assign OwnerID: No ContactID found for current user.");
}
}
else
{
PXProcessing<SOOrder>.SetError($"Order {order.OrderNbr} not found.");
}
}
}
}

If the paymentMethodID = CCARD I only want to include records where the Customer has 1 or more sales orders with CCARD as PaymentMethodID and order status is completed.

 

I have been trying various methods but haven’t worked out how to structure the query to achieve that result.

 

If anyone is able to advise I would really appreciate it.

 

Thanks,

 

Phil

Best answer by ppowell

@darylbowman Thanks for all your help.  After a bit of messing around I came up with the following:

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) { }
}

// 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;

It’s probably not the best way but it works and gives me a basis to start on the other aspects of this process.

 

Really appreciate your help,

 

Phil

 

4 replies

darylbowman
Captain II
Forum|alt.badge.img+15

Like this?

using PX.Data.BQL.Fluent;
---

public SelectFrom<SOOrder>.
Where<SOOrder.orderType.IsEqual<wOOrderType>.
And<SOOrder.paymentMethodID.IsEqual<>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodAFFIRM>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodPAYPAL>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodAFTERPAY>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>.
And<SOOrder.status.IsEqual<SOOrderStatus.completed>>
>
>
>.ProcessingView AISOOrder;

 


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • January 3, 2025

@darylbowman : That gets me part of the way there.  The bit I’m not sure how to do is to check for previous orders with the same customer id and ccard as the payment method.  I only want to show sales orders with payment method CCARD if the customer has at least one previous completed order with CCARD as the payment method. I think I need to do an innerjoin or a seperate selectfrom with customerid = current customer id but I just can’t get the right syntax.

 

I tried the following which didn’t validate: 

public PXProcessing<SOOrder,
Where<SOOrder.orderType, Equal<wOOrderType>,
And<
Where<
SOOrder.paymentMethodID, Equal<paymentMethodAFFIRM>,
Or<SOOrder.paymentMethodID, Equal<paymentMethodPAYPAL>,
Or<SOOrder.paymentMethodID, Equal<paymentMethodAFTERPAY>,
Or<
SOOrder.paymentMethodID, Equal<paymentMethodCCARD>,
And<
InnerJoin<SOOrder, On<SOOrder.customerID, Equal<SOOrder.customerID.FromCurrent>,
And<SOOrder.paymentMethodID, Equal<paymentMethodCCARD>,
And<SOOrder.status, Equal<SOOrderStatus.completed>>>>>
>>>>>>>
> AISOOrder;

Thanks for answering,

 

Phil


darylbowman
Captain II
Forum|alt.badge.img+15

I think maybe you could do something like this:

  1. Create a new DAC projection of SOOrder (SOOrderPrev) so that you can join it to SOOrder
  2. Left Join it to SOOrder and check to make sure it isn’t null in the situation you require
public SelectFrom<SOOrder>.
LeftJoin<SOOrderPrev>.
On<SOOrder.customerID.IsEqual<SOOrderPrev.customerID>.
And<SOOrder.paymentMethodID.IsEqual<SOOrderPrev.paymentMethodID>>>.
Where<SOOrder.orderType.IsEqual<wOOrderType>.
And<SOOrder.paymentMethodID.IsEqual<paymentMethodAFFIRM>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodPAYPAL>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodAFTERPAY>>.
Or<SOOrder.paymentMethodID.IsEqual<paymentMethodCCARD>.
And<SOOrderPrev.orderNbr.IsNotNull>
>
>
>.ProcessingView AISOOrder;

Here’s my definition for SOOrderPrev:

using PX.Data;
using PX.Data.BQL;
using PX.Data.BQL.Fluent;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.Objects.AR;
using PX.Objects.CA;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.SO;
using AR = PX.Objects.AR;
using CRLocation = PX.Objects.CR.Standalone.Location;
//------------------------------------------------------------

[PXProjection(typeof(SelectFrom<SOOrder>.
Where<SOOrder.status.IsEqual<SOOrderStatus.completed>>))]
public class SOOrderPrev : PXBqlTable, IBqlTable
{
#region OrderType
[PXDBString(2, IsKey = true, IsFixed = true, InputMask = ">aa")]
[PXDefault(SOOrderTypeConstants.SalesOrder, typeof(SOSetup.defaultOrderType))]
[PXSelector(typeof(Search2<SOOrderType.orderType,
InnerJoin<SOOrderTypeOperation, On2<SOOrderTypeOperation.FK.OrderType, And<SOOrderTypeOperation.operation, Equal<SOOrderType.defaultOperation>>>>,
Where<FeatureInstalled<PX.Objects.CS.FeaturesSet.inventory>.Or<SOOrderType.behavior.IsNotEqual<SOBehavior.bL>>>>))]
[PXRestrictor(typeof(Where<SOOrderTypeOperation.iNDocType, NotEqual<INTranType.transfer>, Or<FeatureInstalled<PX.Objects.CS.FeaturesSet.warehouse>>>), ErrorMessages.ElementDoesntExist, typeof(SOOrderType.orderType))]
[PXRestrictor(typeof(Where<SOOrderType.requireAllocation, NotEqual<True>, Or<AllocationAllowed>>), ErrorMessages.ElementDoesntExist, typeof(SOOrderType.orderType))]
[PXRestrictor(typeof(Where<SOOrderType.active, Equal<True>>), null)]
[PXUIField(DisplayName = "Order Type", Visibility = PXUIVisibility.SelectorVisible)]
[PX.Data.EP.PXFieldDescription]
public virtual string OrderType { get; set; }
public abstract class orderType : PX.Data.BQL.BqlString.Field<orderType> { }
#endregion
#region OrderNbr
[PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
[PXDefault()]
[PXUIField(DisplayName = "Order Nbr.", Visibility = PXUIVisibility.SelectorVisible)]
[SO.RefNbr(typeof(Search2<SOOrder.orderNbr,
LeftJoinSingleTable<Customer, On<SOOrder.customerID, Equal<Customer.bAccountID>,
And<Where<Match<Customer, Current<AccessInfo.userName>>>>>>,
Where<SOOrder.orderType, Equal<Optional<SOOrder.orderType>>,
And<Where<Customer.bAccountID, IsNotNull,
Or<Exists<Select<SOOrderType,
Where<SOOrderType.orderType, Equal<SOOrder.orderType>,
And<SOOrderType.aRDocType, Equal<ARDocType.noUpdate>,
And<SOOrderType.behavior, In3<SOBehavior.sO, SOBehavior.tR>>>>>>>>>>,
OrderBy<Desc<SOOrder.orderNbr>>>), Filterable = true)]
[SO.Numbering()]
[PX.Data.EP.PXFieldDescription]
public virtual string OrderNbr { get; set; }
public abstract class orderNbr : PX.Data.BQL.BqlString.Field<orderNbr> { }
#endregion
#region CustomerID
[PXDefault]
[Customer(
typeof(Search<BAccountR.bAccountID, Where<True, Equal<True>>>), // TODO: remove fake Where after AC-101187
Visibility = PXUIVisibility.SelectorVisible,
DescriptionField = typeof(Customer.acctName),
Filterable = true)]
[PXRestrictor(typeof(Where<Optional<SOOrder.isTransferOrder>, Equal<True>,
Or<Customer.status, IsNull,
Or<Customer.status, Equal<CustomerStatus.active>,
Or<Customer.status, Equal<CustomerStatus.oneTime>,
Or<Customer.status, Equal<CustomerStatus.creditHold>>>>>>),
AR.Messages.CustomerIsInStatus,
typeof(Customer.status))]
[PXForeignReference(typeof(Field<SOOrder.customerID>.IsRelatedTo<BAccount.bAccountID>))]
public virtual int? CustomerID { get; set; }
public abstract class customerID : PX.Data.BQL.BqlInt.Field<customerID> { }
#endregion
#region CustomerLocationID
[LocationActive(typeof(Where<Location.bAccountID, Equal<Current<SOOrder.customerID>>,
And<MatchWithBranch<Location.cBranchID>>>), DescriptionField = typeof(Location.descr), Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault(typeof(Coalesce<Search2<BAccountR.defLocationID,
InnerJoin<CRLocation, On<CRLocation.bAccountID, Equal<BAccountR.bAccountID>, And<CRLocation.locationID, Equal<BAccountR.defLocationID>>>>,
Where<BAccountR.bAccountID, Equal<Current<SOOrder.customerID>>,
And<CRLocation.isActive, Equal<True>,
And<MatchWithBranch<CRLocation.cBranchID>>>>>,
Search<CRLocation.locationID,
Where<CRLocation.bAccountID, Equal<Current<SOOrder.customerID>>,
And<CRLocation.isActive, Equal<True>, And<MatchWithBranch<CRLocation.cBranchID>>>>>>))]
[PXForeignReference(
typeof(CompositeKey<
Field<SOOrder.customerID>.IsRelatedTo<Location.bAccountID>,
Field<SOOrder.customerLocationID>.IsRelatedTo<Location.locationID>
>))]
public virtual int? CustomerLocationID { get; set; }
public abstract class customerLocationID : PX.Data.BQL.BqlInt.Field<customerLocationID> { }
#endregion
#region PaymentMethodID
[PXDBString(10, IsUnicode = true)]
[PXDefault(typeof(Coalesce<Search2<CustomerPaymentMethod.paymentMethodID, InnerJoin<Customer, On<CustomerPaymentMethod.bAccountID, Equal<Customer.bAccountID>>>,
Where<Customer.bAccountID, Equal<Current<SOOrder.customerID>>,
And<CustomerPaymentMethod.pMInstanceID, Equal<Customer.defPMInstanceID>>>>,
Search<Customer.defPaymentMethodID,
Where<Customer.bAccountID, Equal<Current<SOOrder.customerID>>>>>), PersistingCheck = PXPersistingCheck.Nothing)]
[PXSelector(typeof(Search<PaymentMethod.paymentMethodID,
Where<PaymentMethod.isActive, Equal<boolTrue>,
And<PaymentMethod.useForAR, Equal<boolTrue>>>>), DescriptionField = typeof(PaymentMethod.descr))]
[PXUIFieldAttribute(DisplayName = "Payment Method")]
public virtual string PaymentMethodID { get; set; }
public abstract class paymentMethodID : PX.Data.BQL.BqlString.Field<paymentMethodID> { }
#endregion
}

 


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • Answer
  • January 6, 2025

@darylbowman Thanks for all your help.  After a bit of messing around I came up with the following:

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) { }
}

// 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;

It’s probably not the best way but it works and gives me a basis to start on the other aspects of this process.

 

Really appreciate your help,

 

Phil