Unable to get the final calculated grade value for a student in a course - desire2learn

I have used the following api call
/d2l/api/le/1.2/courseid/grades/final/calculated/studentid
but I get an error message saying Error: Unknown: NOT_FOUND.
Does that mean the grade isn't posted or is it a security issue?

That API gets used to initiate a final grade re-calculation for a student. Your 404 Not Found error most likely means one of these things:
You are using the wrong HTTP Method for this route (i.e. you're making a PUT or GET call, when it should be a POST with an empty body)
Your LMS doesn't support the API version you're using (1.2 in your example)
You haven't specified the correct LMS Org Unit ID value for the course offering
You haven't specified the correct LMS User ID value for the student
Note that "correct value" for those last two must mean that the two entities exist and have an appropriate relationship (i.e. they both validly identity a course, and a user, respectively, and that the user is explicitly enrolled in the course offering with a gradeable role).

Related

What datatype should i use for saving the unique user id returned by an Oauth provider

I want to store the unique user id returned in the response by an Oauth provider in my SQL database. I've seen some posts suggesting that varchar(128) should be enough. Are there any providers whose user id extends this limit? I have checked the docs for some of the more popular providers like Google, Facebook and Github but I can't seem to find any information about the size of this user id.
OIDC defines the sub claim as:
A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is a case sensitive string.
So better use VARCHAR(255).

Desire2Learn Valence API, PUT CourseOffering 404

Based on the information here http://docs.valence.desire2learn.com/res/course.html#actions I would expect that to 'update' a courseOffering I would specify a PUT with a CourseOfferingInfo block, which only contains a few attributes. Every time I try this, I get a 404, not found - even using the same route for a successful GET (404 says org doesn't exist OR org is not an offering - neither is true). However, if I specify a CreateCourseOffering block (directly from a previous GET), the PUT works fine. Is this correct and the documentation not? Or are there other things I should look for in this scenario? The documentation says use CreateCourseOffering for the POST to create an offering… I simply want to update one attribute of that offering and as such thought the PUT was the way to go.
If you use the "create" POST route with a CreateCourseOffering block, this will create a new course offering, and send back the CourseOffering block for the newly created course offering (this will include the org unit ID value for the new org unit you've built).
If you want to update an existing course offering, you should, as you suspected, use the "update" PUT route with a CourseOfferingInfo block. Note that you must provide valid information for all the fields in this block, since when used successfully, the LMS will use all the properties you specify in that block for new values for the org unit. The StartDate and EndDate fields are particularly finicky: you must provide either a valid UTCDateTime value (notice that the three-digit millisecond specifier in these values is mandatory) or a JSON null value if the field is not applicable.
Why a 404? What you're seeing with the 404s and the data you're passing is likely down to the way the back-end service is doing data binding. It tries to de-serialize your provided JSON data (and query parameters) into data objects it can read/manipulate -- if you provide a JSON block that contains a superset of the properties it's expecting, then this may work (for example, if you provide a CourseOffering block when you're expected to provide a CourseOfferingInfo) as the binding layer may ignore fields it doesn't need. If the binding process fails, because you provide a value for a property that can't be bound to the data type expected, or because you fail to provide a JSON property field it expects, then this can cause the service to return a 404 (because binding/de-serializing incoming parameterized data happens at the same time as matching the URL route to an underlying service handler).
If you provide a JSON structure (and query parameters) that the web-service can bind to its expected data objects, but the values you provide are invalid or nonsensical, then this can cause the underlying service handler to respond with a 400 (signalling an Invalid Request). But in order to get this far, your parameterized data still needs to get properly deserialized and bound into data objects for the underlying service to examine.
We'll be updating the documentation to more explicitly draw out this fact. The safest policy from the calling client perspective is to pass valid JSON structures that are exactly what's expected by the individual routes, especially since the underlying back-end service implementation might change how it handles incoming requests.

Modifing Desire2Learn Groups using the Valance REST API

I'm a bit confused on how we are supposed to update a group using the Valence API.
According to documentation, "Name,Code & Description" are required for updating, but the FETCH group block only returns "GroupID,Name, Description and Enrollments". If Group Code is not returned in the fetch, what value are we supposed to use in the update block if we only want to update the name? Since description is provided I can just feed that back, but what am I supposed to do about code ... just lose that data?
Perhaps there a way to send an update that will update only specific fields in the update block? When I omit fields from the update block I currently receive an error (ie in the case I only want to update the name).
The Code property for Groups is intended to be the "org-defined code" for the group (for a course offering, this is often called the "course code"), the one that might appear in the organization's SIS system, for example.
Because groups in Desire2Learn's Learning Suite are considered "org units", when you create one, you need to provide it with an appropriate org-defined code (Code) -- if your organization doesn't use org-defined codes for groups, then you can decide to systematically use some other kind of data by convention (a name, a descriptive string, and so on). You are correct that's inconvenient for the Fetch form of the GroupData structure not to provide this value for you, but the value will be accessible to callers through the organization structure routes (because the newly created group is just an special kind of org unit).
In Learning Suite v10.2 (LP API v1.3+) and later, you can use a single GET call to fetch back the properties for an org unit. In versions prior to v10.2, you will need to fetch the list of parents for the group to get a parent org unit ID, or if you already know the org unit ID for the course offering that owns the group you can use that; then you use that org unit ID to fetch its list of children: your group will be in that list. The OrgUnit and OrgUnitProperties structures both contain the Code property that you need here.

REST URL naming convention /items/{id} vs /items?id={id}

I understand that in MVC pattern and in REST services it is common to use URIs like /items/{id} but what is bad thing about using query parameters in the URI?
GET /items/{id} vs GET /items?id={id}
Further, lets say an entity has 'referenceId' field that points to some related (say parent) entity, and I need to create REST service to get all items for parent entity, which way is better:
GET(POST) /items/parent/{parentId}
or
GET(POST) /items?parent={parentId}
Will be grateful for insights that would help to resolve my subjective issues on constructing URLs for REST services.
I would use the following schemes.
/items/id
This uniquely addresses a resource of items with id id. We are not using parameters as a parameter to uniquely address this resource (as is the case with the other option). Just as
miguelcobain suggests.
/parent/id/items
Here id is an id to uniquely address a resource of parent and from those we collect/retrieve the items it references. From what you have said in the question it seems that parent references multiple items, like a container or collection.
The convention I use for this is to narrow down the scope going from left to right. Therefore in case items could be active or inactive. Thusly items have a property or attribute to be active or inactive. Narrowing down on this I get the following scheme:
/items/active
/parent/id/active
For your first question:
/items/{id} should retrieve a single resource with the specified id or 404 if it doesn't exist.
/items/?id={id} should retrieve an array (even if only one in the array) because you are querying the collection.
For your second question:
I agree with #miguelcobain's assessment - if the item is a specific resource/entity, just use the proper resource path to retrieve it.
To make this easier on the consumer, create a link header with rel="parent" and/or include the uri in the child resource. For an example of link headers, see GitHub's pagination api.
Of course, REST principles don't care about aesthetic details on URLs. It just imposes that every resource should be uniquely addressable.
Furthermore, using the query parameters to uniquely address something "kind of" violates the semantics of a "parameter", doesn't it? A parameter should be something optional, something additional and parameterized. Something like a detailed search on a collection of items, for example.
What you wrote may make sense in some cases. It depends.
In your example, is the item really a resource? If not, you could just do GET(POST) /parents/{parentId}.
If parent is, say, a boolean, and you want to search the items that have parent equals to true, then using the parameters makes sense. But since you're explicitly saying that you want a parent with a specific id, I assume that parent is a resource itself and I would uniquely address that resource using your option 1.
I hope I made myself clear.
It seems to me there are no rules to follow.
items/{id} - this convention is suitable for GET item by given id. If user doesn't provide id then it returns 404 status code.
items/id={id}&name={name} - this type of convention is suitable for search multiple items by given criteria. If no items are found, it is not a 404 situation, you simply say "I successfully found nothing matching your search criteria"

Name on Check in QuickBooks SDK

I have a customer requirement to export the checks written in QuickBooks into a specific format because their bank allows fraud prevention by uploading a file and they verify the name on the check against what you give them before clearing it.
I looked at the QuickBooks SDK (we use the XML to communicate in general) and It references a field on the check called PayeeEntityRef with a FullName property, but typically in QuickBooks that data structure would indicate what the entity is called, not what appears on the check (Vendors have a NameOnCheck property, for example, which can be something other than their name).
Without coding up multiple test cases to demonstrate QuickBooks behavior here, does anyone have experience with getting the name as it was printed on the check? What is the best way to do it?
It's somewhat possible to get what you are wanting, but there are going to be some hiccups that you'll need to let you client know about. The main problem being that there's no way to retrieve the actual name printed on the check.
You would first need to query for the Checks/Bill Payment - Checks for the bank account. Then, using the PayeeEntityRef (I would use the ListID component) figure out which "List" the entity is on; Customer, Vendor, Employee, or Other. I don't know of any way to tell which list the PayeeEntityRef is from other than doing a query for each of the lists.
If the PayeeEntityRef is a Vendor or Employee, then you can retrieve the NameOnCheck value. The only thing you would need to keep in mind is that if the NameOnCheck has been modified AFTER the check was printed, the names will not match.
If the PayeeEntityRef is a Customer or Other name, then you have to do a little bit more. The value that QuickBooks uses for the printed name is based on what fields are filled out for the customer record. It first will use the CompanyName field if it is not null. Next, it will try to use the First/Middle/LastName fields, if they are not null. Finally, it will use the Name field as a last resort. Keep in mind that this is not the FullName field, just the Name field.
I haven't tested this with an "Other" name, as I have my clients try not to use that list, but I would imagine it's similar to how Customers work.

Resources