Merge lp:~savoirfairelinux-openerp/openerp-accountedge/6.1-fix-email-addresses-notifications into lp:~openerp-accountedge/openerp-accountedge/6.1

Status: Merged
Merged at revision: 26
Proposed branch: lp:~savoirfairelinux-openerp/openerp-accountedge/6.1-fix-email-addresses-notifications
Merge into: lp:~openerp-accountedge/openerp-accountedge/6.1
Diff against target: 486 lines (+100/-149)
6 files modified
hr_expense_accountedge/__openerp__.py (+11/-12)
hr_expense_accountedge/edi/__init__.py (+0/-3)
hr_expense_accountedge/edi/hr_expense_expense.py (+7/-13)
hr_expense_accountedge/hr_expense_accountedge.py (+62/-78)
hr_expense_accountedge/hr_expense_accountedge.xml (+6/-6)
hr_expense_accountedge/tools/import_expenses.py (+14/-37)
To merge this branch: bzr merge lp:~savoirfairelinux-openerp/openerp-accountedge/6.1-fix-email-addresses-notifications
Reviewer Review Type Date Requested Status
Omar (Pexego) code review Approve
Joao Alfredo Gama Batista lgtm. no test Approve
Review via email: mp+194052@code.launchpad.net

Commit message

[MRG] Fix email addresses, exported date and PEP8 issues

To post a comment you must log in.
Revision history for this message
Joao Alfredo Gama Batista (joao-gama) :
review: Approve (lgtm. no test)
26. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[FIX] Use the current date in the export file

27. By Maxime Chambreuil (http://www.savoirfairelinux.com)

[FIX] PEP8 issues

Revision history for this message
Omar (Pexego) (omar7r) wrote :

LGTM

review: Approve (code review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hr_expense_accountedge/__openerp__.py'
2--- hr_expense_accountedge/__openerp__.py 2013-08-08 19:16:49 +0000
3+++ hr_expense_accountedge/__openerp__.py 2013-11-18 22:10:04 +0000
4@@ -19,17 +19,17 @@
5 #
6 ##############################################################################
7 {
8- "name" : "Harmonization of expenses with AccountEdge",
9- "version" : "1.0",
10- "author" : "Savoir-faire Linux",
11- "website" : "http://www.savoirfairelinux.com",
12- "category" : "Human Resources",
13+ "name": "Harmonization of expenses with AccountEdge",
14+ "version": "1.0",
15+ "author": "Savoir-faire Linux",
16+ "website": "http://www.savoirfairelinux.com",
17+ "category": "Human Resources",
18 "description": """
19 This module generates the csv reports for the exportation
20 of expenses in AccountEdge.
21 It also modifies the workflow of the expenses.
22 """,
23- "depends" : [
24+ "depends": [
25 'l10n_ca',
26 'hr_employee_accountedge',
27 'hr_expense_line_supplier',
28@@ -39,14 +39,13 @@
29 'account_account_halftax',
30 'account_tax_accountedge'
31 ],
32- "init_xml" : [],
33- "update_xml" : [
34+ "init_xml": [],
35+ "update_xml": [
36 'hr_expense_accountedge.xml',
37 'security/ir_rule.xml',
38 ],
39- "demo_xml" : [],
40- "installable" : True,
41- "certificate" : ''
42+ "demo_xml": [],
43+ "installable": True,
44+ "certificate": ''
45 }
46 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
47-
48
49=== modified file 'hr_expense_accountedge/edi/__init__.py'
50--- hr_expense_accountedge/edi/__init__.py 2013-07-16 19:21:49 +0000
51+++ hr_expense_accountedge/edi/__init__.py 2013-11-18 22:10:04 +0000
52@@ -18,8 +18,5 @@
53 # along with this program. If not, see <http://www.gnu.org/licenses/>.
54 #
55 ##############################################################################
56-
57 import hr_expense_expense
58-
59 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
60-
61
62=== modified file 'hr_expense_accountedge/edi/hr_expense_expense.py'
63--- hr_expense_accountedge/edi/hr_expense_expense.py 2013-07-16 19:21:49 +0000
64+++ hr_expense_accountedge/edi/hr_expense_expense.py 2013-11-18 22:10:04 +0000
65@@ -22,28 +22,22 @@
66 from osv import fields, osv, orm
67 from edi import EDIMixin
68
69+
70 class hr_expense_expense(osv.osv, EDIMixin):
71 _inherit = 'hr.expense.expense'
72
73 def _edi_get_web_url_view(self, cr, uid, ids, field_name, arg, context):
74- res = {}
75-
76+ res = {}
77 for id in ids:
78 web_root_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
79 res[id] = "%s/web/webclient/home#id=%s&view_type=page&model=hr.expense.expense" % (web_root_url, id)
80-
81 return res
82
83 _columns = {
84- 'web_url_view' : fields.function(
85- _edi_get_web_url_view,
86- string='Url of the expense view',
87- type='char',
88- size=255,
89- readonly=True),
90+ 'web_url_view': fields.function(_edi_get_web_url_view,
91+ string='Url of the expense view',
92+ type='char',
93+ size=255,
94+ readonly=True),
95 }
96-
97-
98-
99 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
100-
101
102=== modified file 'hr_expense_accountedge/hr_expense_accountedge.py'
103--- hr_expense_accountedge/hr_expense_accountedge.py 2013-08-12 22:45:27 +0000
104+++ hr_expense_accountedge/hr_expense_accountedge.py 2013-11-18 22:10:04 +0000
105@@ -29,56 +29,52 @@
106 class hr_expense_expense(osv.osv):
107 _inherit = 'hr.expense.expense'
108
109- def _create_csv_report(self,cr,uid,ids,context={}):
110+ def _create_csv_report(self, cr, uid, ids, context={}):
111 res = {}
112 for id in ids:
113- this = self.browse(cr, uid, id)
114- empl_id = self.pool.get('hr.employee').search(cr, uid, [('user_id','=', this.user_id.id)])
115- empl = self.pool.get('hr.employee').browse(cr, uid, empl_id)[0]
116+ this = self.browse(cr, uid, id)
117
118- output = this.employee_id.name
119+ output = this.employee_id.name
120 output += "\r\n"
121 output += "Employee\tCard ID\tDate\tVendor Invoice #\tAccount Number\tAmount\tDescription\
122 \tTax Code\tCurrency Code\tExchange Rate\r\n"
123- # Comment the previous line and uncomment the next one
124+ # Comment the previous line and uncomment the next one
125 # if you want to import taxes with their amount, instead of their code
126 # \tTax Code\tGST Amount\tPST/QST Amount\tCurrency Code\tExchange Rate\r\n"
127
128-
129 for l in this.line_ids:
130- taxes = self._compute_taxes(cr,uid,l,context)
131- #output += u"%s\t%s\t%s\t%s\t%s\t%.2f\t%s\t%s\t%.2f\t%.2f\t%s\t%.2f\r\n" % (
132- output += u"%s\t%s\t%s\t%s\t%s\t%.2f\t%s\t%s\t%s\t%.2f\r\n" % (
133- this.employee_id.name,
134- this.employee_id.supplier_id_accountedge,
135- datetime.strptime(l.date_value,"%Y-%m-%d").strftime("%d-%m-%Y"),
136- l.expense_id.id,
137- l.account_id.code,
138- taxes['amount_before_tax'],
139- l.name,
140- (l.tax_id.tax_code_accountedge or '000'),
141- # Comment the previous line and uncomment the next two ones
142- # if you want to import taxes with their amount, instead of their code
143- # taxes['amount_gst'],
144- # taxes['amount_pst'],
145- (l.expense_id.currency_id.name or 'CAD'),
146- (float(l.expense_id.currency_id.rate) or '1.0'))
147+ taxes = self._compute_taxes(cr, uid, l, context)
148+ # output += u"%s\t%s\t%s\t%s\t%s\t%.2f\t%s\t%s\t%.2f\t%.2f\t%s\t%.2f\r\n" % (
149+ output += u"%s\t%s\t%s\t%s\t%s\t%.2f\t%s\t%s\t%s\t%.2f\r\n" % (
150+ this.employee_id.name,
151+ this.employee_id.supplier_id_accountedge,
152+ datetime.today().strftime("%d-%m-%Y"),
153+ l.expense_id.id,
154+ l.account_id.code,
155+ taxes['amount_before_tax'],
156+ l.name,
157+ (l.tax_id.tax_code_accountedge or '000'),
158+ # Comment the previous line and uncomment the next two ones
159+ # if you want to import taxes with their amount, instead of their code
160+ # taxes['amount_gst'],
161+ # taxes['amount_pst'],
162+ (l.expense_id.currency_id.name or 'CAD'),
163+ (float(l.expense_id.currency_id.rate) or '1.0'))
164
165 byte_string = output.encode('utf-8-sig')
166- res[id] = base64.encodestring(byte_string)
167+ res[id] = base64.encodestring(byte_string)
168
169- self.write(cr, uid, ids, {'csv_file':res[id]}, context=context)
170- self._add_attachment(cr,uid,id,byte_string,context)
171+ self.write(cr, uid, ids, {'csv_file': res[id]}, context=context)
172+ self._add_attachment(cr, uid, id, byte_string, context)
173
174 return True
175
176-
177- def _compute_taxes(self,cr,uid,expense_line,context={}):
178+ def _compute_taxes(self, cr, uid, expense_line, context={}):
179
180 res = {
181- 'amount_before_tax' : expense_line.total_amount,
182- 'amount_gst' : 0.0, # Goods and Services Tax, federal
183- 'amount_pst' : 0.0 # Provincial Sales Tax
184+ 'amount_before_tax': expense_line.total_amount,
185+ 'amount_gst': 0.0, # Goods and Services Tax, federal
186+ 'amount_pst': 0.0 # Provincial Sales Tax
187 }
188
189 tax = expense_line.tax_id
190@@ -90,96 +86,86 @@
191 if expense_line.account_id.tax_halftax:
192 tax_factor = 0.5
193
194- if tax.child_ids :
195- for child_tax in tax.child_ids: # TODO: the detection of the two taxes should be more reliable
196+ if tax.child_ids:
197+ for child_tax in tax.child_ids: # TODO: the detection of the two taxes should be more reliable
198 if 'TPS' in child_tax.name or 'GST' in child_tax.name:
199 res['amount_gst'] = float(child_tax.amount) * tax_factor
200 else:
201 res['amount_pst'] = float(child_tax.amount) * tax_factor
202 else:
203 res['amount_gst'] = float(tax.amount)
204-
205-
206- res['amount_before_tax'] = expense_line.total_amount / (1 + res['amount_gst'] + res['amount_pst'])
207- res['amount_gst'] = res['amount_before_tax'] * res['amount_gst']
208- res['amount_pst'] = res['amount_before_tax'] * res['amount_pst']
209-
210+ res['amount_before_tax'] = expense_line.total_amount / (1 + res['amount_gst'] + res['amount_pst'])
211+ res['amount_gst'] = res['amount_before_tax'] * res['amount_gst']
212+ res['amount_pst'] = res['amount_before_tax'] * res['amount_pst']
213 return res
214
215-
216-
217- def _add_attachment(self,cr,uid,ids,content,context={}):
218-
219- file_name = 'export_'+time.strftime('%Y%m%d_%H%M%S')+'.tsv'
220- attach_id = self.pool.get('ir.attachment').create(cr, uid, {
221- 'name' : file_name,
222- 'datas' : base64.encodestring(content),
223- 'datas_fname' : file_name,
224- 'res_model' : self._name,
225- 'res_id' : ids,
226+ def _add_attachment(self, cr, uid, ids, content, context={}):
227+
228+ file_name = 'export_'+time.strftime('%Y%m%d_%H%M%S')+'.tsv'
229+ self.pool.get('ir.attachment').create(cr, uid, {
230+ 'name': file_name,
231+ 'datas': base64.encodestring(content),
232+ 'datas_fname': file_name,
233+ 'res_model': self._name,
234+ 'res_id': ids,
235 },
236 context=context
237 )
238 return True
239
240- def action_exported(self,cr,uid,ids,*args):
241+ def action_exported(self, cr, uid, ids, *args):
242 if not len(ids):
243 return False
244
245 # Employee must have a recordID matching his supplier account
246 # in Accountedge to generate an expense sheet
247 for id in ids:
248- this = self.browse(cr, uid, id)
249+ this = self.browse(cr, uid, id)
250 if not this.employee_id.supplier_id_accountedge:
251 raise osv.except_osv('Accountedge Supplier ID missing',
252- 'Please add the Accountedge supplier ID on the employee before exporting the sheet.')
253-
254- self._create_csv_report(cr,uid,ids,{})
255- self.write(cr,uid,ids,{'state': 'exported'})
256-
257+ 'Please add the Accountedge supplier ID on the employee before exporting the sheet.')
258+ self._create_csv_report(cr, uid, ids, {})
259+ self.write(cr, uid, ids, {'state': 'exported'})
260 return True
261
262-
263- def action_imported(self,cr,uid,ids,*args):
264+ def action_imported(self, cr, uid, ids, *args):
265 if not len(ids):
266 return False
267 for id in ids:
268- self.write(cr,uid,ids,{'state': 'imported'})
269+ self.write(cr, uid, ids, {'state': 'imported'})
270 return True
271
272-
273 def _get_cur_account_manager(self, cr, uid, ids, field_name, arg, context):
274- res = {}
275+ res = {}
276 for id in ids:
277 emails = ''
278- grp_ids = self.pool.get('res.groups').search(cr, uid, [('name','=',u'Manager'),('category_id.name','=',u'Accounting & Finance')])
279- usr_ids = self.pool.get('res.users').search(cr, uid, [('groups_id','=',grp_ids[0])])
280- usrs = self.pool.get('res.users').browse(cr, uid, usr_ids)
281+ grp_ids = self.pool.get('res.groups').search(cr, uid, [('name', '=', u'Manager'), ('category_id.name', '=', u'Accounting & Finance')])
282+ usr_ids = self.pool.get('res.users').search(cr, uid, [('groups_id', '=', grp_ids[0])])
283+ usrs = self.pool.get('res.users').browse(cr, uid, usr_ids)
284
285 for user in usrs:
286 if user.user_email:
287 emails += user.user_email
288 emails += ','
289 else:
290- empl_id = self.pool.get('hr.employee').search(cr, uid,[('login','=',user.login)])[0]
291- empl = self.pool.get('hr.employee').browse(cr, uid, empl_id)
292+ empl_id = self.pool.get('hr.employee').search(cr, uid, [('login', '=', user.login)])[0]
293+ empl = self.pool.get('hr.employee').browse(cr, uid, empl_id)
294 if empl.work_email:
295 emails += empl.work_email
296 emails += ','
297-
298- emails = emails[:-1]
299+ emails = emails[:-1]
300 res[id] = emails
301 return res
302
303 _columns = {
304- 'manager' : fields.function(_get_cur_account_manager,string='Manager',type='char',size=128,readonly=True),
305- 'state' : fields.selection([
306+ 'manager': fields.function(_get_cur_account_manager, string='Manager', type='char', size=128, readonly=True),
307+ 'state': fields.selection([
308 ('draft', 'New'),
309 ('confirm', 'Waiting Approval'),
310 ('accepted', 'Approved'),
311 ('exported', 'Exported'),
312 ('imported', 'Imported'),
313- ('cancelled', 'Refused'),],
314+ ('cancelled', 'Refused'), ],
315 'State', readonly=True, help='When the expense request is created the state is \'Draft\'.\
316 \n It is confirmed by the user and request is sent to admin, the state is \'Waiting Confirmation\'.\
317 \nIf the admin accepts it, the state is \'Accepted\'.\
318@@ -188,24 +174,22 @@
319 \n If the expense request has been imported in AccountEdge, the state is \'Imported\'.'
320 ),
321 }
322-
323-
324 hr_expense_expense()
325
326+
327 class hr_expense_line(osv.osv):
328 _inherit = 'hr.expense.line'
329
330 def _get_parent_state(self, cr, uid, ids, field_name, arg, context):
331- res = {}
332+ res = {}
333 for id in ids:
334 expense_line = self.pool.get('hr.expense.line').browse(cr, uid, id)
335 res[id] = expense_line.expense_id.state
336 return res
337
338 _columns = {
339- 'state': fields.function(_get_parent_state,string='Expense State',type='char',size=128,readonly=True),
340+ 'state': fields.function(_get_parent_state, string='Expense State', type='char', size=128, readonly=True),
341 }
342-
343 hr_expense_line()
344
345 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
346
347=== modified file 'hr_expense_accountedge/hr_expense_accountedge.xml'
348--- hr_expense_accountedge/hr_expense_accountedge.xml 2013-08-08 19:43:14 +0000
349+++ hr_expense_accountedge/hr_expense_accountedge.xml 2013-11-18 22:10:04 +0000
350@@ -194,12 +194,12 @@
351 -->
352 <record id="email_template_edi_expense_waiting_approval" model="email.template">
353 <field name="name">Automated Invoice Notification Mail</field>
354- <field name="email_from">${object.company_id.email or 'noreply@localhost'}</field>
355+ <field name="email_from">${object.employee_id.user_id.user_email or 'noreply@localhost'}</field>
356 <field name="subject">New expense waiting for approval</field>
357- <field name="email_to">${object.employee_id.parent_id.work_email or 'naysan.saran@gmail.com'}</field>
358+ <field name="email_to">${object.employee_id.parent_id.user_id.user_email}</field>
359 <field name="model_id" ref="model_hr_expense_expense"/>
360 <field name="auto_delete" eval="True"/>
361- <field name="lang">${object.employee_id.partner_id.lang}</field>
362+ <field name="lang">${object.employee_id.user_id.context_lang}</field>
363 <field name="body_html"><![CDATA[
364 <div style="
365 font-family : 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;
366@@ -240,12 +240,12 @@
367 -->
368 <record id="email_template_edi_expense_accepted" model="email.template">
369 <field name="name">Automated Invoice Notification Mail</field>
370- <field name="email_from">${object.company_id.email or 'noreply@localhost'}</field>
371+ <field name="email_from">${object.employee_id.user_id.user_email or 'noreply@localhost'}</field>
372 <field name="subject">New expense approved and ready for export</field>
373- <field name="email_to">${object.manager_emails}</field>
374+ <field name="email_to">payable@localhost</field>
375 <field name="model_id" ref="model_hr_expense_expense"/>
376 <field name="auto_delete" eval="True"/>
377- <field name="lang">${object.employee_id.partner_id.lang}</field>
378+ <field name="lang">${object.employee_id.user_id.context_lang}</field>
379 <field name="body_html"><![CDATA[
380 <div style="
381 font-family : 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;
382
383=== modified file 'hr_expense_accountedge/tools/import_expenses.py'
384--- hr_expense_accountedge/tools/import_expenses.py 2013-08-08 22:25:29 +0000
385+++ hr_expense_accountedge/tools/import_expenses.py 2013-11-18 22:10:04 +0000
386@@ -24,86 +24,63 @@
387 import getpass
388 from datetime import datetime
389
390+
391 def main():
392- username = 'openerp_user'
393- dbname = ''
394- server_url = 'http://localhost:8069'
395- csv_path = 'hr_expense_accountedge.txt'
396+ username = 'openerp_user'
397+ dbname = ''
398+ server_url = 'http://localhost:8069'
399+ csv_path = 'hr_expense_accountedge.txt'
400
401 pwd = getpass.getpass(prompt="Please enter the password of %s: " % username)
402-
403 # Get the uid
404 sock_common = xmlrpclib.ServerProxy('%s/xmlrpc/common' % server_url)
405 uid = sock_common.login(dbname, username, pwd)
406-
407 if not uid:
408 print "Connection error. Please check the username, password and server url."
409- goodbye = raw_input("Type 'enter' to quit...")
410+ raw_input("Type 'enter' to quit...")
411 return 1
412-
413- # Replace localhost with the address of the server
414+ # Replace localhost with the address of the server
415 sock = xmlrpclib.ServerProxy('%s/xmlrpc/object' % server_url)
416-
417 # Search for exported expense notes
418 args = [('state', '=', 'exported')]
419 expense_ids = sock.execute(dbname, uid, pwd, 'hr.expense.expense', 'search', args)
420-
421 print "There are %d expense sheets to import" % len(expense_ids)
422-
423 if not expense_ids:
424- goodbye = raw_input("Type 'enter' to quit...")
425+ raw_input("Type 'enter' to quit...")
426 return 1
427-
428 # Outpout file for AccountEdge
429 final_csv = open(csv_path, 'w')
430-
431 num_expense = 0
432
433 # For each exported expense note, search for the tsv attachment
434 for expense_id in expense_ids:
435-
436- args = [('res_model','=','hr.expense.expense'),('res_id', '=', expense_id)]
437+ args = [('res_model', '=', 'hr.expense.expense'), ('res_id', '=', expense_id)]
438 csv_ids = sock.execute(dbname, uid, pwd, 'ir.attachment', 'search', args)
439-
440- fields = ['name', 'datas']
441+ fields = ['name', 'datas']
442 csv_obj = sock.execute(dbname, uid, pwd, 'ir.attachment', 'read', csv_ids, fields)
443-
444 latest_csv = None
445 latest_date = datetime(2000, 1, 1, 0, 0, 0)
446-
447 # Find the latest csv
448 for csv in csv_obj:
449-
450 format = 'export_%Y%m%d_%H%M%S.tsv'
451 date_created = datetime.strptime(csv["name"], format)
452-
453 if date_created > latest_date:
454 latest_date = date_created
455 latest_csv = csv
456-
457 # Copy the lines to the new summary file
458 if latest_csv:
459- content = base64.b64decode(csv['datas'])
460- content = content.split("\r\n")
461-
462-
463+ content = base64.b64decode(csv['datas'])
464+ content = content.split("\r\n")
465 for num_line in range(len(content)):
466 if (num_line == 1 and num_expense == 0) or num_line > 1:
467 final_csv.write(content[num_line])
468 final_csv.write("\r\n")
469-
470-
471 num_expense = num_expense + 1
472-
473-
474 # Mark the expenses as imported
475 values = {'state': 'exported'}
476- result = sock.execute(dbname, uid, pwd, 'hr.expense.expense', 'write', expense_ids, values)
477-
478+ sock.execute(dbname, uid, pwd, 'hr.expense.expense', 'write', expense_ids, values)
479 final_csv.close()
480-
481- goodbye = raw_input("Type 'enter' to quit...")
482+ raw_input("Type 'enter' to quit...")
483
484 if __name__ == "__main__":
485 main()
486-

Subscribers

People subscribed via source and target branches