Why is order ID not assigned on "Ticket Closing"

I have a rule that I need to run on each order when a ticket gets paid (the rule assigns employee commission per item).

The rule is run like this…

  • A ticket gets paid
  • A “Ticket Closing” rule adds a state to every order (when remaining amount = 0)
  • A “Order State Changed” rule goes through each order since they all had their states updated.

I have been missing some items, because sometimes they don’t have an Order ID assigned and the point the “Ticket Closing” event happens. But I can’t figure out a logical reason for this…

Example 1)

  • Create a ticket
  • Add an Apple
  • Fully pay the ticket
  • The apple order has an Order ID*

Example 2)

  • Create a ticket
  • Add an Apple
  • Close the ticket
  • Reopen the ticket
  • Fully pay the ticket
  • The apple order has an Order ID*

Example 3)

  • Create a ticket
  • Add an Apple
  • Close the ticket
  • Reopen the ticket
  • Add an Orange
  • Fully pay the ticket
  • The apple order has an Order ID*
  • The orange order does not yet have an Order ID*

*I am referring to the existance of the Order ID at the point at which the “Ticket Closing” event occurs

So why could this be happening?

I could run this correctly (I think) on Ticket State=Paid, but by this point the ticket has been closed/locked in the DB and I am not longer able to alter the states (I like using my ule to also alter the states once the commission has been assigned to the employee, so ideally I need to do all of this before the order is completely closed)

My question to you is: How do you know the Order has no Id ? How are you checking for that?

AFAIK, Order Ids (and initial Ticket Ids) not not generated until they are going to be committed to the DB. This happens on Ticket Closed Event, not Ticket Closing Event.

So if you are trying to create a flow where you need reference to the Order before the Id is generated, do not use {ORDER ID} … use {ORDER UID} instead.

The {ORDER UID} is generated on-the-fly in MEMORY when the Order is added to the Ticket. Similarly, the {TICKET UID} is generated upon Ticket Created.

1 Like

After Add Orange did you close ticket. You may want to use Save ticket if you don’t want to close it. I think Orange don’t have ID until ticket close/save.

1 Like

In the Order State Updated rule, for testing purposes I have a ShowMessage action which shows the name of the item and the {ORDER ID}. This is how I know the results of the 3 scenarios I listed above.

As part of the commission calculation I am using a {REPORT ORDER DETAILS} which includes an :O.Id={ORDER ID}, so I think I need the Order ID and not the UID???

No - After adding the Orange I immediately paid the ticket. I will look in to the option of triggering a “Save Ticket”, but doesn’t it seem rather strange that when a ticket is new and gets a new order then paid immediately the order gets a number before “Ticket Closing”, but when a new order is added to a “re-opened” ticket the order doesn’t get a number until after “Ticket Closing” - I don’t understand the logic there, it seems inconsitent??

It depend on your rule when exactly it trigger.

Add new Order
Click Settle
No settle and click close
Come back to order screen
You will see order still new.

Yes, but in example 1 and 3 the item is new and the ticket gets fully paid.
Only in example 1 the new items get an Order ID at “Ticket Closing”

Can you just show the rule?

Rule 1 - Add a state to all items when the ticket gets paid

Rule 2 - Process each indiviual order, since they will all have had their states changed

In the above example you can see I have added a “Save Ticket” actions. I have only just done this since starting this thread but this causes SambaPOS to crash…

-----------------------------
[General Info]

Application: SambaPOS
Version:     5.2.2
Region:      en
DB:          SQ
Machine:     TH1-SVR-01
User:        Administrator
Date:        24/07/2017
Time:        20:58

User Explanation:

Administrator said ""
-----------------------------

[Exception Info 1]

Top-level Exception
Type:        System.Reflection.TargetInvocationException
Message:     Exception has been thrown by the target of an invocation.
Source:      mscorlib
Stack Trace: at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Inner Exception 1
Type:        System.NullReferenceException
Message:     Object reference not set to an instance of an object.
Source:      EntityFramework
Stack Trace: at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.SynchronizeContexts(RelatedEnd targetRelatedEnd, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)
   at System.Data.Entity.Core.Objects.ObjectStateManager.PerformAdd(IEntityWrapper wrappedOwner, RelatedEnd relatedEnd, IEntityWrapper entityToAdd, Boolean isForeignKeyChange)
   at System.Data.Entity.Core.Objects.ObjectStateManager.PerformAdd(IList`1 entries)
   at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()
   at System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()
   at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
   at System.Data.Entity.Infrastructure.DbChangeTracker.HasChanges()
   at Samba.Infrastructure.Data.SqlData.EFWorkspace.HasChanges()
   at Samba.Persistance.Data.CachedDao.CacheSave[T](T entity)
   at Samba.Persistance.Data.Dao.Save[T](T entity)
   at Samba.Persistance.Implementations.TicketDao.Save(Ticket ticket)
   at Samba.Services.Implementations.TicketModule.TicketServiceBase.SubmitTicket(Ticket ticket, TicketType ticketType, AppState appState) in C:\Users\emree\Documents\Github\SambaPOSPro\Samba.Services\Implementations\TicketModule\TicketServiceBase.cs:line 515
   at Samba.Services.Implementations.TicketModule.TicketServiceBase.CloseTicket(Ticket ticket, AppState appState) in C:\Users\emree\Documents\Github\SambaPOSPro\Samba.Services\Implementations\TicketModule\TicketServiceBase.cs:line 533
   at Samba.Presentation.Services.Implementations.TicketModule.TicketService.CloseTicket(Ticket ticket)
   at Samba.Presentation.ClientLibrary.Modules.PosModule.PosViewModel.CloseTicket() in C:\Users\emree\Documents\Github\SambaPOSPro\Samba.Presentation.ClientLibrary\Modules\PosModule\PosViewModel.cs:line 665
   at Samba.Presentation.ClientLibrary.Modules.PosModule.PosViewModel.OnTicketEvent(EventParameters`1 obj) in C:\Users\emree\Documents\Github\SambaPOSPro\Samba.Presentation.ClientLibrary\Modules\PosModule\PosViewModel.cs:line 495
   at Microsoft.Practices.Prism.Events.EventSubscription`1.InvokeAction(Action`1 action, TPayload argument)
   at Microsoft.Practices.Prism.Events.EventSubscription`1.<>c__DisplayClass2.<GetExecutionStrategy>b__0(Object[] arguments)
   at Microsoft.Practices.Prism.Events.EventBase.InternalPublish(Object[] arguments)
   at Microsoft.Practices.Prism.Events.CompositePresentationEvent`1.Publish(TPayload payload)
   at Samba.Presentation.Services.Common.ExtensionMethods.Publish[TEventsubject](TEventsubject eventArgs, String eventTopic, Action expectedAction)

-----------------------------

[Assembly Info]

mscorlib, Version=4.0.0.0
Samba.Services, Version=1.0.0.0
Samba.Domain, Version=1.0.0.0
Samba.Infrastructure.Data, Version=1.0.0.0
System.ComponentModel.Composition, Version=4.0.0.0
Samba.Presentation.Services, Version=1.0.0.0
System.Core, Version=4.0.0.0
PresentationCore, Version=4.0.0.0
DevExpress.Xpf.LayoutControl.v14.1, Version=14.1.13.0
System.Xml, Version=4.0.0.0
DevExpress.Xpf.Grid.v14.1, Version=14.1.13.0
System, Version=4.0.0.0
DevExpress.Xpf.Grid.v14.1.Core, Version=14.1.13.0
WindowsBase, Version=4.0.0.0
System.Xaml, Version=4.0.0.0
PresentationFramework, Version=4.0.0.0
Samba.Infrastructure, Version=1.0.0.0
Microsoft.Practices.Prism, Version=4.0.0.0
System.Runtime.Serialization, Version=4.0.0.0
Microsoft.Practices.Prism.MefExtensions, Version=4.0.0.0
DevExpress.Xpf.Core.v14.1, Version=14.1.13.0
System.Windows.Forms, Version=4.0.0.0
System.Drawing, Version=4.0.0.0
Samba.Persistance, Version=1.0.0.0
Stateless, Version=1.0.0.0
PropertyTools, Version=2012.4.14.1
Samba.Localization, Version=1.0.0.0
ReachFramework, Version=4.0.0.0
EntityFramework, Version=6.0.0.0
FluentValidation, Version=3.4.0.0
Microsoft.CSharp, Version=4.0.0.0
Omu.ValueInjecter, Version=2.3.0.0
Microsoft.Practices.ServiceLocation, Version=1.0.0.0

OK I can confirm if ticket state is New Orders it does generate ID when ticket closing but it doesn’t generate ID if ticket state is not New.

I have Select Order Action Order State Submitted in Ticket closing event.
Ticket State New, Add 3 items - > I got number 5,6,7
Ticket State Unpaid Add 1 more item - > I got number 5,6,7,0

But it can SOLVE by Save Ticket.

1 Like

I’m glad I’m not going crazy :slight_smile:

I have been looking at @QMcKay’s suggestion of using the UID.

In my orgiinal rule I used:
{REPORT ORDER DETAILS:T.TicketNumber:O.id={ORDER ID}}

But this cannot simply be changed to:
{REPORT ORDER DETAILS:T.TicketNumber:O.OrderUid={ORDER UID}}

So is there any way I can retrieve this info using the Order UID? (I don’t just need the ticket number, but it serves as an example)

Were you able to get save ticket working? Where did you put it in the flow? For me, it crashed SambaPOS.

@sukasem, your confirmation regarding Ticket State may well be true, however …

I find it extremely hard to believe there is any hard-coding inside SambaPOS that looks for a specific State to decide whether or not to generate an Order Id, or do anything at all for that matter based on a State.

It must be looking at some other internal property like isLocked or isClosed. My guess would be that the flow sequence when Closing from Payment Screen is different than it is with the Close button on the Ticket Screen. That must be the case, but there is likely some reason for that.

To confirm, you would need to open the Rule Debugger and see the order in which the Events are being fired in the 2 different scenarios.

Yes, Settle Rule.

Save Ticket it is just auto close ticket and reopen same ticket I think that why it crash when you put in ticket closing rule.

1 Like

I did it on ticket screen not payment tho.

Maybe emre has if state is new do this else do that. Since when ticket is not new maybe have a lot more things to check then he add generate id last action in ticket closing rule lol.

You won’t be able to access Order UID from a Report Tag. They don’t support it.

What are you trying to do with the Order, and/or Ticket that you chose the Report?

Interesting. I still refuse to believe this is directly related to a specific State. I mean, we can change the States to “fluffy” and “doofy” and the behavior will remain the same. So it must have to do with other Rule processing flow.

But actually, it doesn’t really depend on state I guess. When adding order to Unpaid it will change to New Orders anyway.

I think it is when ticket is first open there is no ticket idNo. So, it generate ticket idNo and result generate order id as well. Maybe this make more sense.

I too am closing the ticket before going to the settle screen. Maybe a customer comes in and quickly orders and apple but then wants time to browse before coming back to buy the apple and the new orange they have found in my store. In the mean-time I closed the ticket for this customer because another customer came in and I needed to serve them.

My commissions are earned on the item level, since different people might have sold each item sold to the customer. I need access to the order details because to calculate the commission I need to know the item price and details of any order tags applied which might affect the commission due.

Open, Add item, Settle:

Re-Open, Add new item, Settle:

More details:

You can see tha tthe Order number is not available in the Show Message

Yeah - That could be a sensible explanation… I think it is a little inconsistant though and for me I think it probably should be changed/fixed.

In the mean time, @sukasem’s suggestion of adding a “Save Ticket” action to the “Settle” rule seems to be working, but there is a notiable delay before moving forward to the Payment Screen and it seems that this action really shouldn’t have to be there.

Yes, if you have a lot of things doing at ticket closing as I said that before Save Ticket does close ticket and re open.

What you can do is move rule to Ticket closed or delay execute 0.1 sec but you may need to store Ticket ID and Load Ticket and do your thing there.

Maybe Delay Execute Automation Command better you can pass Ticket ID as command value.

Another problem with the save before settle It’s kind of annoying in our workflow to have the ticket saved when we go to the settle screen - Sometimes we chuck a few items in a ticket, head over to the settle screen so we can quickly see how much the total would be in foreign currencies and sometimes we just cancel all items out without ever actually creating a ticket (kind of like a quotation).

I would prefer to “do my thing” before the ticket is closed because then I can still ‘fiddle’ with the individual order states and record the commission that was assign to employees. If I wait until Ticket Closed I can’t actually still alter the order states.

I believe you can use reopen close ticket and change order state and mark as closed again.