mongoengine.errors.ValidationError: Integer value is too small - mongodb

I have a simple User schema in mongoDB for my Flask server. I am using mongoengine to work with the database. The schema is as follows:
class User(Document):
username = StringField(unique=True, requireed=True)
email = EmailField(unique=True)
password = StringField(required=True)
creditCount = IntField(default=0, min_value=0, max_value=None)
date_created = DateTimeField(default=datetime.utcnow)
def json(self):
user_dict = {
"username": self.username,
"email": self.email,
"creditCount": self.creditCount,
}
return json.dumps(user_dict)
meta = {
"indexes": ["username"], # index based on username
"ordering": ["-date_created"], # order in decending order
}
When I try to decrement the creditCount of a user, I get an error saying the integer value is too small. I have confirmed that the user has 10 credits and they only need to have 1 credit for the code to work. The code I am using is as follows:
try:
user = User.objects(username=request.args["username"]).get()
print(user.creditCount)
except DoesNotExist:
return "That user does not exist"
if user.creditCount == 0:
return "You do not have enough credits to search for a doggo."
print("credits: " + str(user.creditCount)) #This is where I'm confirming the user has enough credits through the terminal
if os.path.isfile(filePath):
user.update(dec__creditCount=1)
return send_file(filePath)
I'm not entirely sure what the issue could be since I am validating that the user has more than one credit and also printing their credits to the terminal and they are over one. I am also able to increment the credit count with inc__creditCount=1.
Thanks!
Brad

There is an open ticket about this bug, see
https://github.com/MongoEngine/mongoengine/issues/2339

Related

Salesforce trigger-Not able to understand

Below is the code written by my collegue who doesnt work in the firm anymore. I am inserting records in object with data loader and I can see success message but I do not see any records in my object. I am not able to understand what below trigger is doing.Please someone help me understand as I am new to salesforce.
trigger DataLoggingTrigger on QMBDataLogging__c (after insert) {
Map<string,Schema.RecordTypeInfo> recordTypeInfo = Schema.SObjectType.QMB_Initial_Letter__c.getRecordTypeInfosByName();
List<QMBDataLogging__c> logList = (List<QMBDataLogging__c>)Trigger.new;
List<Sobject> sobjList = (List<Sobject>)Type.forName('List<'+'QMB_Initial_Letter__c'+'>').newInstance();
Map<string, QMBLetteTypeToVfPage__c> QMBLetteTypeToVfPage = QMBLetteTypeToVfPage__c.getAll();
Map<String,QMBLetteTypeToVfPage__c> mapofLetterTypeRec = new Map<String,QMBLetteTypeToVfPage__c>();
set<Id>processdIds = new set<Id>();
for(string key : QMBLetteTypeToVfPage.keyset())
{
if(!mapofLetterTypeRec.containsKey(key)) mapofLetterTypeRec.put(QMBLetteTypeToVfPage.get(Key).Letter_Type__c, QMBLetteTypeToVfPage.get(Key));
}
for(QMBDataLogging__c log : logList)
{
Sobject logRecord = (sobject)log;
Sobject QMBLetterRecord = new QMB_Initial_Letter__c();
if(mapofLetterTypeRec.containskey(log.Field1__c))
{
string recordTypeId = recordTypeInfo.get(mapofLetterTypeRec.get(log.Field1__c).RecordType__c).isAvailable() ? recordTypeInfo.get(mapofLetterTypeRec.get(log.Field1__c).RecordType__c).getRecordTypeId() : recordTypeInfo.get('Master').getRecordTypeId();
string fieldApiNames = mapofLetterTypeRec.containskey(log.Field1__c) ? mapofLetterTypeRec.get(log.Field1__c).FieldAPINames__c : '';
//QMBLetterRecord.put('Letter_Type__c',log.Name);
QMBLetterRecord.put('RecordTypeId',tgh);
processdIds.add(log.Id);
if(string.isNotBlank(fieldApiNames) && fieldApiNames.contains(','))
{
Integer i = 1;
for(string fieldApiName : fieldApiNames.split(','))
{
string logFieldApiName = 'Field'+i+'__c';
fieldApiName = fieldApiName.trim();
system.debug('fieldApiName=='+fieldApiName);
Schema.DisplayType fielddataType = getFieldType('QMB_Initial_Letter__c',fieldApiName);
if(fielddataType == Schema.DisplayType.Date)
{
Date dateValue = Date.parse(string.valueof(logRecord.get(logFieldApiName)));
QMBLetterRecord.put(fieldApiName,dateValue);
}
else if(fielddataType == Schema.DisplayType.DOUBLE)
{
string value = (string)logRecord.get(logFieldApiName);
Double dec = Double.valueOf(value.replace(',',''));
QMBLetterRecord.put(fieldApiName,dec);
}
else if(fielddataType == Schema.DisplayType.CURRENCY)
{
Decimal decimalValue = Decimal.valueOf((string)logRecord.get(logFieldApiName));
QMBLetterRecord.put(fieldApiName,decimalValue);
}
else if(fielddataType == Schema.DisplayType.INTEGER)
{
string value = (string)logRecord.get(logFieldApiName);
Integer integerValue = Integer.valueOf(value.replace(',',''));
QMBLetterRecord.put(fieldApiName,integerValue);
}
else if(fielddataType == Schema.DisplayType.DATETIME)
{
DateTime dateTimeValue = DateTime.valueOf(logRecord.get(logFieldApiName));
QMBLetterRecord.put(fieldApiName,dateTimeValue);
}
else
{
QMBLetterRecord.put(fieldApiName,logRecord.get(logFieldApiName));
}
i++;
}
}
}
sobjList.add(QMBLetterRecord);
}
if(!sobjList.isEmpty())
{
insert sobjList;
if(!processdIds.isEmpty()) DeleteDoAsLoggingRecords.deleteTheProcessRecords(processdIds);
}
Public static Schema.DisplayType getFieldType(string objectName,string fieldName)
{
SObjectType r = ((SObject)(Type.forName('Schema.'+objectName).newInstance())).getSObjectType();
DescribeSObjectResult d = r.getDescribe();
return(d.fields.getMap().get(fieldName).getDescribe().getType());
}
}
You might be looking in the wrong place. Check if there's an unit test written for this thing (there should be one, especially if it's deployed to production), it should help you understand how it's supposed to be used.
You're inserting records of QMBDataLogging__c but then it seems they're immediately deleted in DeleteDoAsLoggingRecords.deleteTheProcessRecords(processdIds). Whether whatever this thing was supposed to do succeeds or not.
This seems to be some poor man's CSV parser or generic "upload anything"... that takes data stored in QMBDataLogging__c and creates QMB_Initial_Letter__c out of it.
QMBLetteTypeToVfPage__c.getAll() suggests you could go to Setup -> Custom Settings, try to find this thing and examine. Maybe it has some values in production but in your sandbox it's empty and that's why essentially nothing works? Or maybe some values that are there are outdated?
There's some comparison if what you upload into Field1__c can be matched to what's in that custom setting. I guess you load some kind of subtype of your QMB_Initial_Letter__c in there. Record Type name and list of fields to read from your log record is also fetched from custom setting based on that match.
Then this thing takes what you pasted, looks at the list of fields in from the custom setting and parses it.
Let's say the custom setting contains something like
Name = XYZ, FieldAPINames__c = 'Name,SomePicklist__c,SomeDate__c,IsActive__c'
This thing will look at first record you inserted, let's say you have the CSV like that
Field1__c,Field2__c,Field3__c,Field4__c
XYZ,Closed,2022-09-15,true
This thing will try to parse and map it so eventually you create record that a "normal" apex code would express as
new QMB_Initial_Letter__c(
Name = 'XYZ',
SomePicklist__c = 'Closed',
SomeDate__c = Date.parse('2022-09-15'),
IsActive__c = true
);
It's pretty fragile, as you probably already know. And because parsing CSV is an art - I expect it to absolutely crash and burn when text with commas in it shows up (some text,"text, with commas in it, should be quoted",more text).
In theory admin can change mapping in setup - but then they'd need to add new field anyway to the loaded file. Overcomplicated. I guess somebody did it to solve issue with Record Type Ids - but there are better ways to achieve that and still have normal CSV file with normal columns and strong type matching, not just chucking everything in as strings.
In theory this lets you have "jagged" csv files (row 1 having 5 fields, row 2 having different record type and 17 fields? no problem)
Your call whether it's salvageable or you'd rather ditch it and try normal loading of QMB_Initial_Letter__c records. (get back to your business people and ask for requirements?) If you do have variable number of columns at source - you'd need to standardise it or group the data so only 1 "type" of records (well, whatever's in that "Field1__c") goes into each file.

Add formhandler field data to subject

My goal is to have the Formhandler log UID inside the Admin emails subject.
Inside of my email template I'm using
###value_tx_formhandler_log_inserted_uid### to insert a unique id.
I need to get this value into my Admin emails subject. E.g.
"Order ID: ###value_tx_formhandler_log_inserted_uid###"
I've read various forum posts, each do something different and I ended up with this snippet:
plugin.Tx_Formhandler.settings.predef.form {
# TEMPLATE MARKERS
name = Form1
templateFile = typo3template/typo3/ext/formhandler/form1/default.html
markers {
name = TEXT
name.value = Form1
}
finishers {
1.config {
class = Tx_Formhandler_Finisher_Mail
subject = TEXT
subject.value = ###GP:tx_formhandler_log_inserted_uid###
}
}
[...]
which just yields "{$formhandler.admin.subject}" as the subject.
I also tried other variations like
###LLL:tx_formhandler_log_inserted_uid### or tx_formhandler_log_inserted_uid
The backend field "subject" is empty.
Pasting the HTML placeholder into the backend field didn't work either.
I can't get this to work.
In what way can you access the id you want to insert?
From the notation GP:tx_formhandler_log_inserted_uid I would assume a GET/POST value.
For using this value in typoscript you need to do it like this (or similar: dataWrap):
subject = TEXT
subject.data = GP:tx_formhandler_log_inserted_uid
subject.noTrimWrap = |Order ID: ||
The notation LLL:tx_formhandler_log_inserted_uid would be a language specific text (you would also insert by .data) but it would be a static text for each language.
After a lot of trial and error, I got it working.
First of all, I forgot to specify that I want to configure the admin mail.
Adding admin { fixed the problem of getting only {$formhandler.admin.subject}.
The UID value itself can be accessed with GP:formhandler|tx_formhandler_log_inserted_uid
I combined that with the noTrimWrap as suggested by #bernd-wilke-πφ
The final snippet looks like this:
finishers {
1 {
class = Tx_Formhandler_Finisher_Mail
config {
admin {
subject = TEXT
subject.data = GP:formhandler|tx_formhandler_log_inserted_uid
subject.noTrimWrap = |Order number: ||
}
}
}
}

TYPO3 formhandler update-table in finisher_db without uid?

I'm using TYPO3 6.2.x with fe-login and formhandler. I created a form, where you can register a new fe-user.
I want to have a 'complete user registration' for,m where the user inputs the username the password and a doi-code for verification.
I thought if formhandler has a finisher-db supporting saltedpassword, it has to have a validator (database -> equalsField -> saltedpassword) as well. But I can't find any.
Something like:
validators {
1.class = Validator_Default
1.config {
fieldConf {
password.errorCheck {
1 = required
2 = saltedpassword <-- does not exist
3 = isInDBTable
3 {
table = fe_users
field = password
#or maybe: special = password ?
showHidden = 1
}
}
}
}
}
So I need help here, please.
//Update 2015-08-31
I got rid of the password field in the formhandler to seperate finish-registration and login as #Jost mentioned.
Now I have a more sincere problem:
I now have a formhandler form where the user is asked to input his email-address and the doi-code. I wanted to use the finisher_db for updating the user in the db. But the update of formhandler-finisher requires the uid of the element to update. Of course I don't have the uid at this state. Is there another way to use the native formhandler finishers?
If not, can someone please give me a heads up of how to write your own finisher for this purpose?

Where is my num_rows failing?

<?php
$link = mysqli_connect('localhost','root','root');
$link->query('CREATE DATABASE IF NOT EXISTS users');
$link->Select_db('users');
$sql='SELECT id FROM users WHERE email = '.$useremail.' AND username = '.$username;
$results = $link->query($sql);
$numrows = $results->num_rows;
if ($numrows == 1) {
#update user information
} else {
#failed to update
}
?>
It only works part of the time, and i'm not able to nail down an error from it one way or the other. I can confirm that the error pops up on the $numrows=$results->num_rows; line, but as for why, i'm lost. Occasionally it will work as intended, so any and all advice on what i can do to fix it, or at least helping me understand it better is greatly appreciated. Thanks!
Use Double Quotation for query and varchar/string pass with single quotation
$sql="SELECT id FROM users WHERE email = '".$useremail."' AND username = '".$username."'";
$results = $link->query($sql);
$numrows = $results->num_rows();
The reason that your call to num_rows generated an error is that your query had an error, and query() returned false instead of a valid result resource. Because it's a fatal error to try to call a method on a false value, you should always check the return value of query() before using it. Example:
if (!($result = $link->query($sql))) {
die($link->error);
}
Problems with your query:
You create a database named users and make that the default database, then you run a SELECT query from a table named users. There would be no tables in a database you have just created. In SQL, we use SELECT against tables, not databases (these are two different things, analogous to files contained in a directory on a filesystem).
You don't quote the string arguments in your SQL statement. For example, this SQL would be an error:
SELECT id FROM users WHERE email = bill#example.com AND username = bill
It should be this instead:
SELECT id FROM users WHERE email = 'bill#example.com' AND username = 'bill'
I know the quotes get confusing, because you have PHP string quotes and then SQL string quotes, but here are several ways of accomplishing it:
$sql='SELECT id FROM users WHERE email = \''.$useremail.'\' AND username = \''.$username.'\'';
$sql="SELECT id FROM users WHERE email = '".$useremail."' AND username = '".$username."'";
$sql="SELECT id FROM users WHERE email = '{$useremail}' AND username = '{$username}'";
I'm not sure if you have protected your PHP variables appropriately. You must never interpolate PHP variables into SQL strings unless you have escaped the content of the variables.
$useremail_esc = $link->real_escape_string($useremail);
$username_esc = $link->real_escape_string($username);
$sql="SELECT id FROM users WHERE email = '{$useremail_esc}' AND username = '{$username_esc}'";
But it would be better to use prepared statements with parameter placeholders. This is easier to use than escaping variables, and it's more reliable. Here's an example:
$sql="SELECT id FROM users WHERE email = ? AND username = ?";
$stmt = $link->prepare($sql);
$stmt->bind_param("ss", $useremail, $username);
$stmt->execute();
$result = $stmt->get_result();
Notice that you don't use escaping when you use parameters, and you don't put SQL quotes around the ? placeholders.

Google Apps Script - Automated Email Based on Cell Value

I'm a total noob when it comes to working with scripts and I'm looking for some help with one that I borrowed and modified to work with my spreadsheet.
I am looking for the value "Need to Order" in column H that will then cause an email to be sent out to a recipient. The only problem I'm having is that every time a value in that column is changed and my "Need to Order" text is present in one of the other cells in the column, an email gets sent out and my inbox gets flooded. Can someone help me tweak it so that it doesn't generate an email if any of the other cells in the column already have the "Need to Order" value present?
Thanks for any help you can afford.
Here's what I'm working with:
function sendEmail(email_address, email_subject, email_message) {
var status = ScriptProperties.getProperty('AlertStatus')+"";
var value = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Vehicle Inventory").getRange( "H2:H100").getValues().toString();
if (value.match("Need to Order" )&&status.match("")) {
ScriptProperties.setProperty('AlertStatus', '')
MailApp.sendEmail('username#gmail.com', 'Need to Order', 'Order more equipment. Open the current version of your Google Document "test spreadsheet": ');
}
else {
if (!value.match("Need to Order" ))
ScriptProperties.setProperty('AlertStatus', '')
}
}​
How about changing:
var value = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Vehicle Inventory").getRange( "H2:H100").getValues().toString();
to
var value = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Vehicle Inventory").getActiveCell().getValue().toString();
This way you inspect the current cell where the cursor is on and not the entire column.