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
1=== modified file 'bin/addons/msf_homere_interface/hr_payroll_wizard.xml'
2--- bin/addons/msf_homere_interface/hr_payroll_wizard.xml 2019-05-14 15:12:35 +0000
3+++ bin/addons/msf_homere_interface/hr_payroll_wizard.xml 2019-08-02 15:10:29 +0000
4@@ -108,13 +108,23 @@
5 <field name="arch" type="xml">
6 <form string="Import Confirmation">
7 <field name="filename" attrs="{'invisible': [('filename', '=', False)]}"/>
8+ <field name="nberrors" invisible="1"/>
9+ <field name="from" invisible="1"/>
10 <group colspan="4" col="8">
11 <field name="total" attrs="{'invisible': [('state', 'in', ['none', 'payroll'])]}"/>
12 <field name="created" attrs="{'invisible': [('state', '=', 'none')]}"/>
13 <field name="updated" invisible="context.get('from', False) not in ['expat_employee_import', 'employee_import']"/>
14 <field name="rejected" invisible="context.get('from', False) != 'employee_import'"/>
15 </group>
16- <field name="error_line_ids" nolabel="1" colspan="4" attrs="{'invisible': [('nberrors', '=', 0)]}">
17+ <group colspan="4" attrs="{'invisible': ['|', ('nberrors', '=', 0), ('from', '!=', 'employee_import')]}">
18+ <html>
19+ <p id="label_import_employee_fail"
20+ style="text-align:center; color: red; font-weight: bold; font-size: 1.2em;">
21+ <translate>The import of the file failed!</translate>
22+ </p>
23+ </html>
24+ </group>
25+ <field name="error_line_ids" nolabel="1" colspan="4">
26 <tree string="Error List">
27 <field name="msg"/>
28 </tree>
29
30=== modified file 'bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py'
31--- bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py 2019-02-15 09:33:04 +0000
32+++ bin/addons/msf_homere_interface/wizard/hr_payroll_employee_import.py 2019-08-02 15:10:29 +0000
33@@ -54,6 +54,17 @@
34 _name = 'hr.payroll.import.confirmation'
35 _description = 'Import Confirmation'
36
37+ def _get_from(self, cr, uid, ids, name, arg, context=None):
38+ """
39+ Returns the value stored in context at index "from" = from where the wizard has been opened
40+ """
41+ if context is None:
42+ context = {}
43+ res = {}
44+ for wiz_id in ids:
45+ res[wiz_id] = context.get('from')
46+ return res
47+
48 _columns = {
49 'updated': fields.integer(string="Updated", size=64, readonly=True),
50 'created': fields.integer(string="Created", size=64, readonly=True),
51@@ -66,6 +77,8 @@
52 'errors': fields.text(string="Errors", readonly=True),
53 'nberrors': fields.integer(string="Errors", readonly=True),
54 'filename': fields.char(string="Filename", size=256, readonly=True),
55+ # WARNING: this wizard model is used for the import of employees from Homere, expats, nat. staff, Payroll, HQ entries...
56+ 'from': fields.function(_get_from, type='char', method=True, string="From where has this wizard been opened?", store=False),
57 }
58
59 _defaults = {
60@@ -188,9 +201,32 @@
61 'filename': fields.char(string="Imported filename", size=256),
62 }
63
64+ def store_error(self, errors, wizard_id, message):
65+ """
66+ Stores the "message" in the dictionary "errors" at index "wizard_id"
67+ """
68+ if errors is not None:
69+ if wizard_id not in errors:
70+ errors[wizard_id] = []
71+ errors[wizard_id].append(message)
72+
73+ def generate_errors(self, cr, uid, errors, context=None):
74+ """
75+ Deletes the old errors in DB and replaces them by the new ones
76+ """
77+ if context is None:
78+ context = {}
79+ error_obj = self.pool.get('hr.payroll.employee.import.errors')
80+ error_ids = error_obj.search(cr, uid, [], order='NO_ORDER', context=context)
81+ if error_ids:
82+ error_obj.unlink(cr, uid, error_ids, context=context)
83+ for wiz_id in errors:
84+ for err in errors[wiz_id]:
85+ error_obj.create(cr, uid, {'wizard_id': wiz_id, 'msg': err}, context=context)
86+
87 def update_employee_check(self, cr, uid,
88 staffcode=False, missioncode=False, staff_id=False, uniq_id=False,
89- wizard_id=None, employee_name=False, registered_keys=None, homere_fields=None):
90+ wizard_id=None, employee_name=False, registered_keys=None, homere_fields=None, errors=None):
91 """
92 Check that:
93 - no more than 1 employee exist for "missioncode + staff_id + uniq_id"
94@@ -227,7 +263,7 @@
95 message = _('No "id_staff" found for employee %s!') % (name,)
96 elif not uniq_id:
97 message = _('No "id_unique" found for employee %s!') % (name,)
98- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})
99+ self.store_error(errors, wizard_id, message)
100 return (res, what_changed)
101
102 # Check employees
103@@ -246,11 +282,10 @@
104 # if not possible only the current employee name will be displayed
105 else:
106 list_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]
107- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {
108- 'wizard_id': wizard_id,
109- 'msg': _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
110- (missioncode, staff_id, uniq_id, ' ; '.join(list_duplicates))
111- })
112+ self.store_error(errors, wizard_id,
113+ _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
114+ (missioncode, staff_id, uniq_id, ' ; '.join(list_duplicates))
115+ )
116 return (res, what_changed)
117
118 # check duplicates already in db
119@@ -261,11 +296,10 @@
120 name_duplicates = ['%s (%s)' % (employee_name, _('Import File'))]
121 # ... and the duplicates already in UniField
122 name_duplicates.extend(['%s (UniField)' % emp.name for emp in emp_duplicates if emp.name])
123- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {
124- 'wizard_id': wizard_id,
125- 'msg': _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
126- (missioncode, staff_id, uniq_id, ' ; '.join(name_duplicates))
127- })
128+ self.store_error(errors, wizard_id,
129+ _('Several employees have the same combination key codeterrain/id_staff/(id_unique) "%s / %s / (%s)": %s') %
130+ (missioncode, staff_id, uniq_id, ' ; '.join(name_duplicates))
131+ )
132 return (res, what_changed)
133
134 # Check staffcode
135@@ -284,7 +318,7 @@
136 # add the duplicated employee from Import File
137 message = _('Several employees have the same Identification No "%s": %s') % \
138 (staffcode, ' ; '.join(["%s (%s)" % (employee_name, _('Import File'))] + employee_error_list))
139- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})
140+ self.store_error(errors, wizard_id, message)
141 return (res, what_changed)
142
143 res = True
144@@ -294,8 +328,8 @@
145 """
146 Method used to check if the Identification No to be used for the employee about to be created/edited doesn't
147 already exist for another employee in UniField.
148- Returns False if there is a duplication AND we are in the use case where the related and detailed
149- "hr.payroll.employee.import.error" has already been created (but the process wasn't blocked earlier since "what_changed" had a value).
150+ Returns False if there is a duplication AND we are in the use case where the related and detailed error has
151+ already been stored in the list of errors to display (but the process wasn't blocked earlier since "what_changed" had a value).
152 Otherwise returns True => the generic create/write checks will then apply (i.e. a generic error msg will be displayed)
153 """
154 if context is None:
155@@ -322,7 +356,7 @@
156 return res
157
158 def update_employee_infos(self, cr, uid, employee_data='', wizard_id=None,
159- line_number=None, registered_keys=None, homere_fields=None, context=None):
160+ line_number=None, registered_keys=None, homere_fields=None, errors=None, context=None):
161 """
162 Get employee infos and set them to DB.
163 """
164@@ -339,7 +373,7 @@
165 payment_method_obj = self.pool.get('hr.payment.method')
166 if not employee_data or not wizard_id:
167 message = _('No data found for this line: %s.') % line_number
168- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})
169+ self.store_error(errors, wizard_id, message)
170 return False, created, updated
171 # Prepare some values
172 vals = {}
173@@ -383,7 +417,8 @@
174 staffcode=ustr(code_staff), missioncode=ustr(codeterrain),
175 staff_id=id_staff, uniq_id=ustr(uniq_id),
176 wizard_id=wizard_id, employee_name=employee_name,
177- registered_keys=registered_keys, homere_fields=homere_fields)
178+ registered_keys=registered_keys, homere_fields=homere_fields,
179+ errors=errors)
180 if not employee_check and not what_changed:
181 return False, created, updated
182
183@@ -426,7 +461,7 @@
184 payment_method_id = payment_method_ids[0]
185 else:
186 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)
187- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})
188+ self.store_error(errors, wizard_id, message)
189 return False, created, updated
190
191 vals.update({'payment_method_id': payment_method_id})
192@@ -506,7 +541,7 @@
193 registered_keys[codeterrain + id_staff + uniq_id] = True
194 else:
195 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)
196- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wizard_id, 'msg': message})
197+ self.store_error(errors, wizard_id, message)
198 return False, created, updated
199
200 return True, created, updated
201@@ -663,10 +698,7 @@
202 processed = 0
203 filename = ""
204 registered_keys = {}
205- # Delete old errors
206- error_ids = self.pool.get('hr.payroll.employee.import.errors').search(cr, uid, [])
207- if error_ids:
208- self.pool.get('hr.payroll.employee.import.errors').unlink(cr, uid, error_ids)
209+ errors = {}
210 for wiz in self.browse(cr, uid, ids):
211 if not wiz.file:
212 raise osv.except_osv(_('Error'), _('Nothing to import.'))
213@@ -735,7 +767,7 @@
214 for i, employee_data in enumerate(staff_seen):
215 update, nb_created, nb_updated = self.update_employee_infos(
216 cr, uid, employee_data, wiz.id, i,
217- registered_keys=registered_keys, homere_fields=homere_fields, context=context)
218+ registered_keys=registered_keys, homere_fields=homere_fields, errors=errors, context=context)
219 if not update:
220 res = False
221 created += nb_created
222@@ -746,7 +778,7 @@
223 # create a different error line for each employee code being duplicated
224 for emp_code in details:
225 message = _('Several employees have the same Identification No "%s": %s') % (emp_code, ' ; '.join(details[emp_code]))
226- self.pool.get('hr.payroll.employee.import.errors').create(cr, uid, {'wizard_id': wiz.id, 'msg': message})
227+ self.store_error(errors, wiz.id, message)
228 # Close Temporary File
229 # Delete previous created lines for employee's contracts
230 if contract_ids:
231@@ -757,9 +789,18 @@
232 shutil.rmtree(tmpdir)
233 del registered_keys
234 if res:
235+ rejected = processed - created - updated
236 message = _("Employee import successful.")
237 else:
238+ # reject the import of all employees
239+ cr.rollback()
240+ rejected = processed
241+ created = updated = 0
242 context.update({'employee_import_wizard_ids': ids})
243+
244+ # handle the errors at the end of the process to ensure the deletion & creation aren't affected by the rollback
245+ self.generate_errors(cr, uid, errors, context=context)
246+
247 context.update({'message': message})
248
249 view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_homere_interface', 'payroll_import_confirmation')
250@@ -768,7 +809,6 @@
251 # This is to redirect to Employee Tree View
252 context.update({'from': 'employee_import'})
253
254- rejected = processed - created - updated
255 res_id = self.pool.get('hr.payroll.import.confirmation').create(cr, uid, {'filename': filename, 'created': created,
256 'updated': updated, 'total': processed,
257 'rejected': rejected, 'state': 'employee'}, context)
258
259=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
260--- bin/addons/msf_profile/i18n/fr_MF.po 2019-07-31 14:57:17 +0000
261+++ bin/addons/msf_profile/i18n/fr_MF.po 2019-08-02 15:10:29 +0000
262@@ -107559,6 +107559,16 @@
263 msgid "Line State"
264 msgstr "État de la Ligne"
265
266+#. module: msf_homere_interface
267+#: view:hr.payroll.import.confirmation:0
268+msgid "The import of the file failed!"
269+msgstr "L'import du fichier a échoué !"
270+
271+#. module: msf_homere_interface
272+#: field:hr.payroll.import.confirmation,from:0
273+msgid "From where has this wizard been opened?"
274+msgstr "Depuis où cet assistant a-t-il été ouvert ?"
275+
276 #. modules: sales_followup, msf_supply_doc_export
277 #: code:sales_followup/wizard/sale_followup_multi_wizard.py:190
278 #: code:addons/msf_supply_doc_export/wizard/po_follow_up.py:297

Subscribers

People subscribed via source and target branches