GQL closeTerminalTicket() BUG causes subsequent Merge Tickets failure with Tickets that have partial Payments made by Entities that were changed

@emre, this is an issue for v5.2.3 and might be present on earlier versions as well.

:warning: EDIT:: investigation reveals issue is with closeTerminalTicket() mutation, not mergeTickets() mutation. See Post #6 in this thread.


Execution of this mutation generally works:

mutation m {
ticketId:mergeTickets
  (
	 terminal:"QMXterminal"
	,department:"Restaurant"
	,ticketType:"Ticket"
	,user:"Q"
	,ticketIds:[42595,42596]
	)
}

However, when attempting to Merge Tickets where 1 or more Tickets have partial Payments already processed, the mutation fails with the following error:

!!! BAD REQUEST !!! [400] Bad Request [400].{
  "data": {
    "ticketId": null
  },
  "errors": [
    {
      "ClassName": "GraphQL.ExecutionError",
      "Message": "Error trying to resolve mergeTickets.",
      "Data": null,
      "InnerException": {
        "ClassName": "System.NullReferenceException",
        "Message": "Object reference not set to an instance of an object.",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Samba.Domain.Models.Tickets.Ticket.RemovePayment(Payment py)\r\n   at System.Collections.Generic.List`1.ForEach(Action`1 action)\r\n   at Samba.Domain.Models.Tickets.Ticket.RemoveData()\r\n   at Samba.Services.Implementations.TicketModule.TicketServiceBase.<>c.<MergeTickets>b__51_14(Ticket x) in C:\\Users\\vehbi\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Implementations\\TicketModule\\TicketServiceBase.cs:line 726\r\n   at System.Collections.Generic.List`1.ForEach(Action`1 action)\r\n   at Samba.Services.Implementations.TicketModule.TicketServiceBase.MergeTickets(IEnumerable`1 ticketIds, AppState appState) in C:\\Users\\vehbi\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Implementations\\TicketModule\\TicketServiceBase.cs:line 726\r\n   at Samba.Services.Graphql.Tickets.TicketMutation.MergeTickets(ResolveFieldContext arg) in C:\\Users\\vehbi\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Graphql\\Tickets\\TicketMutation.cs:line 556\r\n   at GraphQL.DocumentExecuter.<ResolveFieldAsync>d__8.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nRemovePayment\nSamba.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\nSamba.Domain.Models.Tickets.Ticket\nVoid RemovePayment(Samba.Domain.Models.Tickets.Payment)",
        "HResult": -2147467261,
        "Source": "Samba.Domain",
        "WatsonBuckets": null
      },
      "HelpURL": null,
      "StackTraceString": null,
      "RemoteStackTraceString": null,
      "RemoteStackIndex": 0,
      "ExceptionMethod": null,
      "HResult": -2146233088,
      "Source": null,
      "WatsonBuckets": null
    }
  ]
}
1 Like

I will add just to clarify that yes you can successfully merge tickets with partial payments inside SambaPOS so this mutation should be able to work.

1 Like

Further investigation reveals that certain GQL operations cause errors in the SambaPOS GUI as well.

Trying to Merge the same 2 Tickets via the SambaPOS 5.2.3 GUI where at least 1 of the Tickets contains a partial Payment causes the same error in SambaPOS …

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

Application: SambaPOS
Version:     5.2.3
Region:      en
DB:          SQ
Machine:     QBOOK
User:        Quentin
Date:        2018-01-21
Time:        17:29

User Explanation:

Quentin said "Merging Tickets where at least 1 of the Tickets has partial Payment(s)."
-----------------------------

[Exception Info 1]

Top-level Exception
Type:        System.NullReferenceException
Message:     Object reference not set to an instance of an object.
Source:      Samba.Domain
Stack Trace: at Samba.Domain.Models.Tickets.Ticket.RemovePayment(Payment py)
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at Samba.Domain.Models.Tickets.Ticket.RemoveData()
   at Samba.Services.Implementations.TicketModule.TicketServiceBase.<>c.<MergeTickets>b__51_14(Ticket x) in C:\Users\vehbi\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\TicketModule\TicketServiceBase.cs:line 726
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at Samba.Services.Implementations.TicketModule.TicketServiceBase.MergeTickets(IEnumerable`1 ticketIds, AppState appState) in C:\Users\vehbi\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\TicketModule\TicketServiceBase.cs:line 726
   at Samba.Presentation.Services.Implementations.TicketModule.TicketService.MergeTickets(IEnumerable`1 ticketIds)
   at Samba.Presentation.ClientLibrary.Modules.PosModule.TicketListViewModel.OnMergeTickets(String obj) in C:\Users\vehbi\Source\Repos\sambapos-v5-pro\Samba.Presentation.ClientLibrary\Modules\PosModule\TicketListViewModel.cs:line 97
   at Microsoft.Practices.Prism.Commands.DelegateCommand`1.<>c__DisplayClass6.<.ctor>b__2(Object o)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.Execute(Object parameter)
   at Microsoft.Practices.Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.Execute(Object parameter)
   at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   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)

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

[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.v16.2, Version=16.2.6.0
System.Xml, Version=4.0.0.0
DevExpress.Xpf.Grid.v16.2, Version=16.2.6.0
System, Version=4.0.0.0
DevExpress.Xpf.Grid.v16.2.Core, Version=16.2.6.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.v16.2, Version=16.2.6.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
DevExpress.Data.v16.2, Version=16.2.6.0
WindowsInput, Version=1.0.4.0

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

[System Info]

Operating System
-Microsoft Windows 10 Home
--CodeSet = 1252
--CSDVersion = 
--CurrentTimeZone = -360
--FreePhysicalMemory = 2375332
--OSArchitecture = 64-bit
--OSLanguage = 1033
--ServicePackMajorVersion = 0
--ServicePackMinorVersion = 0
--Version = 10.0.15063

Machine
-QBOOK
--Manufacturer = HP
--Model = HP Spectre x360 Convertible     
--TotalPhysicalMemory = 8496979968
--UserName = QBOOK\Quentin

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

… deleted to avoid confusion because content was irrelevant …

1 Like

These are the Payments made on Ticket #108

NOTE: Customer Entity “James” is no longer assigned to the Ticket; that Entity was changed to “Chas”.

@Tayfun, please report this major issue regarding the GraphQL Engine to the appropriate parties…

This issue is caused by GraphQL payTerminalTicket() mutation.

That mutation fails to update [Payments] table columns [AccountTransaction_Id] and [AccountTransaction_AccountTransactionDocumentId] when done via GQL. SambaPOS updates these columns properly.

:warning: EDIT: wow, that ^ too is incorrect. The payTerminalTicket() mutation DOES update the [Payments] table properly.

It is the changeEntityOfTerminalTicket() mutation that is causing the issue. When that mutation is executed, it is NULLing the columns mentioned in the [Payments] table, for previous Entity Accounts. SambaPOS does NOT NULL them when the Entity is changed and the Ticket is Closed.

:warning: EDIT2: I need to clarify this 1 step further. It isn’t actually changeEntityOfTerminalTicket() mutation directly. That mutation is executed, and the [Payments] table remains intact ok. But when the Ticket is closed with closeTerminalTicket() then the Entity change is actually applied, and at that time, the [Payments] table has the mentioned columns NULLed, even if the Entity was changed in SambaPOS and not through GQL.

Changing Entity through SambaPOS and closing the Ticket works ok. But if we open that same Ticket using GQL loadTerminalTicket(), then even immediately close it with closeTerminalTicket(), it is at that time that the [Payments] table goes “bad”.

The following works without issue in SambaPOS, but does not work properly when Payments are made by Entity Account, with a subsequent changeEntityOfTerminalTicket() mutation.

Steps to reproduce:

  • create Ticket

  • select Customer Entity “James”

  • add Orders

  • make partial Payment using Customer Account “James”

  • close Ticket

  • open Ticket “James”

  • change Customer Entity “James” to “John”

  • make partial Payment using Customer Account “John”

  • close Ticket

  • create another Ticket

  • add Orders

  • select Customer Entity “John”

  • make partial Payment using Customer Account “John”

  • close Ticket

  • select Entity John (shows a list of John’s Tickets (2))

  • attempt to Merge Tickets

Create Ticket “James” and make partial “James” Account Payment

Change Ticket “James” to “John” and make partial “John” Account Payment

Create NEW Ticket “John” and Close Ticket

Select Entity “John” and attempt to Merge 2 Tickets


[Payments] table

Notice the [Payments] table, where records in Green were executed via SambaPOS and records in Red were executed via GraphQL, and then the changeEntityOfTerminalTicket() mutation is executed followed by closeTerminalTicket() mutation… this is why the Cancel/Remove Payments process fails, due to the NULLs in columns [AccountTransaction_Id] and [AccountTransaction_AccountTransactionDocumentId]

3 Likes

@QMcKay I informed the developers.

2 Likes

Hi!
I’m unsure whether this is the same issue, but when I do

mutation load {loadTerminalTicket(terminalId: "*****", ticketId: "#####" { id } }
mutation pay {payTerminalTicket(terminalId:"*****", paymentTypeName:"Credit Card", amount:###.##){ ticketId} }
mutation close {closeTerminalTicket(terminalId:"*****") }

through GQL I get the following error once I attempt to close the ticket:

{
  "data": {
    "closeTerminalTicket": null
  },
  "errors": [
    {
      "locations": [
        {
          "line": 0,
          "column": 0
        }
      ],
      "message": "Error trying to resolve closeTerminalTicket.",
      "data": {},
      "innerException": {
        "ClassName": "System.NullReferenceException",
        "Message": "Object reference not set to an instance of an object.",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.SynchronizeContexts(RelatedEnd targetRelatedEnd, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)\r\n   at System.Data.Entity.Core.Objects.ObjectStateManager.PerformAdd(IEntityWrapper wrappedOwner, RelatedEnd relatedEnd, IEntityWrapper entityToAdd, Boolean isForeignKeyChange)\r\n   at System.Data.Entity.Core.Objects.ObjectStateManager.PerformAdd(IList`1 entries)\r\n   at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()\r\n   at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)\r\n   at System.Data.Entity.Infrastructure.DbChangeTracker.HasChanges()\r\n   at Samba.Persistance.Data.CachedDao.CacheSave[T](T entity)\r\n   at Samba.Persistance.Data.Dao.Save[T](T entity)\r\n   at Samba.Persistance.Implementations.TicketDao.Save(Ticket ticket)\r\n   at Samba.Services.Implementations.TicketModule.TicketServiceBase.SubmitTicket(Ticket ticket, TicketType ticketType, AppState appState) in C:\\Users\\Vehbi\\Documents\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Implementations\\TicketModule\\TicketServiceBase.cs:line 610\r\n   at Samba.Services.Implementations.TicketModule.TicketServiceBase.CloseTicket(Ticket ticket, AppState appState) in C:\\Users\\Vehbi\\Documents\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Implementations\\TicketModule\\TicketServiceBase.cs:line 628\r\n   at Samba.Services.Graphql.TerminalStateManager.CloseTicket(String terminalId) in C:\\Users\\Vehbi\\Documents\\Source\\Repos\\sambapos-v5-pro\\Samba.Services\\Graphql\\TerminalState.cs:line 204\r\n   at GraphQL.DocumentExecuter.<ResolveFieldAsync>d__8.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nIncludeEntity\nEntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\nSystem.Data.Entity.Core.Objects.DataClasses.RelatedEnd\nVoid IncludeEntity(System.Data.Entity.Core.Objects.Internal.IEntityWrapper, Boolean, Boolean)",
        "HResult": -2147467261,
        "Source": "EntityFramework",
        "WatsonBuckets": null
      },
      "stackTrace": null,
      "helpLink": null,
      "source": null,
      "hResult": -2146233088
    }
  ]
}

Not all tickets do this, only some tickets, and I, so far, am unable to figure out the pattern.
-Once I register a terminal, and execute the above command on multiple tickets, about 3/4 of them get that error.
-On 90% of them I am paying the full amount.
-The tickets that this happens to can not be paid by GQL, even after multiple tries.

Does anyone have any clue as to why?
I am also thinking of just executing payments through SQL, but am unsure of what records need to be added to which tables.
I do know that we need to add to Payments table, but am not very familiar with accounts.

Thanks so much!

Try adding an entity to them first.

All of them have entities as well!

I wonder if it has anything to do with the entity states?

Also what sambapos version ? We have been updating gql extensively to coincide with our own apps which all use gql.

Version is: 5.3.7390.41561

Err, I guess I was looking at the file version.

The Samba Title Bar says App:5.3.0

1 Like

Ok so your on an older version. Currently we are on 5.3.6 with 5.3.7 in beta.

By the time we release 5.3.8 there will be many updates to gql.

Yes! I got home, and tested it on 5.3.6 and no issues! Thanks as always Jesse!

1 Like