Odoo - Function to get data / value when we open a specific menu - python

Is there any function that can be used to get and check the data every time a specified menu is loaded/opened?
I have 1 field in the appointment module (time). What I want is when I open the appointment menu, a function will try to get/check all the data in appointment, then later the time field will be filled in according to the code I have made. So every time I open the appointments menu, odoo will check the existing data, and the time field data can be updated.
#api.model
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
res = super(MyMenu, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
data = self.env['appointment.appointment'].search([])
for record in data:
 app = self.env['appointment.time'].search([('time1','<=',record.time),('time2','>=',record.time)], limit=1)
if duration:
record.time_final= app.name + "o'clock"
return res
I have tried the code above, but it only runs 1 time (when I restarted the odoo server).

Related

Update database when CSV file is updated

I have data on a CSV file that I have imported into the DB, and display the data into my index.html as a HTML table.
The CSV is updated frequently
Is there anyway to update the data in the DB from the CSV file every hour or day, or even every time the file is updated?
PS: As I'm new to Django, what I do now is that I delete the whole DB and than migrate and import the file again, and I don't think that is a good way to do it.
According to your requirements, you can write a management command and schedule a job using cron every hour or every day.
here is a link to read more about How to create custom django-admin commands
def dummyfunc():
tests = TEST.objects.filter(parameter = parameter)
if tests.exist():
test = tests[0]
test.field = file_name
test.save()
else:
test = Test.objects.create(
field = field_name
)
test.save()
return test

How to add a hidden field value to QSqlRelationalTableModel during row creation?

I'm starting out with PyQt5. I've created a simple password management app that has a login page and a password listing page against various URLs. I'm unable to find a way to add the user_id value to the record with QSqlRelationalTableModel before it gets inserted into the DB. This is what I've done so far. Code examples would help me. Thanks.
self.model.beforeInsert.connect(self.beforeInsert)
def addRecord(self):
"""
Add a new record to the last row of the table.
"""
last_row = self.model.rowCount()
self.model.insertRow(last_row)
def beforeInsert(self, record):
print("[INFO] beforeInsert called", record)
record.setValue("user_id", 1)
done = self.model.insertRecord(-1, record)
# done is False at this point, however record.value("user_id") is 1

web2py: How to execute instructions before delete using SQLFORM.smartgrid

I use SQLFORM.smartgrid to show a list of records from a table (service_types). In each row of the smartgrid there is a delete link/button to delete the record. I want to executive some code before smartgrid/web2py actually deletes the record, for example I want to know if there are child records (services table) referencing this record, and if any, flash a message telling user that record cannot be deleted. How is this done?
db.py
db.define_table('service_types',
Field('type_name', requires=[IS_NOT_EMPTY(), IS_ALPHANUMERIC()]),
format='%(type_name)s',
)
db.define_table('services',
Field('service_name',requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB(db,'services.service_name')]),
Field('service_type','reference service_types',requires=IS_IN_DB(db,db.service_types.id,
'%(type_name)s',
error_message='not in table',
zero=None),
ondelete='RESTRICT',
),
Field('interest_rate','decimal(15,2)',requires=IS_DECIMAL_IN_RANGE(0,100)),
Field('max_term','integer'),
auth.signature,
format='%(service_name)s',
)
db.services._plural='Services'
db.services._singular='Service'
if db(db.service_types).count() < 1:
db.service_types.insert(type_name='Loan')
db.service_types.insert(type_name='Contribution')
db.service_types.insert(type_name='Other')
controller
def list_services():
grid = SQLFORM.smartgrid(db.services
, fields = [db.services.service_name,db.services.service_type]
)
return locals()
view
{{extend 'layout.html'}}
{{=grid}}
There are two options. First, the deletable argument can be a function that takes the Row object of a given record and returns True or False to indicate whether the record is deletable. If it returns False, the "Delete" button will not be shown for that record, nor the delete operation be allowed on the server.
def can_delete(row):
return True if [some condition involving row] else False
grid = SQLFORM.smartgrid(..., deletable=can_delete)
Second, there is an ondelete argument that takes the db Table object and the record ID. It is called right before the delete operation, so to prevent the delete, you can do a redirect within that function:
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
session.flash = 'Cannot delete this record'
redirect(URL())
grid = SQLFORM.smartgrid(..., ondelete=ondelete)
Note, if the grid is loaded via an Ajax component and its actions are therefore performed via Ajax, using redirect within the ondelete method as shown above will not work well, as the redirect will have no effect and the table row will still be deleted from the grid in the browser (even though the database record was not deleted). In that case, an alternative approach is to return a non-200 HTTP response to the browser, which will prevent the client-side Javascript from deleting the row from the table (the delete happens only on success of the Ajax request). We should also set response.flash instead of session.flash (because we are not redirecting/reloading the whole page):
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
response.flash = 'Cannot delete this record'
raise HTTP(403)
Note, both the deletable and ondelete arguments can be dictionaries with table names as keys, so you can specify different values for different tables that might be linked from the smartgrid.
Finally, notice the delete URLs look like /appname/list_services/services/delete/services/[record ID]. So, in the controller, you can determine if a delete is being requested by checking if 'delete' in request.args. In that case, request.args[-2:] represents the table name and record ID, which you can use to do any checks.
From Anthony's answer I chose the second option and came up with the following:
def ondelete_service_type(service_type_table, service_type_id):
count = db(db.services.service_type == service_type_id).count()
if count > 0:
session.flash = T("Cant delete")
#redirect(URL('default','list_service_types#'))
else:
pass
return locals()
def list_service_types():
grid = SQLFORM.smartgrid(db.service_types
, fields = [db.service_types.type_name, db.services.service_name]
, ondelete = ondelete_service_type
)
return locals()
But, if I do this...
if count > 0:
session.flash = T("Cant delete")
else:
pass
return locals()
I get this error:
And if I do this:
if count > 0:
session.flash = T("Cant delete")
redirect(URL('default','list_service_types#')) <== please take note
else:
pass
return locals()
I get the flash error message Cant delete but the record appears deleted from the list, and reappears after a page refresh with F5 (apparently because the delete was not allowed in the database, which is intended).
Which one should I fix and how?
Note
If any of these issue is resolved I can accept Anthony's answer.

Python telegram-bot: Prompt for another input

I have a bot in Python that prompts the user to pick from a list of IDs to change and the idea is that the user will select the ID and then supply the ID they want to change to.
Here is my code:
def build_menu(buttons, n_cols):
menu = [buttons[i:i + n_cols] for i in range(0, len(buttons), n_cols)]
return menu
def change_process(bot, update):
global action
query = update.callback_query
NAME = query.data
if action == 'Change':
# Prompt user for new value
# run sql query to update
def change(bot, update, args):
global action
action = 'Change'
sql = sqlite3.connect('SQL_FILE.db',detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cur = sql.cursor()
button_list = [InlineKeyboardButton(s[0], callback_data=s[0]) for s in cur.execute('SELECT Name FROM ID ORDER BY Name ASC')]
reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=3))
update.message.reply_text('ID to change:', reply_markup=reply_markup)
action = None
updater = Updater(token='XXXX:XXXX')
dispatcher = updater.dispatcher
dispatcher.add_handler(CallbackQueryHandler(change_process))
arg_handler = CommandHandler('change', change, pass_args=True)
dispatcher.add_handler(arg_handler)
Here is how I want the program to work:
User runs /change
Bot returns list of IDs that are able to be changed (using InlineKeyboardMarkup() and build_menu()
User picks one of the ids
Bot prompts user for new value
The next message that the user sends to the bot will be the value to use
Bot will use the ID the user selected as well as new value and run query to update in database
Bot comments that it updated ID with new value of 'USER VALUE'
The problem I am having is that I can prompt the user to pick the ID and I can prompt the user for input, but I do not know how to do both and use both values in a single function.
I believe you need to look to conversation examples that python-telegram-bot library provides:
conversationbot.py
conversationbot2.py
nestedconversationbot.py
There are also diagrams that explains the flow of asking data from user.

Get author_id from mail_message in openERP

I'm trying to get a field from openERPs mail_message model using python code which is executed in a server action (so its not a module where I can debug! I cannot even print in this state) (when a new eMail is being fetched) but I am unable to get anything useful from it.
Basicly when someone is throwing me a email, a new Task is created by openERP. But the newely created ticket is not connected to the user which send me the mail.
When a new email is fetched, this server action gets executed.
In a table called mail_message you can then find the email (+ author_id, + email, + res_id (which is the id of the created Task), therefore I'd like to fetch the author_id from that table.
(A query would look like this:
SELECT author_id FROM mail_message WHERE type = 'email' AND res_id = '<Task.id>')
This is my current code
#Initialize object. That one points to the mail_message model.
mailMessage_obj = self.pool.get('mail.message')
#Created Id in project_task
myId = object.id
#browse whole object with that id
#message = mailMessage_obj.browse(cr,uid,[myId])
#Select field where
messageIds = mailMessage_obj.search(cr,uid,[('type','=','email'),('res_id','=',myId)],context=context)
if messageIds:
#messageRecord = mailMessage_obj.browse(cr,uid,[myId],context=context)
#object.write({'partner_id':messageRecord.author_id.id})
res = mailMessage_obj.read(messageIds, ['author_id'])
partnerId = res[0]
#Author id
#partnerId = message[0]['author_id']
#partnerId = message.author_id
#res = [(r['id'], r['author_id']) for r in messageRecord]
#partnerId = res
#partnerId = 259866
object.write({'partner_id':partnerId})
I dont know how to get my hands on the author_id properly. If I hardcode a ID and let it write to the database (last two lines) It'll work just fine, but I cant hardcode a users id. ;)
Could someone explain to me how its done correctly?
I dont know whether I should use .browse or .read or something else..
I think you have an error on you python method.
you wrote :
res = mailMessage_obj.read(messageIds, ['author_id'])
partnerId = res[0]
But read() method returns here a list of dict (because messageIds is a list). Then, you have not specified the field you wanted to retrieve from res variable, and finally, as author_id is a many2one, it returns something like this : (2, 'myusers').
You should have done :
res = mailMessage_obj.read(cr, uid, messageIds, ['author_id'])
partnerId = res[0]['author_id'][0]
Hope i helped you,
Greatings

Categories

Resources