You do not have the following permissions on CodeUnit ... Execute - dynamics-business-central

I have an AL extension deployed on a BC V20 On-Prem system (Version: GB Business Central 20.0 (Platform 20.0.37114.38150 + Application 20.0.37253.38230)). It was working fine until a new licence was installed. It also works on a Cloud Sandbox. A brief outline of the purpose of the extension is to provide a custom page with a subform and a report associated with it.
I believe I have permissions set-up correctly in my codeunit:-
Permissions = TableData TrialBalByDimParams = rimd,
TableData TrialBalanceByDim = rimd,
TableData "G/L Account" = r,
TableData "G/L Entry" = r,
TableData "General Ledger Setup" = r,
TableData "Dimension Value" = r,
TableData "Accounting Period" = r;
There's also a permission set (as below) which I have assigned to the current user for all companies.
permissionset 50000 CustomFuncsYW
{
Assignable = true;
Permissions = tabledata TrialBalanceByDim=RIMD,
tabledata TrialBalByDimParams=RIMD,
table TrialBalanceByDim=X,
table TrialBalByDimParams=X,
report CustomTrialBalanceByDim=X,
codeunit CustomTrialBalancePopulator=X,
page TrialBalanceByDim=X,
page TrialBalByDimParams=X,
query GleDv1=X;
}
In Effective Permissions the 'Execute Permission' column does not contain 'Yes' for my CodeUnit (see below). Is this incorrect?
From a Universal Code perspective, I do not have a Target setting in my app.json file. My understanding is, that means its default value is 'Cloud'.
Is there anything else code-wise I can check for that might cause it to work under one licence and not another?
Does this mean it's licence related? If yes, what can I look for in the licence file that may reveal the issue?

This does indeed look like a license issue.
To troubleshoot it and pinpoint the problem, try running the same action under a user account with SUPER permissions. If the same error still occurs, this will eliminate the option of a permission set misconfiguration.
To check the license, first of all, you can open the .flf or .bclicense (whichever you use) in Notepad and look at the summary section. It should contain the list of purchased objects, like this:
****************************************************************************
Name Amount
----------------------------------------------------------------- ----------
Country Code: Great Britain 1
Dyn365 Business Central Codeunits (100) 100
Dyn365 Business Central Codeunits (each) 23
Dyn365 Business Central Pages (100) 300
Dyn365 Business Central Pages (each) 34
Dyn365 Business Central Premium 50
Dyn365 Business Central Premium - Upgrade 100
Dyn365 Business Central Queries (100) 100
Dyn365 Business Central Reports (100) 100
Dyn365 Business Central Tables (10) 60
Dyn365 Business Central Tables (each) 4
Dyn365 Business Central XML Ports (100) 100
****************************************************************************
I assume the error that you encounter refers to the custom codeunit CustomTrialBalancePopulator. So at least one custom codeunit must be present in this list.
If this part is ok, check the assigned IDs in the license permissions. GB version of BC 20 has a report License Permissions which you can run, or simply open the table License Permission in the browser:
<BC Service URL>?table=2000000043
In this table, check if your codeunit ID has the execution permission assigned. If not - the license should be recreated with correct permission.
Correct list of objects with custom codeunit permissions should be like this:
Regarding the universal code - that's correct, if the target value is not specified in the app.json, the default is "Cloud".
Note that this object ID assignment only applies to BC on prem, cloud deployments don't need this hassle, therefore it works for you in a cloud sandbox.

Related

How to overwrite sqlite database for existing users in a Xamarin Forms app?

We have a Xamarin Forms app.
We have a few existing users which had been using the app since last year where the database file name is MyAppName.db
Our new app strategy requires us to include the .db (Sqlite) along with the app to ensure we can include persistent information and does not require internet when you install the app, meaning we hope to overwrite the db file for existing users.
After we publish this new change where the database file is now MyNewDbFile.db, our users complain that they do not see any data, the app does not crash tough.
We capture error reports and we can see a common error in the our tool stating about "row value missused", a quick search indicates the value are not present and so the "SELECT * FROM TABLE WHERE COLUMNAME" query does not work causing the exception.
We can confirm we are using
Xamarin.Forms version 4.5.x
sqlite-net-sqlcipher version 1.6.292
We do not have any complex logic and cannot see a very specific reason causing this as this is not produced when we test our apps from the Alpha channel or the TestFlight.
We investigated the heart of the problem and can confirm that the troublemaker is the device Culture information.
We have been testing with English as the device language, however the minute the app is used by folks with any other language except English the query causes exception.
We make use of the Xamarin Essentials library to get device location (which is optional).
The latitude and longitude returned are culture specific.
So if you are using a Spanish language on device, the format for the Latitude and Longitude information is a , (comma) and NOT a . (dot).
That is, a Latitude value is something similar to 77.1234
where it is separated by a . (dot)
However for users with different region settings on device, the format would change to
77,1234 as value where it is separated by a , (comma).
The query requires us to have the values as string and that when not separated by a . (dot) fails to execute:
Query:
if (deviceLocation != null)
queryBuilder.Append($" ORDER BY((Latitude - {deviceLocation.Latitude})*(Latitude - {deviceLocation.Latitude})) +((Longitude - {deviceLocation.Longitude})*(Longitude - {deviceLocation.Longitude})) ASC");
Where the deviceLocation object is of type Xamarin.Essentials.Location which has double Latitude and Longitude values but when used as a string or even if you explicitly do deviceLocation.Latitude.ToString(), it would return the formatted values as per the device CultureInfo.
We can confirm that the problem is due to a mismatch of the format type and causing the query to throw an exception and in return making the experience as if there is no data.

CashPaymentFlow always generates anonymous change output

The CashPaymentFlow has a parameter anonymous to say whether the recipient should be replaced by a confidential identity. In my case, I don't want the confidential identity, so I set it to false.
This works fine for the recipient output (Contains the well known party) but not for the change output to the sender (Contains an anonymous Party).
This happens even if the original sender input is not anonymous
Im on Corda Release 4 on a ubuntu azure VM.
fun sendPayment(amount: Amount<Currency>, recipient: Party): AbstractCashFlow.Result? {
val anonymous = false
val handle = proxy.startTrackedFlow(::CashPaymentFlow, amount, recipient, anonymous)
return handle.returnValue.get()
}
Assume we are sending from A to B and have one unspent output with owner A and value 1000 EUR. Now call sendPayment with amount 800 EUR and recipient B.
I would expect two outputs:
800 EUR, owner B
200 EUR, owner A
Instead I get
800 EUR, owner B
200 EUR, Anonymous(SDFOMWEORHEWLRKHWLEKR...)
Historically, change from cash spends in Corda have been returned using confidential identities. This is the default functionality when generating a spend with either confidential or well-known identities and can't be overridden through CashPaymentFlow.
The Tokens SDK will be replacing Cash (and the rest of the finance module) in due course through which you'll be able to make anonymous change keys optional.

gitlab: get all projects/groups of a member

I'm trying to find inactive members in my GitLab-CE instance via the Gitlab API (v4).
One of the criteria for "(in)activity" is, whether a given user is member of any project or group.
While this information seems to be readily available via the webinterface (Groups and projects tab on the user's overview page in the admin area), I cannot find that information via the API.
The only way i currently found is, to iterate over all projects (resp. groups) and check whether the user is member thereof.
This strikes me as very slow (as there are probably zillions of projects), so I'm looking for a more direct way to query the system for all projects where user is member-of.
As in doc(https://docs.gitlab.com/ce/api/members.html), you can use:
GET /groups/:id/members
GET /projects/:id/members
to get only members added directly in a group/project
or:
GET /groups/:id/members/all
GET /projects/:id/members/all
to get all members (even those inherit from groups above)
---EDIT regards to #Nico question ---
In order to know if a user is a member of a project the solution tested by #umläute is to iterate over project members then all subgroup untill it reaches the user:
Given \fu\bar\project_p
With project_p.id = 1
bar.id = 10
fu.id = 100
Is user 'Nico' a member of project_p ?
GET /projects/1/members returns ('Paul') / No
GET /groups/10/members returns ('Marc', 'Jean') / No
GET /groups/100/members returns ('Nico') / Yes
Instead Gitlab provide an other API :
GET /projects/1/members/all returns ('Paul', 'Marc', 'Jean', 'Nico') / Yes

Paypal Processing - Need to grab TransactionId, CorrelationId and TimeStamp

Current Project:
ASP.NET 4.5.2
MVC 5
PayPal API
I am using this example to build myself a PayPal transaction (and yes, my code is virtually identical), as I do not know of any other method that will return the three values in the title.
My main problem is that, the example I am utilizing is much more concise and compact than the one I used for a much older Web Forms application, and as such, I am unsure as to where or even how to grab the three values I need.
My initial thought was to do so right after the ACK, and indeed I was able to obtain the CorrelationId as well as the TimeStamp, but because this was prior to the user being carted off to PayPal’s site (sandbox in this case -- see the return new PayPalRedirect contained within the if), the TransactionId was blank. And in this example, PayPal explicitly redirects the user to a Success page without returning to the Action that sent the user to PayPal in the first place, and I am not seeing any GET values in the URL at all aside from the Token and the PayerId, much less ones that could provide me with the TransactionId.
Suggestions?
I have also looked at the following examples:
For ASP.NET Core, was unsure how to adapt to my current project particularly due to appsettings.json, but it looked quite well done. I really liked how the values were rolled up in lists.
For MVC 4, but I couldn’t find where ACK was being used to determine success or successwithwarning so I couldn’t hook into that.
I have also found the PayPal content to be like trying to drink from a fire hose at full blast -- not only was the content was hopelessly outdated (Web Forms code, FTW!) but there was also so many different examples it would have taken me days to determine which one was most appropriate to use.
Any assistance would be greatly appreciated.
Edit: my initial attempt at modifying the linked code has this portion:
values = Submit(values);
var ack = values["ACK"].ToLower();
if(ack == "success" || ack == "successwithwarning") {
using(_db = new ApplicationDbContext()) {
var updateOrder = await _db.Orders.FirstOrDefaultAsync(x => x.OrderId == order.OrderId);
if(updateOrder != null) {
updateOrder.OrderProcessed = false;
updateOrder.PayPalCorrelationId = values["CORRELATIONID"];
updateOrder.PayPalTransactionId = values["TRANSACTIONID"];
updateOrder.PayPalTimeStamp = values["TIMESTAMP"];
updateOrder.IPAddress = HttpContext.Current.Request.UserHostAddress;
_db.Entry(updateOrder).State = EntityState.Modified;
await _db.SaveChangesAsync();
}
}
return new PayPalRedirect {
Token = values["TOKEN"],
Url = $"https://{PayPalSettings.CgiDomain}/cgi-bin/webscr?cmd=_express-checkout&token={values["TOKEN"]}"
};
}
Everything within and including the using() is my added content. As I mentioned, the CorrelationId and the TimeStamp come through just fine, but I have yet to successfully obtain the TransactionId.
Edit 2:
More problems -- the transactions that are “successful” through the sandbox site (the ReturnUrl is getting called) aren’t reflecting properly on my Facilitator and Buyer accounts, even when I do payments straight from the buyer’s PayPal account (not using the Credit Card). I know I am supposed to see transactions in the Buyer’s account, either through the overall Dev account (Accounts -> Profile -> balance or Accounts -> Notifications) or through the Buyer’s account in the sandbox front end. And yet -- multiple transactions returning me to the ReturnUrl path, and yet no transactions in either.
Edit 3:
Okay, this is really, really weird. I have gone over all settings with a fine-toothed comb, and intentionally introduced errors to see where things should crap out. It turns out that the entire process goes swimmingly - except nothing shows up in my notifications and no amounts get moved between my different accounts (Facilitator and Buyer). It’s like all my transactions are going into /dev/null, yet the process is successful.
Edit 4: A hint!
In the sandbox, where Buyer accepts the transaction, there is a small note, “You will be able to review the transaction before completing it” or something like that -- suggesting that an additional page is not coming up and that the user is being uncerimoniously dumped back to the success page. Why the success page? No clue. But it’s happening.
It sounds like you are only doing the first part of the process.
Express Checkout consists of 3 API calls:
SetExpressCheckout
GetExpressCheckoutDetails
DoExpressCheckoutPayment
SEC generates a token, and then you redirect to PayPal where the user signs in and reviews the transactions before agreeing to pay.
They are then sent to the ReturnURL included in your SEC request, and this is where you'll call GECD in order to obtain all the buyer details that are now available since they signed in.
Using that data you can complete the final DECP request, which is what finalizes the procedure. No money is actually processed until this final call is completed successfully.

SCORM 1.2 API calls to set the grade in gradebook

What javascript API calls are needed to set the grade after completing an activity? Now I have these three calls:
LMSSetValue("cmi.core.score.min", 0);
LMSSetValue("cmi.core.score.max", 100);
LMSSetValue("cmi.core.score.raw", score);
I also set the status to completed:
LMSSetValue("cmi.core.lesson_status", "completed");
When I complete the activity as a student, sometimes I can see icon which tells that
activity is completed ("1 attempt(s)"), sometimes not. The gained score is never there.
Desire2Learn is at version 10.1
Not a SCORM expert by any means, but someone here that knows more about it than me makes these points:
You also need to call Commit and Terminate and/or LMSFinish; you can find some good technical resources to help developers at the SCORM website, in case you don't already know about them.
To verify scores and status getting to the Learning Environment, you can check the SCORM reports in the Web UI (Content > Table of Contents > View Report), which is the standard place to view SCORM results.
If scores are set there, you can get them into the grade book in two ways:
You can preview the content topic as an instructor: below the topic view, you'll find a spot to associate a grade item with the topic.
If the DOME configuration variable d2l.Tools.Content.AllowAutoSCORMGradeItem is on for the course, that should automatically create a grade item for that SCORM content object.
As Viktor says, you must invoked LMSCommit after using LMSSetValue, or else the data will not be persisted ('saved') in the LMS.
LMSSetValue("cmi.core.score.min", 0);
LMSSetValue("cmi.core.score.max", 100);
LMSSetValue("cmi.core.score.raw", score);
LMSSetValue("cmi.core.lesson_status", "completed");
LMSCommit(); //save in database
LMSFinish(); //exit course
Note that "LMSSetValue" is not an official SCORM call, it means you're working with a SCORM wrapper of some kind. Therefore where I say LMSCommit and LMSFinish, you might actually need to use different syntax -- I'm just guessing about the function names. Check your SCORM wrapper's documentation. The point is that you need to commit (save) and terminate (finish).

Resources