Sending info to database and retrieving as well as using for k,v, in pairs() do - mysql

Issue i have come across is i have an item, if you use this item it writes to the database with your id and the item name. which is correct and this is what i want to happen, but i want it to first look at the database and see if the item is already there and if so stop the insert.
This is the item.
QBCore.Functions.CreateUseableItem("pumpshotgun_bp", function(source, item)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.Functions.GetItemBySlot(item.slot) ~= nil then
QBCore.Functions.TriggerCallback('sin-crafting:server:getCrafts', src, function(result)
if result ~= nil then
TriggerClientEvent("sin-crafting:client:Update", source, "pumpshotgun_bp")
end
end)
end
end)
after that i query the info to the database
QBCore.Functions.CreateCallback('sin-crafting:server:getCrafts', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
local cid = Player.PlayerData.citizenid
local printList = {}
MySQL.query('SELECT * FROM player_crafts WHERE cid = ?', { Player.PlayerData.citizenid }, function(crafts, item)
for k, v in pairs(crafts) do
if v == nil then
end
table.insert(printList,
{
citizenid = v.citizenid,
blueprint = v.blueprint,
}
)
end
cb(json.encode(printList))
end)
end)
and then
the item then triggers this when used and changed info from the item_bp to the actual name for the database
RegisterNetEvent('sin-crafting:client:Update', function(data)
if data == "pumpshotgun_bp" then
TriggerServerEvent('sin-crafting:server:newBlueprint', 'pumpshotgun')
end
end)
Problem now is when i use that item again it will write it again to the database and i dont want that i want instead to set up a notify script that will tell them they have already learned that.
This is the first half of my issue, the second half is pulling the list from the database and and checking it in the script. I really need help as I have been trying to do this for over a week now and cant find a way to do it
This is the config to use for the for k,v in pairs() do, <---which I cant figure out how to do right....
Config.Weapons = {
"pumpshotgun",
"dbshotgun",
"assaultrifle",
"smg",
"combatpistol",
"gusenberg",
"microsmg",
"carbinerifle",
"compactrifle",
"heavypistol",
"machinepistol",
"revolver",
"rifle_silencer",
"pistol_silencer",
"smg_silencer",
"shotgun_silencer",
"weapon_optics",
}

Related

How can I use Logical Operator between 2 Select Statements?

I have few tables which are joined by some conditions.
What I am trying to achieve is Combine 2 SELECT statements in such way where
If there is data in Condition 1 display them OR go to Condition 2 and display data
Condition 1 - I am getting record from table say for exampleA, B, C and D based on some conditions
Condition 2 - I am getting record from table say for example A, B, C and E based on some conditions
What is am trying to achieve is
Display record if it exists in Condition 1
OR
Display record if it exits in Condition 2
Condition 1/ Query 1 - Display data
async getData() {
try {
const data = await this._conn.query(`
select first_name.value_name,quiz_table.answer, windows,player,first_name.value_id,country_place,current_name, pet_name, marker, relations
from schema_name.plugin,schema_name.quiz_table,schema_name.first_name, schema_name.value_version, schema_name.relationss
where plugin.answer= quiz_table.answer
and quiz_table.windows=first_name.value_id
and marker is not null
and schema_name.value_version.value_id= schema_name.first_name.value_id
and schema_name.value_version.caste= schema_name.first_name.caste
and schema_name.value_version.value_name= schema_name.first_name.value_name
and schema_name.value_version.version_number= schema_name.first_name.version_number
and schema_name.relationss.value_id= schema_name.first_name.value_id
and schema_name.relationss.caste= schema_name.first_name.caste
and schema_name.relationss.value_name= schema_name.first_name.value_name
and schema_name.relationss.version_number= schema_name.first_name.version_number
and schema_name.quiz_table.windows= schema_name.first_name.value_id
and in_process='N'
}
OR
Condition 2/ Query 2 - Display data
select schema_name.relationss."relations", schema_name.quiz_table."answer", schema_name.quiz_table."windows", schema_name.quiz_table."in_process", schema_name.quiz_table."object_name", schema_name.quiz_table."processed_date", schema_name.quiz_table."player", schema_name.quiz_table."country_place", schema_name.tools."mesh_scope_note", schema_name.plugin."current_name", schema_name.plugin."pet_name"
from schema_name.quiz_table, schema_name.tools, schema_name.plugin, schema_name.relationss, schema_name.value_version
where (in_process = 'N'
and schema_name.quiz_table."windows" = schema_name.tools."value_id"
and schema_name.quiz_table."player" = schema_name.tools."language"
and schema_name.quiz_table."answer" = schema_name.plugin."answer"
and schema_name.relationss."language" = schema_name.quiz_table."player"
and schema_name.relationss."language" = schema_name.tools."language"
and schema_name.relationss."caste" = schema_name.tools."caste"
and schema_name.relationss."value_name" = schema_name.tools."value_name"
and schema_name.relationss."version_number" = schema_name.tools."version_number"
and schema_name.relationss."value_id" = schema_name.tools."value_id"
and schema_name.value_version."value_id" = schema_name.tools."value_id"
and schema_name.value_version."version_number" = schema_name.tools."version_number"
and schema_name.value_version."caste" = schema_name.tools."caste"
)
NOTE - 1-> I cannot use function or procedure here.
2-> Both the `Conditions` contains `different data`
The problem is, how will the computer choose which option to go to? A computer does not choose, it can't. You have to provide some metric for which to choose. The boolean operator || (or) is for checking if either is true (declarative-sorta), not for imperative. You can 'ask' "is a or b true?" but you can't tell a computer, "do this or that" without any weight to either one which would explain to the computer which to pick and when.
What would be possible is asking,
"If there is data in Condition 1 display them; if not, go to Condition 2 and display data".
If that suits your needs, this is how it could be coded (this is just the framework).
if (data1 != null) {
show data1
}
else {
show data2
}
Or your data could be non-null, but have no contents, in which you could try to get some data from it (say, getChildren() (totally random, I'm just making that up):
if (data1.getChildren() != null) {
show data1
}
else {
show data2
}
I hope you know that this is just pseudocode for the theory of it. show_ is not actual code, it's just the placeholder for whatever you would write. Would this work - checking if it is null and/or checking if its contents are null (i.e., it's empty/without data) and if so then going to the next dataset?
I don't know sql, but I thought that idea of check-null/check-contents-null might help.

MySQL and LUA not triggering correctly or code incorrect

I am struggling to trigger a server event succesfully on my FiveM server. Or maybe it gets triggered but the server event is incorrect. However I do not get any errors and I don't know what to fix...
Server-side
RegisterServerEvent('carwash:pay')
AddEventHandler('carwash:pay', function()
local _source = source
local price = 20
local identifier = GetPlayerIdentifier(_source)
MySQL.Async.fetchAll("SELECT * FROM economy WHERE identifier = #identifier", {
['#identifier'] = identifier
}, function(result)
if result >= 20 then
MySQL.Async.execute('UPDATE economy SET cash = cash - #price WHERE identifier = #identifier',
{ ['#identifier'] = identifier, ['#price'] = price }
)
end
end)
end)
Client-Side
TriggerServerEvent('carwash:pay')
I don't know if you're still working on it or figured it out but for those who have the same problem, I'm gonna answer this.
The problem here is that you are comparing a whole table (SELECT * FROM economy...) to the number 20.
Besides, a "fetchAll" will allways output an array, so, in order to acces the column cash from the table economy, you need to use "result[1].cash".
Then, sometimes the "error" is not a syntaxe one, you need to put some "print()" here and there to understand where it stops, changes or just check if it works.
e.g. :
RegisterServerEvent('carwash:pay')
AddEventHandler('carwash:pay', function()
local _source = source
local price = 20
local identifier = GetPlayerIdentifier(_source)
MySQL.Async.fetchAll("SELECT * FROM economy WHERE identifier = #identifier", {['#identifier'] = identifier},
function(result)
-- CHECK WHAT IT RESULT
print(result)
if result >= 20 then
MySQL.Async.execute('UPDATE economy SET cash = cash - #price WHERE identifier = #identifier', { ['#identifier'] = identifier, ['#price'] = price })
end
end)
end)

Update planned order - two committed modifications, only one saved

I need to update two information on one object: the quantity (PLAF-gsmng) and refresh the planned order via the module function 'MD_SET_ACTION_PLAF'.
I successfully find a way to update each data separately. But when I execute the both solutions the second modification is not saved on the database.
Do you know how I can change the quantity & set the action on PLAF (Planned order) table ?
Do you know other module function to update only the quantity ?
Maybe a parameter missing ?
It's like if the second object is locked (sm12 empty, no sy-subrc = locked) ... and the modification is not committed.
I tried to:
change the order of the algorithm (refresh and after, change PLAF)
add, remove, move the COMMIT WORK & COMMIT WORK AND WAIT
add DEQUEUE_ALL or DEQUEUE_EMPLAFE
This is the current code:
1) Read the data
lv_plannedorder = '00000000001'
"Read PLAF data
SELECT SINGLE * FROM PLAF INTO ls_plaf WHERE plnum = lv_plannedorder.
2) Update Quantity data
" Standard configuration for FM MD_PLANNED_ORDER_CHANGE
CLEAR ls_610.
ls_610-nodia = 'X'. " No dialog display
ls_610-bapco = space. " BAPI type. Do not use mode 2 -> Action PLAF-MDACC will be autmatically set up to APCH by the FM
ls_610-bapix = 'X'. " Run BAPI
ls_610-unlox = 'X'. " Update PLAF
" Customize values
MOVE p_gsmng TO ls_plaf-gsmng. " Change quantity value
MOVE sy-datlo TO ls_plaf-mdacd. " Change by/datetime, because ls_610-bapco <> 2.
MOVE sy-uzeit TO ls_plaf-mdact.
CALL FUNCTION 'MD_PLANNED_ORDER_CHANGE'
EXPORTING
ecm61o = ls_610
eplaf = ls_plaf
EXCEPTIONS
locked = 1
locking_error = 2
OTHERS = 3.
" Already committed on the module function
" sy-subrc = 0
If I go on the PLAF table, I can see that the quantity is edited. It's working :)
3) Refresh BOM & change Action (MDACC) and others fields
CLEAR ls_imdcd.
ls_imdcd-pafxl = 'X'.
CALL FUNCTION 'MD_SET_ACTION_PLAF'
EXPORTING
iplnum = lv_plannedorder
iaccto = 'BOME'
iaenkz = 'X'
imdcd = ls_imdcd
EXCEPTIONS
illegal_interface = 1
system_failure = 2
error_message = 3
OTHERS = 4.
IF sy-subrc = 0.
COMMIT WORK.
ENDIF.
If I go on the table, no modification (only the modif. of the part 2. can be found on it).
Any idea ?
Maybe because the ls_610-bapco = space ?
It should be possible to update planned order quantity with MD_SET_ACTION_PLAF too, at least SAP Help tells us so. Why don't you use it like that?
Its call for changing the quantity should possibly look like this:
DATA: lt_acct LIKE TABLE OF MDACCTO,
ls_acct LIKE LINE OF lt_acct.
ls_acct-accto = 'BOME'.
APPEND lt_acct.
ls_acct-accto = 'CPOD'.
APPEND lt_acct.
is_mdcd-GSMNG = 'value' "updated quantity value
CALL FUNCTION 'MD_SET_ACTION_PLAF'
EXPORTING
iplnum = iv_plnum
iaenkz = 'X'
IVBKZ = 'X'
imdcd = is_mdcd "filled with your BOME-related data + new quantity
TABLES
TMDACCTO = lt_accto
EXCEPTIONS
illegal_interface = 1
system_failure = 2
error_message = 3.
So there is no more need for separate call of MD_PLANNED_ORDER_CHANGE anymore and no more problems with update.
I used word possibly because I didn't find any example of this FM call in the Web (and SAP docu is quite ambiguous), so I propose this solution just as is, without verification.
P.S. Possible actions are listed in T46AS table, and possible impact of imdcd fields on order can be checked in MDAC transaction. It is somewhat GUI equivalent of this FM for single order.

BigCommerce Stencil - Product Variant Stock Levels

A client wants to set up A/B testing on the Product Detail Page related to the stock_level of a product's variants. Once the user selects their options, if the quantity is less than 5, I'd show something like "Hurry, only 3 more in stock"...
I believe I have the correct Inventory settings enabled, because I can retrieve the stock_level of a product without options.
Has anyone had success pulling variant SKU stock_levels in stencil?
Thanks
This can be done using javascript in the assets/js/theme/common/product-details.js file. On initial page load and each time a product option is changed, there is a function updateView(data) that is called. The data parameter contains all the info you need for the selected variation.
Starting on line 285, replace this:
updateView(data) {
const viewModel = this.getViewModel(this.$scope);
this.showMessageBox(data.stock_message || data.purchasing_message);
with this:
updateView(data) {
const viewModel = this.getViewModel(this.$scope);
if(data.stock < "5") {
data.stock_message = "Hurry, only " + data.stock + " left!";
}
this.showMessageBox(data.stock_message || data.purchasing_message);

Using ItemCollection on a BoxFolder type with Box API only returns 100 results and cannot retrieve the remaining ones

For a while now, I've been using the Box API to connect Acumatica ERP to Box and everything has been going fine until recently. Whenever I try to use a BoxCollection type with the property ItemCollection, I'll only get the first 100 results no matter the limit I set in the GetInformationAsync(). Here is the code snippet:
[PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public BoxCollection<BoxItem> GetFolderItems(string folderId, int limit = 500, int offset = 0)
{
var response = new BoxCollection<BoxItem>();
var fieldsToGet = new List<string>() { BoxItem.FieldName, BoxItem.FieldDescription, BoxItem.FieldParent, BoxItem.FieldEtag, BoxFolder.FieldItemCollection };
response = Task.Run(() => Client.FoldersManager.GetFolderItemsAsync(folderId, limit, offset)).Result;
return response;
}
I then pass that information on to a BoxFolder type variable, and then try to use the ItemCollection.Entries property, but this only returns 100 results at a time, with no visible way to extract the remaining 61 (in my case, the Count = 161, but Entries = 100 always)
Another code snippet of the used variable, I am basically trying to get the folder ID based on the name of the folder inside Box:
private static void SyncProcess(BoxFolder rootFolder, string folderName)
{
var boxFolder = rootFolder.ItemCollection.Entries.SingleOrDefault(ic => ic.Type == "folder" && ic.Name == folderName);
}
I wasn't able to find anything related to that limit = 100 in the documentation and it only started to give me problems recently.
I had to create a work around by using the following:
var boxCollection = client.GetFolderItems(rootFolder.Id);
var boxFolder = boxCollection.Entries.SingleOrDefault(ic => ic.Type == "folder" && ic.Name == folderName);
I was just wondering if there was a better way to get the complete collection using the property ItemCollection.Entries like I used to, instead of having to fetch them again.
Thanks!
Box pages folder items to keep response times short. The default page size is 100 items. You must iterate through the pages to get all of the items. Here's a code snippet that'll get 100 items at a time until all items in the folder are fetched. You can request up to 1000 items at a time.
var items = new List<BoxItem>();
BoxCollection<BoxItem> result;
do
{
result = await Client.FoldersManager.GetFolderItemsAsync(folderId, 100, items.Count());
items.AddRange(result.Entries);
} while (items.Count() < result.TotalCount);
John's answer can lead to a duplicate values in your items collection if there will be external/shared folders in your list. Those are being hidden when you are calling "GetFolderItemsAsync" with "asUser" header set.
There is a comment about it in the Box API's codeset itself (https://github.com/box/box-windows-sdk-v2/blob/main/Box.V2/Managers/BoxFoldersManager.cs)
Note: If there are hidden items in your previous response, your next offset should be = offset + limit, not the # of records you received back.
The total_count returned may not match the number of entries when using enterprise scope, because external folders are hidden the list of entries.
Taking this into account, it's better to not rely on comparing the number of items retrieved and the TotalCount property.
var items = new List<BoxItem>();
BoxCollection<BoxItem> result;
int limit = 100;
int offset = 0;
do
{
result = await Client.FoldersManager.GetFolderItemsAsync(folderId, limit, offset);
offset += limit;
items.AddRange(result.Entries);
} while (offset < result.TotalCount);