[IMP] Added possibility to get email and issue name when a user submit an
[odoo/odoo.git] / bin / addons / base / publisher_warranty / publisher_warranty.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 OpenERP S.A. (<http://www.openerp.com>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21 """
22 Module to handle publisher warranty contracts as well as notifications from
23 OpenERP.
24 """
25
26 import datetime
27 import logging
28 import sys
29 import urllib
30 import urllib2
31
32 import pooler
33 import release
34 from osv import osv, fields
35 from tools.translate import _
36 from tools.safe_eval import safe_eval
37 from tools.config import config
38 from tools import misc
39
40 _logger = logging.getLogger(__name__)
41
42 """
43 Time interval that will be used to determine up to which date we will
44 check the logs to see if a message we just received was already logged.
45 @type: datetime.timedelta
46 """
47 _PREVIOUS_LOG_CHECK = datetime.timedelta(days=365)
48
49 class publisher_warranty_contract(osv.osv):
50     """
51     Osv representing a publisher warranty contract.
52     """
53     _name = "publisher_warranty.contract"
54
55     def _get_valid_contracts(self, cr, uid):
56         """
57         Return the list of the valid contracts encoded in the system.
58         
59         @return: A list of contracts
60         @rtype: list of publisher_warranty.contract browse records
61         """
62         return [contract for contract in self.browse(cr, uid, self.search(cr, uid, []))
63                 if contract.state == 'valid']
64     
65     def status(self, cr, uid):
66         """ Method called by the client to check availability of publisher warranty contract. """
67         
68         contracts = self._get_valid_contracts(cr, uid)
69         return {
70             'status': "full" if contracts else "none" ,
71             'uncovered_modules': list(),
72         }
73     
74     def send(self, cr, uid, tb, explanations, remarks=None, issue_name=None, email=None):
75         """ Method called by the client to send a problem to the publisher warranty server. """
76         
77         if not remarks:
78             remarks = ""
79
80         valid_contracts = self._get_valid_contracts(cr, uid)
81         valid_contract = valid_contracts[0]
82         
83         try:
84             origin = 'client'
85             dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
86             db_create_date = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date')
87             
88             msg = {'contract_name': valid_contract.name,
89                 'tb': tb,
90                 'explanations': explanations,
91                 'remarks': remarks,
92                 'origin': origin,
93                 'dbname': cr.dbname,
94                 'dbuuid': dbuuid,
95                 'db_create_date': db_create_date,
96                 'issue_name': issue_name,
97                 'email': email,
98             }
99             
100             
101             add_arg = {"timeout":30} if sys.version_info >= (2,6) else {}
102             uo = urllib2.urlopen(config.get("publisher_warranty_url"),
103                                     urllib.urlencode({'arg0': msg, "action": "send",}),**add_arg)
104             try:
105                 submit_result = uo.read()
106             finally:
107                 uo.close()
108             
109             result = safe_eval(submit_result)
110             
111             crm_case_id = result
112             
113             if not crm_case_id:
114                 return False
115             
116         except osv.except_osv:
117             raise
118         except Exception:
119             _logger.warning("Error sending problem report", exc_info=1)
120             raise osv.except_osv("Connection error", "An error occured during the connection " +
121                                  "with the publisher warranty server.")
122         
123         return True
124     
125     def check_validity(self, cr, uid, ids, context=None):
126         """
127         Check the validity of a publisher warranty contract. This method just call get_logs() but checks
128         some more things, so it can be called from a user interface.
129         """
130         contract_id = ids[0]
131         contract = self.browse(cr, uid, contract_id)
132         state = contract.state
133         validated = state != "unvalidated"
134         
135         self.get_logs(cr, uid, ids, cron_mode=False, context=context)
136         
137         contract = self.browse(cr, uid, contract_id)
138         validated2 = contract.state != "unvalidated"
139         if not validated and not validated2:
140             raise osv.except_osv(_("Contract validation error"),
141                                  _("Please check your publisher warranty contract name and validity."))
142         return True
143     
144     def get_logs(self, cr, uid, ids, cron_mode=True, context=None):
145         """
146         Send a message to OpenERP's publisher warranty server to check the validity of
147         the contracts, get notifications, etc...
148         
149         @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron).
150         @type cron_mode: boolean
151         """
152         try:
153             try:
154                 result = get_sys_logs(cr, uid)
155             except Exception:
156                 if cron_mode: # we don't want to see any stack trace in cron
157                     return False 
158                 _logger.debug("Exception while sending a get logs messages", exc_info=1)
159                 raise osv.except_osv(_("Error"), _("Error during communication with the publisher warranty server."))
160
161             contracts = result["contracts"]
162             for contract in contracts:
163                 c_id = self.search(cr, uid, [("name","=",contract)])[0]
164                 date_from = contracts[contract][0]
165                 date_to = contracts[contract][1]
166                 state = contracts[contract][2]
167                 self.write(cr, uid, c_id, {
168                     "date_start": date_from,
169                     "date_stop": date_to,
170                     "state": state,
171                 })
172             
173             limit_date = (datetime.datetime.now() - _PREVIOUS_LOG_CHECK).strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT)
174             for message in result["messages"]:
175                 ids = self.pool.get("res.log").search(cr, uid, [("res_model", "=", "publisher_warranty.contract"),
176                                                           ("create_date", ">=", limit_date),
177                                                           ("name", "=", message)])
178                 if ids:
179                     continue
180                 self.pool.get('res.log').create(cr, uid,
181                         {
182                             'name': message,
183                             'res_model': "publisher_warranty.contract",
184                             "read": True,
185                             "user_id": False,
186                         },
187                         context=context
188                 )
189         except Exception:
190             if cron_mode:
191                 return False # we don't want to see any stack trace in cron
192             else:
193                 raise
194         return True
195     
196     def get_last_user_messages(self, cr, uid, limit, context=None):
197         """
198         Get the messages to be written in the web client.
199         @return: A list of html messages with ids, can be False or empty.
200         @rtype: list of tuples(int,string)
201         """
202         ids = self.pool.get('res.log').search(cr, uid, [("res_model", "=", "publisher_warranty.contract")]
203                                         , order="create_date desc", limit=limit)
204         if not ids:
205             return []
206         messages = [(x.id, x.name) for x in self.pool.get('res.log').browse(cr, uid, ids)]
207     
208         return messages
209     
210     def del_user_message(self, cr, uid, id, context=None):
211         """
212         Delete a message.
213         """
214         self.pool.get('res.log').unlink(cr, uid, [id])
215         
216         return True
217
218     _columns = {
219         'name' : fields.char('Serial Key', size=384, required=True),
220         'date_start' : fields.date('Starting Date', readonly=True),
221         'date_stop' : fields.date('Ending Date', readonly=True),
222         'state' : fields.selection([('unvalidated', 'Unvalidated'), ('valid', 'Valid')
223                             , ('terminated', 'Terminated'), ('canceled', 'Canceled')], string="State", readonly=True),
224         'kind' : fields.char('Kind', size=64, readonly=True),
225     }
226     
227     _defaults = {
228         'state': 'unvalidated',
229     }
230     
231     _sql_constraints = [
232         ('uniq_name', 'unique(name)', "Your publisher warranty contract is already subscribed in the system !")
233     ]
234
235 publisher_warranty_contract()
236
237 class maintenance_contract(osv.osv_memory):
238     """ Old osv we only keep for compatibility with the clients. """
239     
240     _name = "maintenance.contract"
241     
242     def status(self, cr, uid):
243         return self.pool.get("publisher_warranty.contract").status(cr, uid)
244         
245     def send(self, cr, uid, tb, explanations, remarks=None, issue_name=None, email=None):
246         return self.pool.get("publisher_warranty.contract").send(cr, uid, tb,
247                         explanations, remarks, issue_name, email)
248     
249 maintenance_contract()
250
251 class publisher_warranty_contract_wizard(osv.osv_memory):
252     """
253     A wizard osv to help people entering a publisher warranty contract.
254     """
255     _name = 'publisher_warranty.contract.wizard'
256     _inherit = "ir.wizard.screen"
257
258     _columns = {
259         'name' : fields.char('Serial Key', size=256, required=True ),
260         'state' : fields.selection([("draft", "Draft"), ("finished", "Finished")])
261     }
262     
263     _defaults = {
264         "state": "draft",
265     }
266
267     def action_validate(self, cr, uid, ids, context=None):
268         if not ids:
269             return False
270
271         wiz = self.browse(cr, uid, ids[0])
272         c_name = wiz.name
273         
274         contract_osv = self.pool.get("publisher_warranty.contract")
275         contracts = contract_osv.search(cr, uid, [("name","=",c_name)])
276         if contracts:
277             raise osv.except_osv(_("Error"), _("That contract is already registered in the system."))
278         
279         contract_id = contract_osv.create(cr, uid, {
280             "name": c_name,
281             "state": "unvalidated",
282         })
283         
284         contract_osv.check_validity(cr, uid, [contract_id])
285         
286         self.write(cr, uid, ids, {"state": "finished"})
287         
288         return True
289
290
291 publisher_warranty_contract_wizard()
292
293 def get_sys_logs(cr, uid):
294     """
295     Utility method to send a publisher warranty get logs messages.
296     """
297     pool = pooler.get_pool(cr.dbname)
298     
299     dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
300     db_create_date = pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date')
301     nbr_users = pool.get("res.users").search(cr, uid, [], count=True)
302     contractosv = pool.get('publisher_warranty.contract')
303     contracts = contractosv.browse(cr, uid, contractosv.search(cr, uid, []))
304     user = pool.get("res.users").browse(cr, uid, uid)
305     msg = {
306         "dbuuid": dbuuid,
307         "nbr_users": nbr_users,
308         "dbname": cr.dbname,
309         "db_create_date": db_create_date,
310         "version": release.version,
311         "contracts": [c.name for c in contracts],
312         "language": user.context_lang,
313     }
314     
315     add_arg = {"timeout":30} if sys.version_info >= (2,6) else {}
316     uo = urllib2.urlopen(config.get("publisher_warranty_url"),
317                         urllib.urlencode({'arg0': msg, "action": "update",}), **add_arg)
318     try:
319         submit_result = uo.read()
320     finally:
321         uo.close()
322     
323     result = safe_eval(submit_result)
324     
325     return result
326
327 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
328