Sage / SData-2.0

Contains documents pertaining to the SData 2.0 developments
33 stars 10 forks source link

Sage 50 Accounts - Contacts are not being deleted #6

Closed geoffo closed 4 months ago

geoffo commented 9 years ago

I am attempting to perform a DELETE operation on a Contact. The delete call itself returns a 200 OK response, however the contact that was to be deleted is still showing in the UI and can be retrieved via a GET call. So essentially the contact is not being deleted.

Below are my request/response logs for reference. Are there any problems with my request? If not, are there any other reasons as to why contacts are not being deleted?

DELETE http://localhost:5493/sdata/accounts50/GCRM/-/contacts(96df2e1e-72c6-4b52-b39a-eeb42c840f87) HTTP/1.1 Host: localhost:5493 Content-Length: 2 Authorization: Basic ****

HTTP/1.1 200 OK Server: Sage.Common.Web.Server/1.0.0.0 Date: Tue, 07 Apr 2015 20:20:54 GMT Content-Length: 0 Connection: Close

darroncockram commented 9 years ago

What kind of contact are you trying to delete?

Deleting contacts in Accounts is a little bit complicated as, whilst the overall resource kinds is set as canDelete="true", in practical terms it's actually the case that some contacts can be deleted and some cannot.

For example the primary contact and trade contact on a customer/supplier (tradingAccount), invoice, order or project cannot be deleted as they are stored directly on the parent record so the only way to delete the contact for these types is to delete the owning entity itself. On the other hand secondary or delivery contacts on a customer/supplier are stored independently so it should be possible to delete these.

geoffo commented 9 years ago

I am just attempting to delete a Delivery Contact for a customer.

What I am currently doing is running some SData tests on Customer contacts. So I created a contact, updated it, then tried to delete it. The creation and updating worked fine. However deleting the contact just returns a 200 response but remains assigned as a contact for the customer. I should be able to delete this contact right? If not, can you explain what may be happening here when I can delete the contact from the UI without any problem?

In addition to your comments, I did notice in some testing that there are items that cannot be deleted when they are linked to additional resources. For example, I cannot delete a tradingAccount that is tied to additional resources such as salesOrders, invoices, etc. This much I understand. However when I try to delete a tradingAccount with SData in such a circumstance, I receive a 200 OK response which makes me assume that the tradingAccount was deleted. However it actually was not because of the links to additional resources. If I try to delete the tradingAccount in the Sage UI I receive an error stating the record cannot be deleted due to remaining balances, etc. still tied to the account. I would assume that SData would return an error similar to the one that the UI presents so we can identify that the record still exists and was not deleted. Is there anyway to update the responses for this?

Thanks for all your help Darron.

darroncockram commented 9 years ago

However when I try to delete a tradingAccount with SData in such a circumstance, I receive a 200 OK response which makes me assume that the tradingAccount was deleted.

I've just tested this and I get the expected error response 'DELETE operation failed - Cannot delete record as it has associated transactions'. If you capture the details of your delete request and paste it here I can take a look and see if I can spot what is going wrong.

geoffo commented 9 years ago

Sorry for the delay but here are the details of the delete request. I also included a GET request/response (truncated) that I made after the delete to show that the contact still exists. If you need any additional information, please let me know.

DELETE REQUEST

DELETE http://localhost:5493/sdata/accounts50/GCRM/-/contacts('96df2e1e-72c6-4b52-b39a-eeb42c840f87') HTTP/1.1 Host: localhost:5493 Authorization: Basic ***** Accept-Encoding: gzip, deflate Content-Type: application/atom+xml; type=entry Content-Length: 0

DELETE RESPONSE

HTTP/1.1 200 OK Server: Sage.Common.Web.Server/1.0.0.0 Date: Mon, 04 May 2015 13:06:41 GMT Content-Length: 0 Connection: Close

FOLLOWING GET REQUEST

GET http://localhost:5493/sdata/accounts50/GCRM/-/contacts(96df2e1e-72c6-4b52-b39a-eeb42c840f87) HTTP/1.1 Accept-Encoding: gzip, deflate Host: localhost:5493 Authorization: Basic *****

FOLLOWING GET RESPONSE

HTTP/1.1 200 OK Server: Sage.Common.Web.Server/1.0.0.0 Date: Mon, 04 May 2015 13:07:27 GMT Content-Length: 14164 Last-Modified: Tue, 07 Apr 2015 16:23:18 GMT Content-Type: application/atom+xml;type=feed Connection: Close

......... <published>2015-04-07T16:23:18.000-04:00</published> <updated>2015-04-07T16:23:18.000-04:00</updated> <http:httpStatus>200</http:httpStatus> <sdata:payload> <crm:contact sdata:url="http://localhost:5493/sdata/accounts50/GCRM/-/contactCustomerDel(96df2e1e-72c6-4b52-b39a-eeb42c840f87)?format=atomentry" sdata:uuid="96df2e1e-72c6-4b52-b39a-eeb42c840f87"> <crm:contactGroups xsi:nil="true" /> <crm:active>true</crm:active> .............

geoffo commented 9 years ago

I have still not been able to delete a contact (I am seeing the same behavior as shown in previous comments). I tried using the $url value returned in a GET response but I am receiving an error stating "Member not found". However the contact is still showing up in Sage Accounts and can be retrieved via a GET request.

DELETE http://localhost:5493/sdata/accounts50/GCRM/-/contactCustomerDel(96df2e1e-72c6-4b52-b39a-eeb42c840f87) HTTP/1.1

HTTP/1.1 500 Internal Server Error Content-Length: 1483 Content-Type: application/xml Connection: Close

<?xml version="1.0" encoding="utf-8"?>
<diagnosis xmlns="http://schemas.sage.com/sdata/2008/1" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sdatasync="http://schemas.sage.com/sdata/sync/2008/1" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sdata="http://schemas.sage.com/sdata/2008/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:sme="http://schemas.sage.com/sdata/sme/2007" xmlns:http="http://schemas.sage.com/sdata/http/2008/1">
  <sdata:severity>error</sdata:severity>
  <sdata:sdataCode>ApplicationDiagnosis</sdata:sdataCode>
  <sdata:applicationCode />
  <sdata:message>DELETE operation failed - Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))

   at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData&amp; msgData)
   at Sage.Integration.Accounts50.SDOAdapter.ISDORecord.Remove()
   at Sage.Integration.Accounts50.SDOAdapter.SDORequestHandler.OnDeleteRecordRequest(ISDORecord record, IRequest request)
   at Sage.Integration.Accounts50.SDOAdapter.SDORequestHandler.OnDeleteRequest(IRequest request)
   at Sage.Integration.Accounts50.SDOAdapter.RequestHandler`2.DeleteRequest(IRequest request)
   at Sage.Integration.Accounts50.SDOAdapter.SDORequestManager.DeleteRequest(IRequest request) (-1)</sdata:message>
  <sdata:stackTrace />
  <sdata:payloadPath />
</diagnosis>

Do you have any ideas?

malard commented 7 years ago

@darroncockram I just came to this, as you know I've started to play around with sdata and run into the same issue, example:

DELETE /sdata/accounts50/GCRM/-/postalAddresses(a90fd823-b130-40da-b177-bc427e5a7c28)

Returns 200 OK

GET /sdata/accounts50/GCRM/-/postalAddresses(a90fd823-b130-40da-b177-bc427e5a7c28)?format=json

Returns the original data with no changes. I was expecting the "Active" flag to be the "deleted" concept, i.e. would turn false, upon being deleted as obviously the internal references to legacy orders etc will need to be preserved.

According to the specification: http://sage.github.io/SData-2.0/pages/core/1001/ IF the operation succeeds then it should return 200, but the documentation is somewhat vaigue on this point. Because it merely says the operation, not the delete action on the record.

"operation" in a server architecture concept could easily just refer to the transaction, rather than the action. I would suggest some clarification on this page of documentation and to specify that it should return 200 IF the record is successfully deleted.

I also tried a PUT on the record, changing "active" to false, but it seems you cannot change "active" via the PUT action

darroncockram commented 7 years ago

Returns the original data with no changes. I was expecting the "Active" flag to be the "deleted" concept, i.e. would turn false, upon being deleted as obviously the internal references to legacy orders etc will need to be preserved.

Active and deleted are two different concepts but can be fairly closely aligned depending on the specific implementation. Active in the case of Sage 50 Accounts is any non-deleted record but Accounts has no concept of a soft delete so this means that you will never see a non-active record returned by the Sage 50 Accounts Sdata adapter and why the PUT operation makes no difference to the field.

Deletion of postal address records in in Accounts can be a little esoteric as only addresses that are not directly part of another entity can actually be deleted. In practice this means that it's pretty much only contact and delivery addresses (both of which are Accounts 50 concepts rather than GCRM or Sdata concepts) for customers or suppliers (again Accounts 50 only concepts) can actually be deleted. Processing a DELETE via the sData feeds against one of these records will result in it actually being removed from the underlying data. For any other address the parent entity would have to be deleted to delete the address as they are intrinsically linked.

This is really just an internal complexity of how Sage 50 Accounts works that the Sdata provider is abstracting away. It provides a consistent response for the DELETE operations as there is no way for a consumer to discover which records can or cannot be deleted. Unfortunately the Sdata standard only has provision for this information at the overall feed level and not at the entity level.

Just to be clear this deletion complexity is not due to Sdata as the same rules hold for the Accounts 50 UI and SDO (the product specific SDK) and other providers may have a much simpler implementations.

malard commented 7 years ago

Okay, is there a way of raising specific Accounts 50 sdata issues? I have setup a fake company, created one contact, then one delivery address.

Then i try and delete the delivery address, and this fails. There is no items referencing the data (as far as i can tell) but i still get a 200 response and the data is not actually deleted.

Would this be a "bug" with the sdata implementation for Accounts 50?

darroncockram commented 7 years ago

If a record that should be allowed to be deleted isn't that could be a bug but not deleting address data that that is not allowed to deleted independently in the main application would be by design. Could you share the response data for the GET request on the address record you are trying to delete please. I will see if I can replicate the issue.

malard commented 7 years ago

As mentioned above, all I get back is a 200, with no body, as per the sdata specification.

darroncockram commented 7 years ago

As mentioned above, all I get back is a 200, with no body, as per the sdata specification.

It's the response to a GET request for the postalAddress record you are trying to delete that I was asking for.

malard commented 7 years ago

http://localhost:5493/sdata/accounts50/GCRM/-/postalAddresses(a90fd823-b130-40da-b177-bc427e5a7c28)?format=json

{ "$descriptor": "Sage Accounts 50 | postalAddress - Pulse-Eight Test ", "$totalResults": 1, "$startIndex": 1, "$itemsPerPage": 1, "$resources": [ { "$url": "http://p8-dir001:5493/sdata/accounts50/GCRM/{8F10E9D8-4EF0-45FC-AC5F-6629F940DDC9}/postalAddressCustomerShipping(a90fd823-b130-40da-b177-bc427e5a7c28)?format=atomentry", "$uuid": "a90fd823-b130-40da-b177-bc427e5a7c28", "$httpStatus": "OK", "$descriptor": "", "active": true, "reference": "SAGEINTE", "name": "Customer Delivery Address", "description": "OLD OFFICE", "address1": "Unit 2", "address2": "57 Hatch Pond Road", "address3": null, "address4": null, "townCity": "Poole", "county": null, "stateRegion": "Dorset", "zipPostCode": "BH17 9JZ", "country": "United Kingdom", "primacyIndicator": false, "type": "Shipping" } ] }

malard commented 7 years ago

btw, seperate bug, when you get a json response back, the $url value has format=atomentry at the end, not format=json

darroncockram commented 7 years ago

Sorry, forgot to ask. What version of Age 50 Accounts are you using?

malard commented 7 years ago

Sage.Integration.Accounts50.SDO.Adapter.GCRM.Feeds.dll = 23.0.3.140

SBD Desktop Version 14.0.54.0

darroncockram commented 7 years ago

I cannot replicate getting a 200 response when attempting to delete a customer delivery address but I have managed to replicate the 'Member not found' error originally reported. I have passed this on to the Accounts team.

malard commented 7 years ago

which endpoint are you calling though?

You get a 200 with postalAddresses but contacts gives you the Member not found error

darroncockram commented 7 years ago

I am calling the postalAddresses enpoint