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

Proposed by jftempo
Status: Merged
Merged at revision: 5399
Proposed branch: lp:~julie-w/unifield-server/US-4703
Merge into: lp:unifield-server
Diff against target: 840 lines (+324/-346)
2 files modified
bin/addons/vertical_integration/report/hq_report_oca.py (+314/-345)
bin/addons/vertical_integration/wizard/wizard_hq_report_oca.py (+10/-1)
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-4703
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+357934@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/vertical_integration/report/hq_report_oca.py'
--- bin/addons/vertical_integration/report/hq_report_oca.py 2017-02-13 16:32:30 +0000
+++ bin/addons/vertical_integration/report/hq_report_oca.py 2019-06-07 09:34:36 +0000
@@ -28,13 +28,11 @@
28import os28import os
29from osv import osv29from osv import osv
30from tools.translate import _30from tools.translate import _
31from time import strptime
3132
32from report import report_sxw33from report import report_sxw
3334
3435
35ZERO_CELL_CONTENT = "0.0"
36
37
38class hq_report_oca(report_sxw.report_sxw):36class hq_report_oca(report_sxw.report_sxw):
3937
40 def __init__(self, name, table, rml=False, parser=report_sxw.rml_parse, header='external', store=False):38 def __init__(self, name, table, rml=False, parser=report_sxw.rml_parse, header='external', store=False):
@@ -45,7 +43,28 @@
45 return st.encode('utf8')43 return st.encode('utf8')
46 return st44 return st
4745
48 def translate_country(self, cr, uid, pool, browse_instance, context={}):46 def translate_account(self, cr, uid, pool, browse_account, context=None):
47 """
48 Returns the "HQ System Account Code" of the account in parameter if it exists, else returns the standard account code
49 """
50 if context is None:
51 context = {}
52 mapping_obj = pool.get('account.export.mapping')
53 if browse_account:
54 mapping_ids = mapping_obj.search(cr, uid, [('account_id', '=', browse_account.id)], context=context)
55 if len(mapping_ids) > 0:
56 mapping = mapping_obj.browse(cr, uid, mapping_ids[0], fields_to_fetch=['mapping_value'], context=context)
57 return mapping.mapping_value
58 else:
59 return browse_account.code
60 return ""
61
62 def translate_country(self, cr, uid, pool, browse_instance, context=None):
63 """
64 Returns the "HQ System Country Code" of the instance in parameter if it exists, else returns 0
65 """
66 if context is None:
67 context = {}
49 mapping_obj = pool.get('country.export.mapping')68 mapping_obj = pool.get('country.export.mapping')
50 if browse_instance:69 if browse_instance:
51 mapping_ids = mapping_obj.search(cr, uid, [('instance_id', '=', browse_instance.id)], context=context)70 mapping_ids = mapping_obj.search(cr, uid, [('instance_id', '=', browse_instance.id)], context=context)
@@ -54,69 +73,69 @@
54 return mapping.mapping_value73 return mapping.mapping_value
55 return "0"74 return "0"
5675
57 def create_counterpart(self, cr, uid, line):76 def create_subtotal(self, cr, uid, line_key, line_debit, counterpart_date, period, department_info, field_activity, context=None):
58 """ third report: up balances """77 if context is None:
59 # method to create counterpart line78 context = {}
60 return line[:2] + \79 pool = pooler.get_pool(cr.dbname)
61 ["20750",80 curr_obj = pool.get('res.currency')
62 "0", # before US-274/7 was expat EMP identification line[3]81 rate_obj = pool.get('res.currency.rate')
63 "0",
64 line[5], # expat employee name or "0"
65 line[6],
66 line[7],
67 line[9],
68 line[8]] + line[10:]
69
70 def create_subtotal(self, cr, uid, line_key,
71 line_debit, line_functional_debit, line_functional_debit_no_ccy_adj,
72 counterpart_date, country_code, sequence_number):
73 """ third report: up balances """
74 # method to create subtotal + counterpart line82 # method to create subtotal + counterpart line
75 if len(line_key) > 2 and line_debit != 0.0 and line_functional_debit != 0.0:83 period_code = period.code or ""
76 # US-118: func debit with no FXA currency adjustement entries84 if len(line_key) > 1 and line_debit != 0.0:
77 # compute subtotal line inverted rate with no FXA entry:85 currency = curr_obj.browse(cr, uid, line_key[1], context=context)
78 # no booking amount but funct one then cause a wrong balance86 # rate at the first day of the selected period
79 # for ccy inverted rate computation87 rate = 0
80 rate = round(1 / (line_debit / line_functional_debit_no_ccy_adj), 8)88 rate_ids = rate_obj.search(cr, uid, [('currency_id', '=', currency.id), ('name', '<=', period.date_start)],
81 return [["01",89 order='name DESC', limit=1, context=context)
82 country_code,90 if rate_ids:
91 rate = rate_obj.browse(cr, uid, rate_ids[0], fields_to_fetch=['rate'], context=context).rate
92 # Description for the line
93 if line_key[0] == "1000 0000":
94 description = "Mvts_BANK_" + period_code + "_" + currency.name
95 elif line_key[0] == "1000 0001":
96 description = "Mvts_CASH_" + period_code + "_" + currency.name
97 else:
98 mapping_obj = pool.get('account.export.mapping')
99 account_values = ""
100 mapping_ids = mapping_obj.search(cr, uid, [('mapping_value', '=', line_key[0])], context=context)
101 for mapping in mapping_obj.browse(cr, uid, mapping_ids, fields_to_fetch=['account_id'], context=context):
102 if account_values != "":
103 account_values += "-"
104 account_values += mapping.account_id.code
105 description = "Mvts_" + account_values + period_code + "_" + currency.name
106
107 return [["",
108 "",
109 "",
110 description,
111 "",
112 counterpart_date,
113 counterpart_date,
114 period_code,
83 line_key[0],115 line_key[0],
84 "0",116 "",
85 "0",117 department_info,
86 counterpart_date,118 "",
87 line_key[1],119 "",
120 "",
88 rate,121 rate,
89 line_debit > 0 and round(line_debit, 2) or "",122 line_debit > 0 and round(line_debit, 2) or "0.00",
90 line_debit < 0 and round(-line_debit, 2) or "",123 line_debit > 0 and "0.00" or round(-line_debit, 2),
91 sequence_number,124 currency.name,
92 "Subtotal - " + line_key[0] + " - " + line_key[1] + " - " + line_key[2],125 field_activity]]
93 "",
94 "0",
95 counterpart_date,
96 "0"]
97 ,["01",
98 country_code,
99 "20750",
100 "0",
101 "0",
102 counterpart_date,
103 line_key[1],
104 rate,
105 line_debit < 0 and round(-line_debit, 2) or "",
106 line_debit > 0 and round(line_debit, 2) or "",
107 sequence_number,
108 "Automatic counterpart for " + line_key[0] + " - " + line_key[1] + " - " + line_key[2],
109 "",
110 "0",
111 counterpart_date,
112 "0"]]
113126
114 def create(self, cr, uid, ids, data, context=None):127 def create(self, cr, uid, ids, data, context=None):
115 if context is None:128 if context is None:
116 context = {}129 context = {}
117 # US-2303 Data should always be in English whatever the language settings130 # data should always be in English whatever the language settings
118 context.update({'lang': 'en_MF'})131 context.update({'lang': 'en_MF'})
119 pool = pooler.get_pool(cr.dbname)132 pool = pooler.get_pool(cr.dbname)
133 rate_obj = pool.get('res.currency.rate')
134 period_obj = pool.get('account.period')
135 inst_obj = pool.get('msf.instance')
136 aml_obj = pool.get('account.move.line')
137 aal_obj = pool.get('account.analytic.line')
138 rates = {} # store the rates already computed
120139
121 first_header = ['Proprietary Instance',140 first_header = ['Proprietary Instance',
122 'Journal Code',141 'Journal Code',
@@ -127,6 +146,7 @@
127 'Posting Date',146 'Posting Date',
128 'Period',147 'Period',
129 'G/L Account',148 'G/L Account',
149 'Unifield Account',
130 'Destination',150 'Destination',
131 'Cost Centre',151 'Cost Centre',
132 'Funding Pool',152 'Funding Pool',
@@ -136,38 +156,49 @@
136 'Booking Currency',156 'Booking Currency',
137 'Functional Debit',157 'Functional Debit',
138 'Functional Credit',158 'Functional Credit',
139 'Functional Currency',159 'Functional Currency']
140 'Exchange Rate']160
161 second_header = ['Proprietary Instance',
162 'Journal Code',
163 'Entry Sequence',
164 'Description',
165 'Reference',
166 'Document Date',
167 'Posting Date',
168 'Period',
169 'G/L Account',
170 'Destination',
171 'Department',
172 'Cost Centre',
173 'Third Parties',
174 'Employee Id',
175 'Exchange rate',
176 'Booking Debit',
177 'Booking Credit',
178 'Booking Currency',
179 'Field Activity']
180
181 period = period_obj.browse(cr, uid, data['form']['period_id'], context=context)
182
183 # list the journal types for which the rate used will always be 1
184 # i.e. REVAL, Curr. Adjustment, and Accrual
185 no_rate_journal_types = ['revaluation', 'cur_adj', 'accrual']
186 no_rate_analytic_journal_types = ['revaluation', 'cur_adj', 'general'] # Analytic Accrual Journals have the type General
141187
142 # Initialize lists: one for the first report...188 # Initialize lists: one for the first report...
143 first_result_lines = []189 first_result_lines = []
144 # ...one for the second report...190 # ...and subdivisions for the second report.
145 second_result_lines = []191 second_result_lines = []
146 # ...and subdivisions for the third report.192 main_lines = {}
147 third_report = []
148 account_lines = []
149 account_lines_debit = {}193 account_lines_debit = {}
150 account_lines_functional_debit = {}194 # Get department code filled in through the country code mapping
151 rate_req = "SELECT rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s ORDER BY name desc LIMIT 1"195 department_info = ""
152 # US-118: func debit with no FXA currency adjustement entries196 field_activity = "" # always empty
153 account_lines_functional_debit_no_ccy_adj = {}197 parent_instance = False
154 journal_exclude_subtotal_ids = pool.get('account.journal').search(cr,
155 uid, [('type', 'in', ('cur_adj', 'revaluation'))], context=context)
156 # General variables
157 period = pool.get('account.period').browse(cr, uid, data['form']['period_id'])
158 period_name = period and period.code or "0"
159 counterpart_date = period and period.date_stop and \
160 datetime.datetime.strptime(period.date_stop, '%Y-%m-%d').date().strftime('%d/%m/%Y') or ""
161 integration_ref = "0"
162 country_code = "0"
163 move_prefix = "0"
164 if len(data['form']['instance_ids']) > 0:198 if len(data['form']['instance_ids']) > 0:
165 parent_instance = pool.get('msf.instance').browse(cr, uid, data['form']['instance_ids'][0], context=context)199 parent_instance = inst_obj.browse(cr, uid, data['form']['instance_ids'][0], context=context)
166 if parent_instance:200 if parent_instance:
167 country_code = self.translate_country(cr, uid, pool, parent_instance)201 department_info = self.translate_country(cr, uid, pool, parent_instance, context=context)
168 if period and period.date_start:
169 integration_ref = parent_instance.code[:2] + period.date_start[5:7]
170 move_prefix = parent_instance.move_prefix[:2]
171202
172 # UFTP-375: Add export all/previous functionality203 # UFTP-375: Add export all/previous functionality
173 selection = data['form'].get('selection', False)204 selection = data['form'].get('selection', False)
@@ -181,66 +212,30 @@
181 else:212 else:
182 raise osv.except_osv(_('Error'), _('Wrong value for selection: %s.') % (selection,))213 raise osv.except_osv(_('Error'), _('Wrong value for selection: %s.') % (selection,))
183214
184 last_processed_journal = False215 move_line_ids = aml_obj.search(cr, uid, [('period_id', '=', data['form']['period_id']),
185 move_line_ids = pool.get('account.move.line').search(cr, uid, [('period_id', '=', data['form']['period_id']),216 ('instance_id', 'in', data['form']['instance_ids']),
186 ('instance_id', 'in', data['form']['instance_ids']),217 ('account_id.is_analytic_addicted', '=', False),
187 ('account_id.is_analytic_addicted', '=', False),218 ('journal_id.type', 'not in', ['migration', 'hq']),
188 ('journal_id.type', 'not in', ['hq', 'migration']),219 ('exported', 'in', to_export)],
189 ('exported', 'in', to_export)], context=context)220 context=context)
190 # US-274/2: remove 'Inkind', 'OD-Extra Accounting' entries from both
191 # in Upbalances and Upexpenses files
192 exclude_jn_type_for_balance_and_expense_report = (
193 'inkind',
194 'extra',
195 )
196221
197 nb_move_line = len(move_line_ids)222 nb_move_line = len(move_line_ids)
198 move_line_count = 0223 move_line_count = 0
199
200 if 'background_id' in context:224 if 'background_id' in context:
201 bg_id = context['background_id']225 bg_id = context['background_id']
202 else:226 else:
203 bg_id = None227 bg_id = None
204228
205 # assume that this for loop is about 40% of the total treatment229 move_share = 0.4 # 40% of the total process
206 move_share = 0.4
207230
208 for move_line in pool.get('account.move.line').browse(cr, uid, move_line_ids, context=context):231 for move_line in aml_obj.browse(cr, uid, move_line_ids, context=context):
232 if move_line.move_id.state != 'posted': # only posted move lines are kept
233 move_line_count += 1
234 continue
209 journal = move_line.journal_id235 journal = move_line.journal_id
210 if journal:
211 last_processed_journal = journal
212 account = move_line.account_id236 account = move_line.account_id
213 currency = move_line.currency_id237 currency = move_line.currency_id
214 func_currency = move_line.functional_currency_id238 # For the first report:
215 rate = ZERO_CELL_CONTENT
216
217 is_cur_adj_entry = move_line.journal_id \
218 and move_line.journal_id.type == 'cur_adj' or False
219 is_rev_entry = move_line.journal_id \
220 and move_line.journal_id.type == 'revaluation' or False
221
222 if currency and func_currency:
223 # US-274/9: accrual account (always refer to previous period)
224 # base on doc date instead posting in this case
225 # - 1st period accruals: doc date and posting same period
226 # - next accruals: doc date previous period (accrual of)
227 move_line_date = move_line.journal_id \
228 and move_line.journal_id.type == 'accrual' \
229 and move_line.document_date or move_line.date
230
231 if move_line.journal_id.type == 'correction' and move_line.source_date:
232 # US-1525 For the Correction entries display the rate of the entry period corrected
233 move_line_date = move_line.source_date
234 cr.execute(rate_req, (move_line.functional_currency_id.id, move_line_date))
235 if cr.rowcount:
236 func_rate = cr.fetchall()[0][0]
237 cr.execute(rate_req, (currency.id, move_line_date))
238 if cr.rowcount:
239 curr_rate = cr.fetchall()[0][0]
240 if func_rate != 0.00:
241 rate = round(1 / (curr_rate / func_rate), 8)
242
243 # For first report: as it
244 formatted_data = [move_line.instance_id and move_line.instance_id.code or "",239 formatted_data = [move_line.instance_id and move_line.instance_id.code or "",
245 journal and journal.code or "",240 journal and journal.code or "",
246 move_line.move_id and move_line.move_id.name or "",241 move_line.move_id and move_line.move_id.name or "",
@@ -249,6 +244,7 @@
249 datetime.datetime.strptime(move_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),244 datetime.datetime.strptime(move_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),
250 datetime.datetime.strptime(move_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),245 datetime.datetime.strptime(move_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),
251 move_line.period_id and move_line.period_id.code or "",246 move_line.period_id and move_line.period_id.code or "",
247 self.translate_account(cr, uid, pool, account, context=context),
252 account and account.code + " " + account.name,248 account and account.code + " " + account.name,
253 "",249 "",
254 "",250 "",
@@ -259,79 +255,74 @@
259 currency and currency.name or "",255 currency and currency.name or "",
260 round(move_line.debit, 2),256 round(move_line.debit, 2),
261 round(move_line.credit, 2),257 round(move_line.credit, 2),
262 func_currency and func_currency.name or "",258 move_line.functional_currency_id and move_line.functional_currency_id.name or ""]
263 rate]
264 first_result_lines.append(formatted_data)259 first_result_lines.append(formatted_data)
265 if is_cur_adj_entry or is_rev_entry:260
266 # US-788/1 and US-478/3: FXA/REV raw data override261 # For the second report:
267 # without impacting formatted_data for other files262 # exclude In-kind Donations and OD-Extra Accounting entries from the "formatted data" file
268 # US-788/1: always display booking as func263 if move_line.journal_id.type not in ['inkind', 'extra']:
269 # US-478/3 always rate of 1264 if not account.shrink_entries_for_hq:
270 first_result_lines[-1][13] = first_result_lines[-1][16] # US-788/1265 # data for the "Employee Id" column
271 first_result_lines[-1][14] = first_result_lines[-1][17] # US-788/1266 employee_id = ''
272 first_result_lines[-1][15] = first_result_lines[-1][18] # US-788/1267 if move_line.employee_id and move_line.employee_id.employee_type == 'ex': # expat staff
273 first_result_lines[-1][-1] = 1. # US-478/3268 employee_id = move_line.employee_id.identification_id or ''
274269 # data for the columns: Exchange rate, Booking Debit, Booking Credit, Booking Currency
275 # For third report: add to corresponding sub270 exchange_rate = 0
276 if journal and journal.type not in (271 booking_amounts = [round(move_line.debit_currency, 2), round(move_line.credit_currency, 2)]
277 exclude_jn_type_for_balance_and_expense_report): # US-274/2272 booking_curr = formatted_data[16:17]
278 if not account.shrink_entries_for_hq or is_rev_entry or is_cur_adj_entry:273 if move_line.journal_id.type in no_rate_journal_types:
279 # US-478/1: or is_rev_entry, no shrink for rev journal entries274 # use 1 as exchange rate and display the functional values in the "booking" columns
280 expat_identification = "0"275 exchange_rate = 1
281 expat_employee = "0"276 booking_amounts = [round(move_line.debit, 2), round(move_line.credit, 2)]
282 # Expat employees are the only third party in this report277 booking_curr = formatted_data[19:20]
283 if move_line.partner_txt and move_line.employee_id and move_line.employee_id.employee_type == 'ex':278 # automatic corrections
284 if account.code == '15640': # US-274/7279 elif move_line.journal_id.type == 'correction' and (move_line.corrected_line_id or move_line.reversal_line_id):
285 expat_identification = move_line.employee_id.identification_id280 # If there are several levels of correction use the last one
286 expat_employee = move_line.partner_txt281 corr_aml = move_line.corrected_line_id or move_line.reversal_line_id # JI corrected or reversed
287282 initial_id = -1
288 # US-274/1: for FXA/REV entries output fonctional amount in balance283 final_id = -2
289 # report284 while initial_id != final_id:
290 if is_cur_adj_entry or is_rev_entry:285 initial_id = corr_aml.id
291 output_debit = move_line.debit286 # check if the corrected line corrects another line
292 output_credit = move_line.credit287 corr_aml = corr_aml.corrected_line_id or corr_aml
293 output_rate = 1.288 final_id = corr_aml.id
294 output_curr = func_currency and func_currency.name or "0"289 # rate of the original corrected entry
295 else:290 if currency.id not in rates:
296 output_debit = move_line.debit_currency291 rates[currency.id] = {}
297 output_credit = move_line.credit_currency292 if corr_aml.date not in rates[currency.id]:
298 output_rate = rate293 rate = 0
299 output_curr = currency and currency.name or "0"294 rate_ids = rate_obj.search(cr, uid, [('currency_id', '=', currency.id), ('name', '<=', corr_aml.date)],
300295 order='name DESC', limit=1, context=context)
301 other_formatted_data = ["01",296 if rate_ids:
302 country_code,297 rate = rate_obj.browse(cr, uid, rate_ids[0], fields_to_fetch=['rate'], context=context).rate
303 account and account.code or "0",298 rates[currency.id][corr_aml.date] = rate
304 expat_identification,299 exchange_rate = rates[currency.id][corr_aml.date]
305 "0",300 # other lines
306 move_line.date and datetime.datetime.strptime(move_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y') or "0",301 elif currency:
307 output_curr,302 # rate of the period selected
308 output_rate,303 if currency.id not in rates:
309 output_debit != 0.0 and round(output_debit, 2) or "",304 rates[currency.id] = {}
310 output_credit != 0.0 and round(output_credit, 2) or "",305 if period.date_start not in rates[currency.id]:
311 move_line.move_id and move_line.move_id.name or "0",306 rate = 0
312 move_line.name or "0",307 rate_ids = rate_obj.search(cr, uid, [('currency_id', '=', currency.id), ('name', '<=', period.date_start)],
313 move_line.ref or "",308 order='name DESC', limit=1, context=context)
314 expat_employee,309 if rate_ids:
315 move_line.document_date and datetime.datetime.strptime(move_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y') or "0",310 rate = rate_obj.browse(cr, uid, rate_ids[0], fields_to_fetch=['rate'], context=context).rate
316 move_line.ref or "0"]311 rates[currency.id][period.date_start] = rate
317 account_lines.append(other_formatted_data)312 exchange_rate = rates[currency.id][period.date_start]
313
314 if (journal.code, journal.id, currency.id) not in main_lines:
315 main_lines[(journal.code, journal.id, currency.id)] = []
316 main_lines[(journal.code, journal.id, currency.id)].append(formatted_data[:9] + [formatted_data[10]] +
317 [department_info] + [formatted_data[11]] +
318 [formatted_data[13]] + [employee_id] +
319 [exchange_rate] + booking_amounts +
320 booking_curr + [field_activity])
318 else:321 else:
319 if (account.code, currency.name, period_name) not in account_lines_debit:322 translated_account_code = self.translate_account(cr, uid, pool, account, context=context)
320 account_lines_debit[(account.code, currency.name, period_name)] = 0.0323 if (translated_account_code, currency.id) not in account_lines_debit:
321 account_lines_functional_debit[(account.code, currency.name, period_name)] = 0.0324 account_lines_debit[(translated_account_code, currency.id)] = 0.0
322 account_lines_functional_debit_no_ccy_adj[(account.code, currency.name, period_name)] = 0.0325 account_lines_debit[(translated_account_code, currency.id)] += (move_line.debit_currency - move_line.credit_currency)
323
324 account_lines_debit[(account.code, currency.name, period_name)] += (move_line.debit_currency - move_line.credit_currency)
325 funct_balance = (move_line.debit - move_line.credit)
326 account_lines_functional_debit[(account.code, currency.name, period_name)] += funct_balance
327
328 # US-118: func debit with no FXA currency adjustement entries
329 # compute subtotal line inverted rate with no FXA entry:
330 # no booking amount but funct one then cause a wrong balance
331 # for ccy inverted rate computation
332 if not journal_exclude_subtotal_ids or \
333 move_line.journal_id.id not in journal_exclude_subtotal_ids:
334 account_lines_functional_debit_no_ccy_adj[(account.code, currency.name, period_name)] += funct_balance
335326
336 move_line_count += 1327 move_line_count += 1
337 if move_line_count % 30 == 0:328 if move_line_count % 30 == 0:
@@ -343,124 +334,113 @@
343 self.shared_update_percent(cr, uid, pool, [bg_id],334 self.shared_update_percent(cr, uid, pool, [bg_id],
344 share=move_share, finished=True)335 share=move_share, finished=True)
345336
346 # UFTP-375: Do not include FREE1 and FREE2 analytic lines337 analytic_line_ids = aal_obj.search(cr, uid, [('period_id', '=', data['form']['period_id']),
347 # US-817: search period from JI (VI from HQ so AJI always with its JI)338 ('instance_id', 'in', data['form']['instance_ids']),
348 # (AJI period_id is a field function always deduced from date since UTP-943)339 ('journal_id.type', 'not in', ['migration', 'hq', 'engagement']),
349 analytic_line_ids = pool.get('account.analytic.line').search(cr, uid, [('period_id', '=', data['form']['period_id']),340 ('account_id.category', 'not in', ['FREE1', 'FREE2']),
350 ('instance_id', 'in', data['form']['instance_ids']),341 ('exported', 'in', to_export)], context=context)
351 ('journal_id.type', 'not in', ['hq', 'engagement', 'migration']),
352 ('account_id.category', 'not in', ['FREE1', 'FREE2']),
353 ('exported', 'in', to_export)], context=context)
354
355 nb_analytic_line = len(analytic_line_ids)342 nb_analytic_line = len(analytic_line_ids)
356 analytic_line_count = 0343 analytic_line_count = 0
357344
358 # assume that this for loop is about 50% of the total treatment345 analytic_share = 0.5 # 50% of the total process
359 analytic_share = 0.5
360346
361 for analytic_line in pool.get('account.analytic.line').browse(cr, uid, analytic_line_ids, context=context):347 for analytic_line in aal_obj.browse(cr, uid, analytic_line_ids, context=context):
362 journal = analytic_line.move_id and analytic_line.move_id.journal_id or False348 # restrict to analytic lines coming from posted move lines
363 if journal:349 if analytic_line.move_state != 'posted':
364 last_processed_journal = journal350 analytic_line_count += 1
351 continue
352 journal = analytic_line.move_id and analytic_line.move_id.journal_id
365 account = analytic_line.general_account_id353 account = analytic_line.general_account_id
366 currency = analytic_line.currency_id354 currency = analytic_line.currency_id
367 func_currency = analytic_line.move_id.functional_currency_id355 cost_center_code = analytic_line.cost_center_id and analytic_line.cost_center_id.code or ""
368 rate = ""
369
370 # US-478 - US-274/9 accrual account always refer to previous period
371 # base on doc date instead posting in this case
372 # - 1st period accruals: doc date and posting same period
373 # - next accruals: doc date previous period (accrual of)
374 ldate = analytic_line.date
375 if analytic_line.move_id:
376 if analytic_line.move_id.journal_id.type == 'accrual':
377 ldate = analytic_line.document_date or analytic_line.date
378 elif analytic_line.journal_id \
379 and analytic_line.journal_id.code == 'ACC':
380 # sync border case no JI for the AJI
381 ldate = analytic_line.document_date or analytic_line.date
382
383 if func_currency:
384 if analytic_line.journal_id.type == 'correction' and analytic_line.source_date:
385 # US-1525 For the Correction entries display the rate of the entry period corrected
386 ldate = analytic_line.source_date
387 cr.execute(rate_req, (currency.id, ldate))
388 if cr.rowcount:
389 rate = round(1 / cr.fetchall()[0][0], 8)
390
391 is_analytic_cur_adj_entry = analytic_line.journal_id \
392 and analytic_line.journal_id.type == 'cur_adj' or False
393 is_analytic_rev_entry = analytic_line.journal_id \
394 and analytic_line.journal_id.type == 'revaluation' or False
395
396 # US-1375: cancel US-817
397 aji_period_id = analytic_line and analytic_line.period_id or False356 aji_period_id = analytic_line and analytic_line.period_id or False
398357
399 # For first report: as is358 # For the first report:
400 formatted_data = [analytic_line.instance_id and analytic_line.instance_id.code or "",359 formatted_data = [analytic_line.instance_id and analytic_line.instance_id.code or "",
401 analytic_line.journal_id and analytic_line.journal_id.code or "",360 analytic_line.journal_id and analytic_line.journal_id.code or "",
402 analytic_line.entry_sequence or "",361 analytic_line.entry_sequence or analytic_line.move_id and analytic_line.move_id.move_id and analytic_line.move_id.move_id.name or "",
403 analytic_line.name or "",362 analytic_line.name or "",
404 analytic_line.ref or "",363 analytic_line.ref or "",
405 datetime.datetime.strptime(analytic_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),364 datetime.datetime.strptime(analytic_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),
406 datetime.datetime.strptime(analytic_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),365 datetime.datetime.strptime(analytic_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y'),
407 aji_period_id and aji_period_id.code or "",366 aji_period_id and aji_period_id.code or "",
367 self.translate_account(cr, uid, pool, account, context=context),
408 account and account.code + " " + account.name or "",368 account and account.code + " " + account.name or "",
409 analytic_line.destination_id and analytic_line.destination_id.code or "",369 analytic_line.destination_id and analytic_line.destination_id.code or "",
410 analytic_line.cost_center_id and analytic_line.cost_center_id.code or "",370 cost_center_code,
411 analytic_line.account_id and analytic_line.account_id.code or "",371 analytic_line.account_id and analytic_line.account_id.code or "",
412 analytic_line.partner_txt or "",372 analytic_line.partner_txt or "",
413 analytic_line.amount_currency > 0 and ZERO_CELL_CONTENT or round(-analytic_line.amount_currency, 2),373 analytic_line.amount_currency > 0 and "0.00" or round(-analytic_line.amount_currency, 2),
414 analytic_line.amount_currency > 0 and round(analytic_line.amount_currency, 2) or ZERO_CELL_CONTENT,374 analytic_line.amount_currency > 0 and round(analytic_line.amount_currency, 2) or "0.00",
415 currency and currency.name or "",375 currency and currency.name or "",
416 analytic_line.amount > 0 and ZERO_CELL_CONTENT or round(-analytic_line.amount, 2),376 analytic_line.amount > 0 and "0.00" or round(-analytic_line.amount, 2),
417 analytic_line.amount > 0 and round(analytic_line.amount, 2) or ZERO_CELL_CONTENT,377 analytic_line.amount > 0 and round(analytic_line.amount, 2) or "0.00",
418 func_currency and func_currency.name or "",378 analytic_line.functional_currency_id and analytic_line.functional_currency_id.name or ""]
419 rate]
420 first_result_lines.append(formatted_data)379 first_result_lines.append(formatted_data)
421 if is_analytic_cur_adj_entry or is_analytic_rev_entry:380
422 # US-788/1 and US-478/3: FXA/REV raw data override381 # exclude In-kind Donations and OD-Extra Accounting entries from the "formatted data" file
423 # without impacting formatted_data for other files382 if analytic_line.journal_id.type not in ['inkind', 'extra']:
424 # US-788/1: always display booking as func383 # format CC as: P + the 4 digits from the right
425 # US-478/3 always rate of 1384 cost_center = formatted_data[11] and "P%s" % formatted_data[11][-4:] or ""
426 first_result_lines[-1][13] = first_result_lines[-1][16] # US-788/1385 # data for the "Employee Id" column
427 first_result_lines[-1][14] = first_result_lines[-1][17] # US-788/1386 employee_id = ''
428 first_result_lines[-1][15] = first_result_lines[-1][18] # US-788/1387 if analytic_line.move_id and analytic_line.move_id.employee_id and analytic_line.move_id.employee_id.employee_type == 'ex': # expat staff
429 first_result_lines[-1][-1] = 1. # US-478/3388 employee_id = analytic_line.move_id.employee_id.identification_id or ''
430 if analytic_line.journal_id \389
431 and analytic_line.journal_id.type not in (390 # data for the columns: Exchange rate, Booking Debit, Booking Credit, Booking Currency
432 exclude_jn_type_for_balance_and_expense_report): # US-274/2391 exchange_rate = 0
433 # Add to second report (expenses only)392 booking_amounts = [analytic_line.amount_currency > 0 and "0.00" or round(-analytic_line.amount_currency, 2),
434 up_exp_ccy = currency393 analytic_line.amount_currency > 0 and round(analytic_line.amount_currency, 2) or "0.00"]
435 up_exp_rate = rate394 booking_curr = formatted_data[16:17]
436 up_exp_amount = analytic_line.amount_currency395 if analytic_line.journal_id.type in no_rate_analytic_journal_types:
437396 # use 1 as exchange rate and display the functional values in the "booking" columns
438 if is_analytic_rev_entry:397 exchange_rate = 1
439 # US-1008 for up_expenses (file 2), match REV AJIs to JIs:398 booking_amounts = [analytic_line.amount > 0 and "0.00" or round(-analytic_line.amount, 2),
440 # display AJIs booked on REV journal in func ccy and rate 1399 analytic_line.amount > 0 and round(analytic_line.amount, 2) or "0.00"]
441 # as already done here for JIs of up_balances (file 3)400 booking_curr = formatted_data[19:20]
442 up_exp_ccy = func_currency401 # automatic corrections
443 up_exp_rate = 1.402 elif analytic_line.journal_id.type == 'correction' and (analytic_line.last_corrected_id or analytic_line.reversal_origin):
444 up_exp_amount = analytic_line.amount403 # If there are several levels of correction use the last one
445404 corr_aal = analytic_line.last_corrected_id or analytic_line.reversal_origin # AJI corrected or reversed
446 other_formatted_data = [integration_ref ,405 initial_id = -1
447 analytic_line.document_date and datetime.datetime.strptime(analytic_line.document_date, '%Y-%m-%d').date().strftime('%d/%m/%Y') or "0",406 final_id = -2
448 "0",407 while initial_id != final_id:
449 "0",408 initial_id = corr_aal.id
450 analytic_line.cost_center_id and analytic_line.cost_center_id.code or "0",409 # check if the corrected line corrects another line
451 "1",410 corr_aal = corr_aal.last_corrected_id or corr_aal
452 account and account.code + " " + account.name or "0",411 final_id = corr_aal.id
453 up_exp_ccy and up_exp_ccy.name or "0",412 # rate of the original corrected entry
454 up_exp_amount and round(-up_exp_amount, 2) or ZERO_CELL_CONTENT,413 if currency.id not in rates:
455 "0",414 rates[currency.id] = {}
456 up_exp_rate,415 if corr_aal.date not in rates[currency.id]:
457 analytic_line.date and datetime.datetime.strptime(analytic_line.date, '%Y-%m-%d').date().strftime('%d/%m/%Y') or "0",416 rate = 0
458 analytic_line.entry_sequence or "0",417 rate_ids = rate_obj.search(cr, uid, [('currency_id', '=', currency.id), ('name', '<=', corr_aal.date)],
459 "0",418 order='name DESC', limit=1, context=context)
460 analytic_line.name or "0",419 if rate_ids:
461 analytic_line.ref or "0",420 rate = rate_obj.browse(cr, uid, rate_ids[0], fields_to_fetch=['rate'], context=context).rate
462 analytic_line.destination_id and analytic_line.destination_id.code or "0"]421 rates[currency.id][corr_aal.date] = rate
463 second_result_lines.append(other_formatted_data)422 exchange_rate = rates[currency.id][corr_aal.date]
423 # other lines
424 elif currency:
425 # rate of the period selected
426 if currency.id not in rates:
427 rates[currency.id] = {}
428 if period.date_start not in rates[currency.id]:
429 rate = 0
430 rate_ids = rate_obj.search(cr, uid, [('currency_id', '=', currency.id), ('name', '<=', period.date_start)],
431 order='name DESC', limit=1, context=context)
432 if rate_ids:
433 rate = rate_obj.browse(cr, uid, rate_ids[0], fields_to_fetch=['rate'], context=context).rate
434 rates[currency.id][period.date_start] = rate
435 exchange_rate = rates[currency.id][period.date_start]
436
437 if (journal.code, journal.id, currency.id) not in main_lines:
438 main_lines[(journal.code, journal.id, currency.id)] = []
439 main_lines[(journal.code, journal.id, currency.id)].append(formatted_data[:9] + [formatted_data[10]] +
440 [department_info] + [cost_center] +
441 [formatted_data[13]] + [employee_id] +
442 [exchange_rate] + booking_amounts +
443 booking_curr + [field_activity])
464444
465 analytic_line_count += 1445 analytic_line_count += 1
466 if analytic_line_count % 30 == 0:446 if analytic_line_count % 30 == 0:
@@ -474,69 +454,58 @@
474 share=analytic_share, finished=True, already_done=move_share)454 share=analytic_share, finished=True, already_done=move_share)
475455
476 first_result_lines = sorted(first_result_lines, key=lambda line: line[2])456 first_result_lines = sorted(first_result_lines, key=lambda line: line[2])
477 if not move_line_ids and not analytic_line_ids:457 first_report = [first_header] + first_result_lines
478 first_report = []458
479 else:459 counterpart_date = period and period.date_stop and \
480 first_report = [first_header] + first_result_lines460 datetime.datetime.strptime(period.date_stop, '%Y-%m-%d').date().strftime('%d/%m/%Y') or ""
481461
482 second_report = sorted(second_result_lines, key=lambda line: line[12])462 # regroup second report lines
483463 for key in sorted(main_lines.iterkeys(), key=lambda tuple: tuple[0]):
484 for line in sorted(account_lines, key=lambda line: line[10]):464 second_result_lines += sorted(main_lines[key], key=lambda line: line[2])
485 third_report.append(line)465
486 third_report.append(self.create_counterpart(cr, uid, line))466 for key in sorted(account_lines_debit.iterkeys(), key=lambda tuple: tuple[0]):
487467 # for entries "shrunk for HQ export"
488 if last_processed_journal and last_processed_journal.type not in (468 subtotal_lines = self.create_subtotal(cr, uid, key, account_lines_debit[key], counterpart_date, period,
489 exclude_jn_type_for_balance_and_expense_report): # US-274/2469 department_info, field_activity, context=context)
490 for key in sorted(account_lines_debit.iterkeys(), key=lambda tuple: tuple[0]):470 if subtotal_lines:
491 # create the sequence number for those lines471 second_result_lines += subtotal_lines
492 sequence_number = move_prefix + "-" + \
493 period.date_start[5:7] + "-" + \
494 period.date_start[:4] + "-" + \
495 key[0] + "-" + \
496 key[1]
497
498 subtotal_lines = self.create_subtotal(cr, uid, key,
499 account_lines_debit[key],
500 account_lines_functional_debit[key],
501 account_lines_functional_debit_no_ccy_adj[key],
502 counterpart_date,
503 country_code,
504 sequence_number)
505 if subtotal_lines:
506 third_report += subtotal_lines
507472
508 self.shared_update_percent(cr, uid, pool, [bg_id],473 self.shared_update_percent(cr, uid, pool, [bg_id],
509 share=0.05, finished=True,474 share=0.05, finished=True,
510 already_done=move_share+analytic_share)475 already_done=move_share+analytic_share)
511476
512 # Write result to the final content477 second_report = [second_header] + second_result_lines
478
479 # set prefix for file names
480 mission_code = ''
481 if parent_instance:
482 mission_code = "%s" % parent_instance.code[:3]
483 tm = strptime(period.date_start, '%Y-%m-%d')
484 year = str(tm.tm_year)
485 period_number = period and period.number and '%02d' % period.number or ''
486 prefix = '%sY%sP%s_' % (mission_code, year, period_number)
487
513 zip_buffer = StringIO.StringIO()488 zip_buffer = StringIO.StringIO()
514 first_fileobj = NamedTemporaryFile('w+b', delete=False)489 first_fileobj = NamedTemporaryFile('w+b', delete=False)
515 second_fileobj = NamedTemporaryFile('w+b', delete=False)490 second_fileobj = NamedTemporaryFile('w+b', delete=False)
516 third_fileobj = NamedTemporaryFile('w+b', delete=False)491 # for Raw data file: use double quotes for all entries
517 writer = csv.writer(first_fileobj, quoting=csv.QUOTE_ALL)492 writer = csv.writer(first_fileobj, quoting=csv.QUOTE_ALL, delimiter=",")
518 for line in first_report:493 for line in first_report:
519 writer.writerow(map(self._enc,line))494 writer.writerow(map(self._enc, line))
520 first_fileobj.close()495 first_fileobj.close()
521 writer = csv.writer(second_fileobj, quoting=csv.QUOTE_ALL)496 # for formatted data file: use double quotes only for entries containing double quote or comma
497 writer = csv.writer(second_fileobj, quoting=csv.QUOTE_MINIMAL, delimiter=",")
522 for line in second_report:498 for line in second_report:
523 writer.writerow(map(self._enc,line))499 writer.writerow(map(self._enc, line))
524 second_fileobj.close()500 second_fileobj.close()
525 writer = csv.writer(third_fileobj, quoting=csv.QUOTE_ALL)501
526 for line in third_report:
527 line.pop()
528 line.pop()
529 writer.writerow(map(self._enc,line))
530 third_fileobj.close()
531 out_zipfile = zipfile.ZipFile(zip_buffer, "w")502 out_zipfile = zipfile.ZipFile(zip_buffer, "w")
532 out_zipfile.write(first_fileobj.name, "%sRaw_Data.csv" % (integration_ref and integration_ref+'_' or ''), zipfile.ZIP_DEFLATED)503 out_zipfile.write(first_fileobj.name, prefix + "Raw data UF export.csv", zipfile.ZIP_DEFLATED)
533 out_zipfile.write(second_fileobj.name, "%sUp_Expenses.csv" % (integration_ref and integration_ref+'_' or ''), zipfile.ZIP_DEFLATED)504 out_zipfile.write(second_fileobj.name, prefix + "formatted data D365 import.csv", zipfile.ZIP_DEFLATED)
534 out_zipfile.write(third_fileobj.name, "%sUp_Balances.csv" % (integration_ref and integration_ref+'_' or ''), zipfile.ZIP_DEFLATED)
535 out_zipfile.close()505 out_zipfile.close()
536 out = zip_buffer.getvalue()506 out = zip_buffer.getvalue()
537 os.unlink(first_fileobj.name)507 os.unlink(first_fileobj.name)
538 os.unlink(second_fileobj.name)508 os.unlink(second_fileobj.name)
539 os.unlink(third_fileobj.name)
540509
541 # Mark lines as exported510 # Mark lines as exported
542 if move_line_ids:511 if move_line_ids:
543512
=== modified file 'bin/addons/vertical_integration/wizard/wizard_hq_report_oca.py'
--- bin/addons/vertical_integration/wizard/wizard_hq_report_oca.py 2017-03-16 17:04:51 +0000
+++ bin/addons/vertical_integration/wizard/wizard_hq_report_oca.py 2019-06-07 09:34:36 +0000
@@ -23,6 +23,8 @@
23from tools.translate import _23from tools.translate import _
24assert _ # pyflakes24assert _ # pyflakes
25import time25import time
26from time import strptime
27
2628
27class wizard_hq_report_oca(osv.osv_memory):29class wizard_hq_report_oca(osv.osv_memory):
28 _name = "wizard.hq.report.oca"30 _name = "wizard.hq.report.oca"
@@ -60,14 +62,21 @@
60 data = {}62 data = {}
61 # add parameters63 # add parameters
62 data['form'] = {}64 data['form'] = {}
65 mission_code = ''
66 year = ''
67 period_number = ''
63 if wizard.instance_id:68 if wizard.instance_id:
69 mission_code = "%s" % wizard.instance_id.code[:3]
64 # Get projects below instance70 # Get projects below instance
65 data['form'].update({'instance_ids': [wizard.instance_id.id] + [x.id for x in wizard.instance_id.child_ids]})71 data['form'].update({'instance_ids': [wizard.instance_id.id] + [x.id for x in wizard.instance_id.child_ids]})
66 if wizard.period_id:72 if wizard.period_id:
73 tm = strptime(wizard.period_id.date_start, '%Y-%m-%d')
74 year = str(tm.tm_year)
75 period_number = wizard.period_id.number and '%02d' % wizard.period_id.number or ''
67 data['form'].update({'period_id': wizard.period_id.id})76 data['form'].update({'period_id': wizard.period_id.id})
68 # UFTP-375: Permit user to select all lines or only previous ones77 # UFTP-375: Permit user to select all lines or only previous ones
69 data['form'].update({'selection': wizard.selection})78 data['form'].update({'selection': wizard.selection})
70 data['target_filename'] = '%s_%s_%s' % (_('Export to HQ System'), wizard.instance_id and wizard.instance_id.code or '', time.strftime('%Y%m%d'))79 data['target_filename'] = '%sY%sP%s_formatted data D365 import' % (mission_code, year, period_number)
7180
72 background_id = self.pool.get('memory.background.report').create(cr, uid, {81 background_id = self.pool.get('memory.background.report').create(cr, uid, {
73 'file_name': data['target_filename'],82 'file_name': data['target_filename'],

Subscribers

People subscribed via source and target branches