Send reports automatically via email openerp - odoo

Odoo has the Reporting part and I was wondering how (if its even possible) to send reports via mail (and create an automated action for it)?
Let's say we have to crm.phonecall.report model, how to take it's information and use it in an email template? I tried making an email template with that model and then add the same xml text as it is in the Phonecall Analysis, but that didn't work. So all the help is really appreciated.

Following code will be enough to fulfill your mentioned requirements. It calls the email template and then attached a report attachment and finally send an email.
email = email_obj.browse(cr, uid, template_id)
attachment_obj = self.pool.get('ir.attachment')
ir_actions_report = self.pool.get('ir.actions.report.xml')
matching_reports = ir_actions_report.search(
cr, uid, [('name', '=', 'Report_Name_here')])
if matching_reports:
report = ir_actions_report.browse(cr, uid, matching_reports[0])
report_service = 'report.' + report.report_name
service = netsvc.LocalService(report_service)
(result, format) = service.create(
cr, uid, mrp_ids, {'model': self._name, 'start_date': start, 'end_date': end}, context=context)
if not report.attachment:
file_name = "Production Sale Report " + datetime.strftime(datetime.now().date(), "%Y-%m-%d") + ".pdf"
attachment_id = attachment_obj.create(cr, uid,
{
'name': file_name,
'datas': result,
'datas_fname': file_name,
'type': 'binary'
}, context=context)
email_obj.write(cr, uid, template_id, {'email_from': email.email_from,
'email_to': email.email_to,
'subject': email.subject,
'body_html': email.body_html,
'email_recipients': email.email_recipients,
'attachment_ids': [(6, 0, [attachment_id])],
})
email_obj.send_mail(cr, uid, template_id, False, True, context=context)
Hope this will solve your problem. Cheers

Related

Odoo validate invoice from code

I creating an invoice from another model, and want to get validated not draft
But internal number and total are not generated with my code.
invoice_id = self.pool.get('account.invoice').create(cr, uid,{
'partner_id':self.supplier.id,
'name' : 'Faltante mercaderia',
'journal_id': journal_id,
'account_id':account_id,
'type': 'in_refund',
})
self.pool.get('account.invoice.line').create(cr, uid,{
'invoice_id' : invoice_id,
'name' : 'Faltante mercaderia %s: %s' %(self.type,self.number),
'quantity' : self.dif_final,
'price_unit':self.tarifa_dif / 1000,
})
a = self.env['account.invoice'].browse([invoice_id])
a.invoice_validate()
I also try adding a.action_number()
This code should work for you:
inv_obj = self.pool.get('account.invoice')
inv_obj.button_compute(cr, uid, [invoice_id], context=context, set_total=True)
inv_obj.action_date_assign(cr, uid, invoice_id, context=context)
inv_obj.action_move_create(cr, uid, invoice_id, context=context)
inv_obj.action_number(cr, uid, invoice_id, context=context)
inv_obj.invoice_validate(cr, uid, invoice_id, context=context)
You can check by calling all above methods and let me know.
validate button sends a signal to a workflow, you just need to send the same signal:
a.signal_workflow('invoice_open')

Confirm a sale quotation into a sale order with some quantities set to 0

In my custom sale quotation report I want to show some products with a 0 quantity and therefore have created sale order lines for some products with their quantities set to 0. It works fine and shows in the sale quotation report.
But when I confirm that same sale quotation into a sale order OpenERP throws the following message:
"Data Insufficient !
Please check the quantity in procurement order(s), it should not be 0 or less!"
How can I confirm an order with some quantities set to 0?
First you have to inherit the Procurement and then override the action_confirm method in your custom module.
In procurement.py, find "def action_confirm()" on line: 320. Copy and past the whole method and remove those lines which raise the exception.
Hope this will solve your problem.
Thank You.
class procurement_order(osv.osv):
_inherit = 'procurement.order'
def action_confirm(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
for procurement in self.browse(cr, uid, ids, context=context):
#if procurement.product_qty <= 0.00:
#raise osv.except_osv(_('Data Insufficient !'),_('Please check the quantity in procurement order(s), it should not be 0 or less!'))
if procurement.product_id.type in ('product', 'consu'):
if not procurement.move_id:
source = procurement.location_id.id
if procurement.procure_method == 'make_to_order':
source = procurement.product_id.product_tmpl_id.property_stock_procurement.id
id = move_obj.create(cr, uid, {
'name': procurement.name,
'location_id': source,
'location_dest_id': procurement.location_id.id,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,
'product_uom': procurement.product_uom.id,
'date_expected': procurement.date_planned,
'state': 'draft',
'company_id': procurement.company_id.id,
'auto_validate': True,
})
move_obj.action_confirm(cr, uid, [id], context=context)
self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
return True

Messaging System of Openerp v7

Can anyone share how I can change the "from" field value when sending a message because it always has the same email address?
--the address of the outgoing mail server I configure.
You can even send mail without making use of email template.
You can use mail.message & mail.mail objects.
def send_mail(cr, uid, ids, context=context):
mail_server_obj = self.pool.get('ir.mail_server')
mail_message_obj = self.pool.get('mail.message')
mail_mail_obj = self.pool.get('mail.mail')
for id in ids:
mail_message_id = mail_message_obj.create(cr, uid, {'email_from': 'from_add', 'model': 'model_name', 'res_id': id, 'subject': 'subject_name', 'body': 'your_html_body'}, context=context)
mail_server_ids = mail_server_obj.search(cr, uid, [], context=context)
mail_mail_id = mail_mail_obj.create(cr, uid, {'mail_message_id': mail_message_id, 'mail_server_id': mail_server_ids and mail_server_ids[0], 'state': 'outgoing', 'email_from': 'from_add', 'email_to': 'to_add', 'body_html': 'your_html_body'}, context=context)
if mail_mail_id:
mail_mail_obj.send(cr, uid, [mail_mail_id], context=context)
return True
There are many ways of sending mails. The good way is by creating a email template.
First create one email template.
def send_email(self, cr, uid, ids, context=None):
email_template_obj = self.pool.get('email.template')
template_ids = email_template_obj.search(cr, uid, [('model_id.model', '=', 'sale.order')])
if template_ids:
for id in ids:
values = email_template_obj.generate_email(cr, uid, template_ids[0], id, context=context)
print "values:: ", values
values['subject'] = your_subject
values['email_to'] = your_mail_to_address
values['email_cc'] = your_cc_address
values['body_html'] = your_body_html_part
values['body'] = your_body_html_part
mail_mail_obj = self.pool.get('mail.mail')
msg_id = mail_mail_obj.create(cr, uid, values, context=context)
if msg_id:
mail_mail_obj.send(cr, uid, [msg_id], context=context)
return True
Hope this will solve your problem.
Thank you.
Change your email preference from the top right menu showing your login.

Openerp Comparing another object field value with an object field

I have this:
class events_places(osv.osv):
"""Places for events"""
_name = 'oevents.places'
_columns = {
'name': fields.char('Name',size=35, help='Place\'s name', required = True),
'description': fields.char('Description',size=50, help='Place\'s description'),
'street': fields.char('Street',size=35, help='Place\'s street', required = True),
'number': fields.integer('Local number', help='Place\'s local number', required = True),
'zip': fields.char('Zip Code', size=5, help='Place\'s Zip code', required = True),
'city': fields.char('City',size=20, help='Place\'s city', required = True),
'country': fields.many2one('res.country', 'Country', help='Place\'s country'),
'state': fields.many2one('res.country.state','State', help='Place\'s state'),
'inWinter': fields.boolean('Active in winter', store = True, help='Place\'s province'),
}
_defaults = {
'inWinter' : True,
}
class events_events(osv.osv):
"""Client's contacts"""
_name = 'oevents.events'
_columns = {
'name': fields.char('Name',size=20, help='Event\'s name', required = True),
'place': fields.many2one('oevents.places','Place', help='Event\'s location', required = True),
'artist': fields.many2one('oevents.artists','Artist', help='Artist\'s performing in the event.', required = True),
'client': fields.many2one('res.partner','Client', help='Event\'s clients.', required = True),
'date': fields.date('Date', help='Event\'s date.', required = True),
'type': fields.selection([('children','Children\'s'),('private','Private'),('concert','Concert')],'Event type', help='Type of event this artist can do'),
}
_defaults = {
'type' : 'private'
}
When I want to create an event, there's a place related field. The event has a date, but it shouldn't let me create the event in a a winter date if the related place field in the event has the field inWinter unchecked.
How can I do that? I need to create a function or constraint which gets place inWinter field and compare it with the date, but I don't know how to do it. Any suggestions?
Thanks in advance!
You can override create & write method. In those methods just check whether "inWinter" is True or False.
def create() method will be called when new record will be created.
def create(self, cr, uid, vals, context=None):
if vals.get('place'):
event_brw = self.pool.get('oevents.places').browse(cr, uid, vals.get('place'), context=context)
#if inWinter is True
if event_brw.inWinter:
raise osv.except_osv('Error ! ', 'You can not create an event in winter.')
return super(oevents_events, self).create(cr, uid, vals, context)
def write() method will be called when record will be modified.
def write(self, cr, uid, ids, vals, context=None):
if vals.get('place'):
event_brw = self.pool.get('oevents.places').browse(cr, uid, vals.get('place'), context=context)
#if inWinter is True
if event_brw.inWinter:
raise osv.except_osv('Error ! ', 'You can not create an event in winter.')
return super(oevents_events, self).write(cr, uid, ids, vals, context)
you have to write an on_change function on 'date' field, where you raise an error if given date is in winter months and isWinter is false.
Of course, yo have to define range date for iswinter an put on_change in field definition in your xml view.
you should use constraints. grep addons folder for _constraints and _sql_contraints and you'll find a lot of examples.
Go for _constraints= , Is not at all good idea to call create and write.

Run a report from a wizard

I have a wizard with a button. On button action I want to run a report and leave the PDF on the server. I have the above code fragment that creates a report with web service. But in a wizard context I have normally only the uid (I think).
What will be the equivalent way to get the report to disk in a wizard ?
def reportToDisk(self, cr, uid, ids, context=None):
dbname = 'db'
username = 'user'
pwd = 'pass'
model = 'sale.order'
report_name = 'doc.sale'
sock_common = xmlrpclib.ServerProxy ('http://localhost:8069/xmlrpc/common')
uid = sock_common.login(dbname, username, pwd)
sock = xmlrpclib.ServerProxy ('http://localhost:8069/xmlrpc/object')
ids = sock.execute(dbname, uid, pwd, model, 'search',[])[0:1]
sock_report = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/report')
id_report = sock_report.report(
dbname, uid, pwd, report_name, ids,{'model': model, 'id': ids[0], 'report_type':'pdf'}
)
cont = True
while cont:
report = sock_report.report_get(dbname, uid, pwd, id_report)
cont = not report['state']
string_pdf = base64.decodestring(report['result'])
file_pdf = open('/home/arch-in/file.pdf','w')
file_pdf.write(string_pdf)
file_pdf.close()
Return the report action on your button click(It can be wizard button or view button, it just works with button click return) like following:
def btn_clik_action(self, cr, uid, ids, context=None):
if context == None:
context = {}
value = {
'type': 'ir.actions.report.xml',
'report_name':'report.name.(servicename)',
'datas': {
'model':'model.name',
'id': ids and ids[0] or False,
'ids': ids and ids or [],
'report_type': 'pdf'
},
'nodestroy': True
}
Just returning the report action will give you file of the report which basically you don't need to write or anything.
Thank YOu