# -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 OpenERP S.A. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ############################################################################## """ Module to handle publisher warranty contracts as well as notifications from OpenERP. """ import datetime import logging import sys import urllib import urllib2 import pooler import release from osv import osv, fields from tools.translate import _ from tools.safe_eval import safe_eval from tools.config import config from tools import misc _logger = logging.getLogger(__name__) """ Time interval that will be used to determine up to which date we will check the logs to see if a message we just received was already logged. @type: datetime.timedelta """ _PREVIOUS_LOG_CHECK = datetime.timedelta(days=365) class publisher_warranty_contract(osv.osv): """ Osv representing a publisher warranty contract. """ _name = "publisher_warranty.contract" def _get_valid_contracts(self, cr, uid): """ Return the list of the valid contracts encoded in the system. @return: A list of contracts @rtype: list of publisher_warranty.contract browse records """ return [contract for contract in self.browse(cr, uid, self.search(cr, uid, [])) if contract.state == 'valid'] def status(self, cr, uid): """ Method called by the client to check availability of publisher warranty contract. """ contracts = self._get_valid_contracts(cr, uid) return { 'status': "full" if contracts else "none" , 'uncovered_modules': list(), } def send(self, cr, uid, tb, explanations, remarks=None, issue_name=None): """ Method called by the client to send a problem to the publisher warranty server. """ if not remarks: remarks = "" valid_contracts = self._get_valid_contracts(cr, uid) valid_contract = valid_contracts[0] try: origin = 'client' dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') db_create_date = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date') user = self.pool.get("res.users").browse(cr, uid, uid) user_name = user.name email = user.user_email msg = {'contract_name': valid_contract.name, 'tb': tb, 'explanations': explanations, 'remarks': remarks, 'origin': origin, 'dbname': cr.dbname, 'dbuuid': dbuuid, 'db_create_date': db_create_date, 'issue_name': issue_name, 'email': email, 'user_name': user_name, } add_arg = {"timeout":30} if sys.version_info >= (2,6) else {} uo = urllib2.urlopen(config.get("publisher_warranty_url"), urllib.urlencode({'arg0': msg, "action": "send",}),**add_arg) try: submit_result = uo.read() finally: uo.close() result = safe_eval(submit_result) crm_case_id = result if not crm_case_id: return False except osv.except_osv: raise except Exception: _logger.warning("Error sending problem report", exc_info=1) raise osv.except_osv(_("Error"), _("Error during communication with the publisher warranty server.")) return True def check_validity(self, cr, uid, ids, context=None): """ Check the validity of a publisher warranty contract. This method just call get_logs() but checks some more things, so it can be called from a user interface. """ contract_id = ids[0] contract = self.browse(cr, uid, contract_id) state = contract.state validated = state != "unvalidated" self.get_logs(cr, uid, ids, cron_mode=False, context=context) contract = self.browse(cr, uid, contract_id) validated2 = contract.state != "unvalidated" if not validated and not validated2: raise osv.except_osv(_("Contract validation error"), _("Please verify your publisher warranty serial number and validity.")) return True def get_logs(self, cr, uid, ids, cron_mode=True, context=None): """ Send a message to OpenERP's publisher warranty server to check the validity of the contracts, get notifications, etc... @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). @type cron_mode: boolean """ try: try: result = get_sys_logs(cr, uid) except Exception: if cron_mode: # we don't want to see any stack trace in cron return False _logger.debug("Exception while sending a get logs messages", exc_info=1) raise osv.except_osv(_("Error"), _("Error during communication with the publisher warranty server.")) contracts = result["contracts"] for contract in contracts: c_id = self.search(cr, uid, [("name","=",contract)])[0] # for backward compatibility if type(contracts[contract]) == tuple: self.write(cr, uid, c_id, { "date_start": contracts[contract][0], "date_stop": contracts[contract][1], "state": contracts[contract][2], "check_support": False, "check_opw": False, "kind": "", }) else: self.write(cr, uid, c_id, { "date_start": contracts[contract]["date_from"], "date_stop": contracts[contract]["date_to"], "state": contracts[contract]["state"], "check_support": contracts[contract]["check_support"], "check_opw": contracts[contract]["check_opw"], "kind": contracts[contract]["kind"], }) limit_date = (datetime.datetime.now() - _PREVIOUS_LOG_CHECK).strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT) for message in result["messages"]: ids = self.pool.get("res.log").search(cr, uid, [("res_model", "=", "publisher_warranty.contract"), ("create_date", ">=", limit_date), ("name", "=", message)]) if ids: continue self.pool.get('res.log').create(cr, uid, { 'name': message, 'res_model': "publisher_warranty.contract", "read": True, "user_id": False, }, context=context ) except Exception: if cron_mode: return False # we don't want to see any stack trace in cron else: raise return True def get_last_user_messages(self, cr, uid, limit, context=None): """ Get the messages to be written in the web client. @return: A list of html messages with ids, can be False or empty. @rtype: list of tuples(int,string) """ ids = self.pool.get('res.log').search(cr, uid, [("res_model", "=", "publisher_warranty.contract")] , order="create_date desc", limit=limit) if not ids: return [] messages = [(x.id, x.name) for x in self.pool.get('res.log').browse(cr, uid, ids)] return messages def del_user_message(self, cr, uid, id, context=None): """ Delete a message. """ self.pool.get('res.log').unlink(cr, uid, [id]) return True _columns = { 'name' : fields.char('Serial Key', size=384, required=True, help="Your OpenERP Publisher's Warranty Contract unique key, also called serial number."), 'date_start' : fields.date('Starting Date', readonly=True), 'date_stop' : fields.date('Ending Date', readonly=True), 'state' : fields.selection([('unvalidated', 'Unvalidated'), ('valid', 'Valid') , ('terminated', 'Terminated'), ('canceled', 'Canceled')], string="State", readonly=True), 'kind' : fields.char('Kind', size=64, readonly=True), "check_support": fields.boolean("Support Level 1", readonly=True), "check_opw": fields.boolean("OPW", readonly=True, help="Checked if this is an OpenERP Publisher's Warranty contract (versus older contract types"), } _defaults = { 'state': 'unvalidated', } _sql_constraints = [ ('uniq_name', 'unique(name)', "That contract is already registered in the system.") ] publisher_warranty_contract() class maintenance_contract(osv.osv_memory): """ Old osv we only keep for compatibility with the clients. """ _name = "maintenance.contract" def status(self, cr, uid): return self.pool.get("publisher_warranty.contract").status(cr, uid) def send(self, cr, uid, tb, explanations, remarks=None, issue_name=None): return self.pool.get("publisher_warranty.contract").send(cr, uid, tb, explanations, remarks, issue_name) maintenance_contract() class publisher_warranty_contract_wizard(osv.osv_memory): """ A wizard osv to help people entering a publisher warranty contract. """ _name = 'publisher_warranty.contract.wizard' _inherit = "ir.wizard.screen" _columns = { 'name' : fields.char('Serial Key', size=256, required=True, help="Your OpenERP Publisher's Warranty Contract unique key, also called serial number."), 'state' : fields.selection([("draft", "Draft"), ("finished", "Finished")]) } _defaults = { "state": "draft", } def action_validate(self, cr, uid, ids, context=None): if not ids: return False wiz = self.browse(cr, uid, ids[0]) c_name = wiz.name contract_osv = self.pool.get("publisher_warranty.contract") contracts = contract_osv.search(cr, uid, [("name","=",c_name)]) if contracts: raise osv.except_osv(_("Error"), _("That contract is already registered in the system.")) contract_id = contract_osv.create(cr, uid, { "name": c_name, "state": "unvalidated", }) contract_osv.check_validity(cr, uid, [contract_id]) self.write(cr, uid, ids, {"state": "finished"}) # We should return an action ? return True publisher_warranty_contract_wizard() def get_sys_logs(cr, uid): """ Utility method to send a publisher warranty get logs messages. """ pool = pooler.get_pool(cr.dbname) dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') db_create_date = pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date') limit_date = datetime.datetime.now() limit_date = limit_date - datetime.timedelta(15) limit_date_str = limit_date.strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT) nbr_users = pool.get("res.users").search(cr, uid, [], count=True) nbr_active_users = pool.get("res.users").search(cr, uid, [("date", ">=", limit_date_str)], count=True) nbr_share_users = False nbr_active_share_users = False if "share" in pool.get("res.users")._all_columns: nbr_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True)], count=True) nbr_active_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True), ("date", ">=", limit_date_str)], count=True) contractosv = pool.get('publisher_warranty.contract') contracts = contractosv.browse(cr, uid, contractosv.search(cr, uid, [])) user = pool.get("res.users").browse(cr, uid, uid) msg = { "dbuuid": dbuuid, "nbr_users": nbr_users, "nbr_active_users": nbr_active_users, "nbr_share_users": nbr_share_users, "nbr_active_share_users": nbr_active_share_users, "dbname": cr.dbname, "db_create_date": db_create_date, "version": release.version, "contracts": [c.name for c in contracts], "language": user.context_lang, } add_arg = {"timeout":30} if sys.version_info >= (2,6) else {} arguments = {'arg0': msg, "action": "update",} arguments_raw = urllib.urlencode(arguments) url = config.get("publisher_warranty_url") uo = urllib2.urlopen(url, arguments_raw, **add_arg) try: submit_result = uo.read() finally: uo.close() result = safe_eval(submit_result) if submit_result else {} return result # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: