Merge lp:~julie-w/unifield-server/US-5658 into lp:unifield-server

Proposed by jftempo
Status: Merged
Merged at revision: 5448
Proposed branch: lp:~julie-w/unifield-server/US-5658
Merge into: lp:unifield-server
Diff against target: 278 lines (+88/-28)
3 files modified
bin/addons/msf_homere_interface/hr_payroll_wizard.xml (+11/-1)
bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py (+67/-27)
bin/addons/msf_profile/i18n/fr_MF.po (+10/-0)
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-5658
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+370915@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/addons/msf_homere_interface/hr_payroll_wizard.xml'
--- bin/addons/msf_homere_interface/hr_payroll_wizard.xml 2019-05-14 15:12:35 +0000
+++ bin/addons/msf_homere_interface/hr_payroll_wizard.xml 2019-08-02 15:10:29 +0000
@@ -108,13 +108,23 @@
108 <field name="arch" type="xml">108 <field name="arch" type="xml">
109 <form string="Import Confirmation">109 <form string="Import Confirmation">
110 <field name="filename" attrs="{'invisible': [('filename', '=', False)]}"/>110 <field name="filename" attrs="{'invisible': [('filename', '=', False)]}"/>
111 <field name="nberrors" invisible="1"/>
112 <field name="from" invisible="1"/>
111 <group colspan="4" col="8">113 <group colspan="4" col="8">
112 <field name="total" attrs="{'invisible': [('state', 'in', ['none', 'payroll'])]}"/>114 <field name="total" attrs="{'invisible': [('state', 'in', ['none', 'payroll'])]}"/>
113 <field name="created" attrs="{'invisible': [('state', '=', 'none')]}"/>115 <field name="created" attrs="{'invisible': [('state', '=', 'none')]}"/>
114 <field name="updated" invisible="context.get('from', False) not in ['expat_employee_import', 'employee_import']"/>116 <field name="updated" invisible="context.get('from', False) not in ['expat_employee_import', 'employee_import']"/>
115 <field name="rejected" invisible="context.get('from', False) != 'employee_import'"/>117 <field name="rejected" invisible="context.get('from', False) != 'employee_import'"/>
116 </group>118 </group>
117 <field name="error_line_ids" nolabel="1" colspan="4" attrs="{'invisible': [('nberrors', '=', 0)]}">119 <group colspan="4" attrs="{'invisible': ['|', ('nberrors', '=', 0), ('from', '!=', 'employee_import')]}">
120 <html>
121 <p id="label_import_employee_fail"
122 style="text-align:center; color: red; font-weight: bold; font-size: 1.2em;">
123 <translate>The import of the file failed!</translate>
124 </p>
125 </html>
126 </group>
127 <field name="error_line_ids" nolabel="1" colspan="4">
118 <tree string="Error List">128 <tree string="Error List">
119 <field name="msg"/>129 <field name="msg"/>
120 </tree>130 </tree>
121131
=== modified file 'bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py'
--- bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py 2019-02-15 09:33:04 +0000
+++ bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py 2019-08-02 15:10:29 +0000
@@ -54,6 +54,17 @@
54 _name = 'hr.payroll.import.confirmation'54 _name = 'hr.payroll.import.confirmation'
55 _description = 'Import Confirmation'55 _description = 'Import Confirmation'
5656
57 def _get_from(self, cr, uid, ids, name, arg, context=None):
58 """
59 Returns the value stored in context at index "from" = from where the wizard has been opened
60 """
61 if context is None:
62 context = {}
63 res = {}
64 for wiz_id in ids:
65 res[wiz_id] = context.get('from')
66 return res
67
57 _columns = {68 _columns = {
58 'updated': fields.integer(string="Updated", size=64, readonly=True),69 'updated': fields.integer(string="Updated", size=64, readonly=True),
59 'created': fields.integer(string="Created", size=64, readonly=True),70 'created': fields.integer(string="Created", size=64, readonly=True),
@@ -66,6 +77,8 @@
66 'errors': fields.text(string="Errors", readonly=True),77 'errors': fields.text(string="Errors", readonly=True),
67 'nberrors': fields.integer(string="Errors", readonly=True),78 'nberrors': fields.integer(string="Errors", readonly=True),
68 'filename': fields.char(string="Filename", size=256, readonly=True),79 'filename': fields.char(string="Filename", size=256, readonly=True),
80 # WARNING: this wizard model is used for the import of employees from Homere, expats, nat. staff, Payroll, HQ entries...
81 'from': fields.function(_get_from, type='char', method=True, string="From where has this wizard been opened?", store=False),
69 }82 }
7083
71 _defaults = {84 _defaults = {
@@ -188,9 +201,32 @@
188 'filename': fields.char(string="Imported filename", size=256),201 'filename': fields.char(string="Imported filename", size=256),
189 }202 }
190203
204 def store_error(self, errors, wizard_id, message):
205 """
206 Stores the "message" in the dictionary "errors" at index "wizard_id"
207 """
208 if errors is not None:
209 if wizard_id not in errors:
210 errors[wizard_id] = []
211 errors[wizard_id].append(message)
212
213 def generate_errors(self, cr, uid, errors, context=None):
214 """
215 Deletes the old errors in DB and replaces them by the new ones
216 """
217 if context is None:
218 context = {}
219 error_obj = self.pool.get('hr.payroll.employee.import.errors')
220 error_ids = error_obj.search(cr, uid, [], order='NO_ORDER', context=context)
221 if error_ids:
222 error_obj.unlink(cr, uid, error_ids, context=context)
223 for wiz_id in errors:
224 for err in errors[wiz_id]:
225 error_obj.create(cr, uid, {'wizard_id': wiz_id, 'msg': err}, context=context)
226
191 def update_employee_check(self, cr, uid,227 def update_employee_check(self, cr, uid,
192 staffcode=False, missioncode=False, staff_id=False, uniq_id=False,228 staffcode=False, missioncode=False, staff_id=False, uniq_id=False,
193 wizard_id=None, employee_name=False, registered_keys=None, homere_fields=None):229 wizard_id=None, employee_name=False, registered_keys=None, homere_fields=None, errors=None):
194 """230 """
195 Check that:231 Check that:
196 - no more than 1 employee exist for "missioncode + staff_id + uniq_id"232 - no more than 1 employee exist for "missioncode + staff_id + uniq_id"
@@ -227,7 +263,7 @@
227 message = _('No "id_staff" found for employee %s!') % (name,)263 message = _('No "id_staff" found for employee %s!') % (name,)
228 elif not uniq_id:264 elif not uniq_id:
229 message = _('No "id_unique" found for employee %s!') % (name,)265 message = _('No "id_unique" found for employee %s!') % (name,)
230 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})266 self.store_error(errors, wizard_id, message)
231 return (res, what_changed)267 return (res, what_changed)
232268
233 # Check employees269 # Check employees
@@ -246,11 +282,10 @@
246 # if not possible only the current employee name will be displayed282 # if not possible only the current employee name will be displayed
247 else:283 else:
248 list_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]284 list_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]
249 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {285 self.store_error(errors, wizard_id,
250 'wizard_id': wizard_id,286 _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
251 'msg': _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %287 (missioncode, staff_id, uniq_id, ' ; '.join(list_duplicates))
252 (missioncode, staff_id, uniq_id, ' ; '.join(list_duplicates))288 )
253 })
254 return (res, what_changed)289 return (res, what_changed)
255290
256 # check duplicates already in db291 # check duplicates already in db
@@ -261,11 +296,10 @@
261 name_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]296 name_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]
262 # ... and the duplicates already in UniField297 # ... and the duplicates already in UniField
263 name_duplicates.extend(['%s (UniField)' % emp.name for emp in emp_duplicates if emp.name])298 name_duplicates.extend(['%s (UniField)' % emp.name for emp in emp_duplicates if emp.name])
264 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {299 self.store_error(errors, wizard_id,
265 'wizard_id': wizard_id,300 _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
266 'msg': _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %301 (missioncode, staff_id, uniq_id, ' ; '.join(name_duplicates))
267 (missioncode, staff_id, uniq_id, ' ; '.join(name_duplicates))302 )
268 })
269 return (res, what_changed)303 return (res, what_changed)
270304
271 # Check staffcode305 # Check staffcode
@@ -284,7 +318,7 @@
284 # add the duplicated employee from Import File318 # add the duplicated employee from Import File
285 message = _('Several employees have the same Identification No "%s": %s') % \319 message = _('Several employees have the same Identification No "%s": %s') % \
286 (staffcode, ' ; '.join(["%s (%s)" % (employee_name, _('Import File'))] + employee_error_list))320 (staffcode, ' ; '.join(["%s (%s)" % (employee_name, _('Import File'))] + employee_error_list))
287 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})321 self.store_error(errors, wizard_id, message)
288 return (res, what_changed)322 return (res, what_changed)
289323
290 res = True324 res = True
@@ -294,8 +328,8 @@
294 """328 """
295 Method used to check if the Identification No to be used for the employee about to be created/edited doesn't329 Method used to check if the Identification No to be used for the employee about to be created/edited doesn't
296 already exist for another employee in UniField.330 already exist for another employee in UniField.
297 Returns False if there is a duplication AND we are in the use case where the related and detailed331 Returns False if there is a duplication AND we are in the use case where the related and detailed error has
298 "hr.payroll.employee.import.error" has already been created (but the process wasn't blocked earlier since "what_changed" had a value).332 already been stored in the list of errors to display (but the process wasn't blocked earlier since "what_changed" had a value).
299 Otherwise returns True => the generic create/write checks will then apply (i.e. a generic error msg will be displayed)333 Otherwise returns True => the generic create/write checks will then apply (i.e. a generic error msg will be displayed)
300 """334 """
301 if context is None:335 if context is None:
@@ -322,7 +356,7 @@
322 return res356 return res
323357
324 def update_employee_infos(self, cr, uid, employee_data='', wizard_id=None,358 def update_employee_infos(self, cr, uid, employee_data='', wizard_id=None,
325 line_number=None, registered_keys=None, homere_fields=None, context=None):359 line_number=None, registered_keys=None, homere_fields=None, errors=None, context=None):
326 """360 """
327 Get employee infos and set them to DB.361 Get employee infos and set them to DB.
328 """362 """
@@ -339,7 +373,7 @@
339 payment_method_obj = self.pool.get('hr.payment.method')373 payment_method_obj = self.pool.get('hr.payment.method')
340 if not employee_data or not wizard_id:374 if not employee_data or not wizard_id:
341 message = _('No data found for this line: %s.') % line_number375 message = _('No data found for this line: %s.') % line_number
342 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})376 self.store_error(errors, wizard_id, message)
343 return False, created, updated377 return False, created, updated
344 # Prepare some values378 # Prepare some values
345 vals = {}379 vals = {}
@@ -383,7 +417,8 @@
383 staffcode=ustr(code_staff), missioncode=ustr(codeterrain),417 staffcode=ustr(code_staff), missioncode=ustr(codeterrain),
384 staff_id=id_staff, uniq_id=ustr(uniq_id),418 staff_id=id_staff, uniq_id=ustr(uniq_id),
385 wizard_id=wizard_id, employee_name=employee_name,419 wizard_id=wizard_id, employee_name=employee_name,
386 registered_keys=registered_keys, homere_fields=homere_fields)420 registered_keys=registered_keys, homere_fields=homere_fields,
421 errors=errors)
387 if not employee_check and not what_changed:422 if not employee_check and not what_changed:
388 return False, created, updated423 return False, created, updated
389424
@@ -426,7 +461,7 @@
426 payment_method_id = payment_method_ids[0]461 payment_method_id = payment_method_ids[0]
427 else:462 else:
428 message = _('Payment Method %s not found for line: %s. Please fix Homere configuration or request a new Payment Method to the HQ.') % (ustr(bqmodereglement), line_number)463 message = _('Payment Method %s not found for line: %s. Please fix Homere configuration or request a new Payment Method to the HQ.') % (ustr(bqmodereglement), line_number)
429 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})464 self.store_error(errors, wizard_id, message)
430 return False, created, updated465 return False, created, updated
431466
432 vals.update({'payment_method_id': payment_method_id})467 vals.update({'payment_method_id': payment_method_id})
@@ -506,7 +541,7 @@
506 registered_keys[codeterrain + id_staff + uniq_id] = True541 registered_keys[codeterrain + id_staff + uniq_id] = True
507 else:542 else:
508 message = _('Line %s. One of this column is missing: code_terrain, id_unique or id_staff. This often happens when the line is empty.') % (line_number)543 message = _('Line %s. One of this column is missing: code_terrain, id_unique or id_staff. This often happens when the line is empty.') % (line_number)
509 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})544 self.store_error(errors, wizard_id, message)
510 return False, created, updated545 return False, created, updated
511546
512 return True, created, updated547 return True, created, updated
@@ -663,10 +698,7 @@
663 processed = 0698 processed = 0
664 filename = ""699 filename = ""
665 registered_keys = {}700 registered_keys = {}
666 # Delete old errors701 errors = {}
667 error_ids = self.pool.get('hr.payroll.employee.import.errors').search(cr, uid, [])
668 if error_ids:
669 self.pool.get('hr.payroll.employee.import.errors').unlink(cr, uid, error_ids)
670 for wiz in self.browse(cr, uid, ids):702 for wiz in self.browse(cr, uid, ids):
671 if not wiz.file:703 if not wiz.file:
672 raise osv.except_osv(_('Error'), _('Nothing to import.'))704 raise osv.except_osv(_('Error'), _('Nothing to import.'))
@@ -735,7 +767,7 @@
735 for i, employee_data in enumerate(staff_seen):767 for i, employee_data in enumerate(staff_seen):
736 update, nb_created, nb_updated = self.update_employee_infos(768 update, nb_created, nb_updated = self.update_employee_infos(
737 cr, uid, employee_data, wiz.id, i,769 cr, uid, employee_data, wiz.id, i,
738 registered_keys=registered_keys, homere_fields=homere_fields, context=context)770 registered_keys=registered_keys, homere_fields=homere_fields, errors=errors, context=context)
739 if not update:771 if not update:
740 res = False772 res = False
741 created += nb_created773 created += nb_created
@@ -746,7 +778,7 @@
746 # create a different error line for each employee code being duplicated778 # create a different error line for each employee code being duplicated
747 for emp_code in details:779 for emp_code in details:
748 message = _('Several employees have the same Identification No "%s": %s') % (emp_code, ' ; '.join(details[emp_code]))780 message = _('Several employees have the same Identification No "%s": %s') % (emp_code, ' ; '.join(details[emp_code]))
749 self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wiz.id, 'msg': message})781 self.store_error(errors, wiz.id, message)
750 # Close Temporary File782 # Close Temporary File
751 # Delete previous created lines for employee's contracts783 # Delete previous created lines for employee's contracts
752 if contract_ids:784 if contract_ids:
@@ -757,9 +789,18 @@
757 shutil.rmtree(tmpdir)789 shutil.rmtree(tmpdir)
758 del registered_keys790 del registered_keys
759 if res:791 if res:
792 rejected = processed - created - updated
760 message = _("Employee import successful.")793 message = _("Employee import successful.")
761 else:794 else:
795 # reject the import of all employees
796 cr.rollback()
797 rejected = processed
798 created = updated = 0
762 context.update({'employee_import_wizard_ids': ids})799 context.update({'employee_import_wizard_ids': ids})
800
801 # handle the errors at the end of the process to ensure the deletion & creation aren't affected by the rollback
802 self.generate_errors(cr, uid, errors, context=context)
803
763 context.update({'message': message})804 context.update({'message': message})
764805
765 view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_homere_interface', 'payroll_import_confirmation')806 view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_homere_interface', 'payroll_import_confirmation')
@@ -768,7 +809,6 @@
768 # This is to redirect to Employee Tree View809 # This is to redirect to Employee Tree View
769 context.update({'from': 'employee_import'})810 context.update({'from': 'employee_import'})
770811
771 rejected = processed - created - updated
772 res_id = self.pool.get('hr.payroll.import.confirmation').create(cr, uid, {'filename': filename, 'created': created,812 res_id = self.pool.get('hr.payroll.import.confirmation').create(cr, uid, {'filename': filename, 'created': created,
773 'updated': updated, 'total': processed,813 'updated': updated, 'total': processed,
774 'rejected': rejected, 'state': 'employee'}, context)814 'rejected': rejected, 'state': 'employee'}, context)
775815
=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
--- bin/addons/msf_profile/i18n/fr_MF.po 2019-07-31 14:57:17 +0000
+++ bin/addons/msf_profile/i18n/fr_MF.po 2019-08-02 15:10:29 +0000
@@ -107559,6 +107559,16 @@
107559msgid "Line State"107559msgid "Line State"
107560msgstr "État de la Ligne"107560msgstr "État de la Ligne"
107561107561
107562#. module: msf_homere_interface
107563#: view:hr.payroll.import.confirmation:0
107564msgid "The import of the file failed!"
107565msgstr "L'import du fichier a échoué !"
107566
107567#. module: msf_homere_interface
107568#: field:hr.payroll.import.confirmation,from:0
107569msgid "From where has this wizard been opened?"
107570msgstr "Depuis où cet assistant a-t-il été ouvert ?"
107571
107562#. modules: sales_followup, msf_supply_doc_export107572#. modules: sales_followup, msf_supply_doc_export
107563#: code:sales_followup/wizard/sale_followup_multi_wizard.py:190107573#: code:sales_followup/wizard/sale_followup_multi_wizard.py:190
107564#: code:addons/msf_supply_doc_export/wizard/po_follow_up.py:297107574#: code:addons/msf_supply_doc_export/wizard/po_follow_up.py:297

Subscribers

People subscribed via source and target branches