Merge lp:~julie-w/unifield-server/US-8001 into lp:unifield-server
- US-8001
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 5993 |
Proposed branch: | lp:~julie-w/unifield-server/US-8001 |
Merge into: | lp:unifield-server |
Diff against target: |
2031 lines (+1072/-124) (has conflicts) 30 files modified
bin/addons/account_corrections/wizard/analytic_distribution_wizard.py (+18/-31) bin/addons/account_hq_entries/hq_entries.py (+11/-0) bin/addons/account_hq_entries/wizard/hq_entries_split.py (+3/-1) bin/addons/analytic_distribution/account_commitment.py (+16/-2) bin/addons/analytic_distribution/analytic_account_view.xml (+24/-8) bin/addons/analytic_distribution/analytic_distribution.py (+27/-9) bin/addons/analytic_distribution/analytic_line.py (+33/-14) bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py (+5/-1) bin/addons/analytic_override/__init__.py (+2/-0) bin/addons/analytic_override/__openerp__.py (+2/-0) bin/addons/analytic_override/analytic_account.py (+197/-29) bin/addons/analytic_override/analytic_line.py (+6/-0) bin/addons/analytic_override/dest_cc_link.py (+174/-0) bin/addons/analytic_override/dest_cc_link.xml (+49/-0) bin/addons/analytic_override/multiple_cc_selection_wizard.py (+56/-0) bin/addons/analytic_override/multiple_cc_selection_wizard.xml (+30/-0) bin/addons/financing_contract/financing_contract_account_quadruplet.py (+9/-8) bin/addons/msf_audittrail/__openerp__.py (+4/-0) bin/addons/msf_audittrail/data/audittrail_dest_cc_link.yml (+39/-0) bin/addons/msf_doc_import/msf_import_export.py (+118/-11) bin/addons/msf_doc_import/msf_import_export_conf.py (+3/-1) bin/addons/msf_homere_interface/hr_payroll.py (+28/-1) bin/addons/msf_profile/data/patches.xml (+8/-0) bin/addons/msf_profile/i18n/fr_MF.po (+152/-3) bin/addons/msf_profile/msf_profile.py (+17/-0) bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv (+1/-0) bin/addons/sync_client/update.py (+1/-0) bin/addons/sync_common/common.py (+1/-0) bin/addons/sync_so/specific_xml_id.py (+24/-0) bin/osv/orm.py (+14/-5) Text conflict in bin/addons/msf_audittrail/__openerp__.py Text conflict in bin/addons/msf_profile/data/patches.xml Text conflict in bin/addons/msf_profile/msf_profile.py |
To merge this branch: | bzr merge lp:~julie-w/unifield-server/US-8001 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email: mp+402434@code.launchpad.net |
Commit message
Description of the change
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/account_corrections/wizard/analytic_distribution_wizard.py' | |||
2 | --- bin/addons/account_corrections/wizard/analytic_distribution_wizard.py 2020-09-22 13:17:55 +0000 | |||
3 | +++ bin/addons/account_corrections/wizard/analytic_distribution_wizard.py 2021-05-07 16:01:07 +0000 | |||
4 | @@ -283,38 +283,25 @@ | |||
5 | 283 | old_line = self.pool.get('funding.pool.distribution.line').browse(cr, uid, wiz_line.distribution_line_id.id) | 283 | old_line = self.pool.get('funding.pool.distribution.line').browse(cr, uid, wiz_line.distribution_line_id.id) |
6 | 284 | 284 | ||
7 | 285 | if old_line: | 285 | if old_line: |
39 | 286 | #US-714: For HQ Entries, always create the COR and REV even the period is closed | 286 | # existing line, test modifications |
40 | 287 | original_al_id = ana_line_obj.search(cr, uid, [('distrib_line_id', '=', 'funding.pool.distribution.line,%d'%old_line.id), ('is_reversal', '=', False), ('is_reallocated', '=', False)]) | 287 | # for FP, percentage, CC or destination changes regarding contracts |
41 | 288 | 288 | if old_line.analytic_id.id != wiz_line.analytic_id.id \ | |
42 | 289 | is_HQ_entries = False | 289 | or old_line.percentage != wiz_line.percentage \ |
43 | 290 | if original_al_id and len(original_al_id) == 1: | 290 | or old_line.cost_center_id.id != wiz_line.cost_center_id.id \ |
44 | 291 | original_al = ana_line_obj.browse(cr, uid, original_al_id[0], context) | 291 | or old_line.destination_id.id != wiz_line.destination_id.id: |
45 | 292 | if original_al.journal_id.type == 'hq': | 292 | # FP account changed or % modified |
46 | 293 | is_HQ_entries = True | 293 | if self.pool.get('account.analytic.account').is_blocked_by_a_contract(cr, uid, [old_line.analytic_id.id]): |
47 | 294 | 294 | raise osv.except_osv(_('Error'), _("Funding pool is on a soft/hard closed contract: %s")%(old_line.analytic_id.code)) | |
48 | 295 | # In case it's an HQ entries, just generate the REV and COR | 295 | |
49 | 296 | if is_HQ_entries: | 296 | if (old_line.cost_center_id.id != wiz_line.cost_center_id.id or |
50 | 297 | to_reverse.append(wiz_line) | 297 | old_line.destination_id.id != wiz_line.destination_id.id or |
51 | 298 | else: | 298 | old_line.percentage != wiz_line.percentage): |
52 | 299 | # existing line, test modifications | 299 | if self._check_period_closed_on_fp_distrib_line(cr, uid, old_line.id, is_HQ_origin=is_HQ_origin): |
53 | 300 | # for FP, percentage, CC or destination changes regarding contracts | 300 | to_reverse.append(wiz_line) |
54 | 301 | if old_line.analytic_id.id != wiz_line.analytic_id.id \ | 301 | else: |
24 | 302 | or old_line.percentage != wiz_line.percentage \ | ||
25 | 303 | or old_line.cost_center_id.id != wiz_line.cost_center_id.id \ | ||
26 | 304 | or old_line.destination_id.id != wiz_line.destination_id.id: | ||
27 | 305 | # FP account changed or % modified | ||
28 | 306 | if self.pool.get('account.analytic.account').is_blocked_by_a_contract(cr, uid, [old_line.analytic_id.id]): | ||
29 | 307 | raise osv.except_osv(_('Error'), _("Funding pool is on a soft/hard closed contract: %s")%(old_line.analytic_id.code)) | ||
30 | 308 | |||
31 | 309 | if (old_line.cost_center_id.id != wiz_line.cost_center_id.id or | ||
32 | 310 | old_line.destination_id.id != wiz_line.destination_id.id or | ||
33 | 311 | old_line.percentage != wiz_line.percentage): | ||
34 | 312 | if self._check_period_closed_on_fp_distrib_line(cr, uid, old_line.id): | ||
35 | 313 | to_reverse.append(wiz_line) | ||
36 | 314 | else: | ||
37 | 315 | to_override.append(wiz_line) | ||
38 | 316 | elif old_line.analytic_id.id != wiz_line.analytic_id.id: | ||
55 | 317 | to_override.append(wiz_line) | 302 | to_override.append(wiz_line) |
56 | 303 | elif old_line.analytic_id.id != wiz_line.analytic_id.id: | ||
57 | 304 | to_override.append(wiz_line) | ||
58 | 318 | 305 | ||
59 | 319 | old_line_ok.append(old_line.id) | 306 | old_line_ok.append(old_line.id) |
60 | 320 | 307 | ||
61 | 321 | 308 | ||
62 | === modified file 'bin/addons/account_hq_entries/hq_entries.py' | |||
63 | --- bin/addons/account_hq_entries/hq_entries.py 2021-05-05 16:04:38 +0000 | |||
64 | +++ bin/addons/account_hq_entries/hq_entries.py 2021-05-07 16:01:07 +0000 | |||
65 | @@ -44,6 +44,7 @@ | |||
66 | 44 | res = {} | 44 | res = {} |
67 | 45 | logger = netsvc.Logger() | 45 | logger = netsvc.Logger() |
68 | 46 | ad_obj = self.pool.get('analytic.distribution') | 46 | ad_obj = self.pool.get('analytic.distribution') |
69 | 47 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
70 | 47 | # Search MSF Private Fund element, because it's valid with all accounts | 48 | # Search MSF Private Fund element, because it's valid with all accounts |
71 | 48 | try: | 49 | try: |
72 | 49 | fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', | 50 | fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', |
73 | @@ -87,6 +88,13 @@ | |||
74 | 87 | res[line.id] = 'invalid' | 88 | res[line.id] = 'invalid' |
75 | 88 | logger.notifyChannel('account_hq_entries', netsvc.LOG_WARNING, _('%s: inactive DEST (%s)') % (line.id or '', dest.code or '')) | 89 | logger.notifyChannel('account_hq_entries', netsvc.LOG_WARNING, _('%s: inactive DEST (%s)') % (line.id or '', dest.code or '')) |
76 | 89 | continue | 90 | continue |
77 | 91 | if line.destination_id and line.cost_center_id and line.date and \ | ||
78 | 92 | dest_cc_link_obj.is_inactive_dcl(cr, uid, line.destination_id.id, line.cost_center_id.id, line.date, context=context): | ||
79 | 93 | res[line.id] = 'invalid' | ||
80 | 94 | logger.notifyChannel('account_hq_entries', netsvc.LOG_WARNING, | ||
81 | 95 | _('%s: inactive combination (%s - %s)') % | ||
82 | 96 | (line.id or '', line.destination_id.code or '', line.cost_center_id.code or '')) | ||
83 | 97 | continue | ||
84 | 90 | # G Check | 98 | # G Check |
85 | 91 | if line.analytic_id: | 99 | if line.analytic_id: |
86 | 92 | fp = self.pool.get('account.analytic.account').browse(cr, uid, line.analytic_id.id, context={'date': line.document_date}) | 100 | fp = self.pool.get('account.analytic.account').browse(cr, uid, line.analytic_id.id, context={'date': line.document_date}) |
87 | @@ -485,6 +493,9 @@ | |||
88 | 485 | def _check_cc(self, cr, uid, ids, context=None): | 493 | def _check_cc(self, cr, uid, ids, context=None): |
89 | 486 | """ | 494 | """ |
90 | 487 | At synchro time sets HQ entry to Not Run if the Cost Center used in the line doesn't exist or is inactive | 495 | At synchro time sets HQ entry to Not Run if the Cost Center used in the line doesn't exist or is inactive |
91 | 496 | |||
92 | 497 | Note: if the CC is active but the Dest/CC combination is inactive, the sync update is NOT blocked: | ||
93 | 498 | the HQ entry will be created with an invalid AD to be fixed before validation. | ||
94 | 488 | """ | 499 | """ |
95 | 489 | if isinstance(ids, (int, long)): | 500 | if isinstance(ids, (int, long)): |
96 | 490 | ids = [ids] | 501 | ids = [ids] |
97 | 491 | 502 | ||
98 | === modified file 'bin/addons/account_hq_entries/wizard/hq_entries_split.py' | |||
99 | --- bin/addons/account_hq_entries/wizard/hq_entries_split.py 2020-11-02 17:29:34 +0000 | |||
100 | +++ bin/addons/account_hq_entries/wizard/hq_entries_split.py 2021-05-07 16:01:07 +0000 | |||
101 | @@ -42,7 +42,9 @@ | |||
102 | 42 | # Process | 42 | # Process |
103 | 43 | for line in self.browse(cr, uid, ids, context=context): | 43 | for line in self.browse(cr, uid, ids, context=context): |
104 | 44 | res[line.id] = {'state_info': False, 'state': 'none'} | 44 | res[line.id] = {'state_info': False, 'state': 'none'} |
106 | 45 | state, info = self.pool.get('analytic.distribution').analytic_state_from_info(cr, uid, line.account_id.id, line.destination_id.id, line.cost_center_id.id, line.analytic_id.id, context=context) | 45 | state, info = self.pool.get('analytic.distribution').analytic_state_from_info(cr, uid, line.account_id.id, line.destination_id.id, |
107 | 46 | line.cost_center_id.id, line.analytic_id.id, | ||
108 | 47 | posting_date=line.wizard_id.date, context=context) | ||
109 | 46 | res[line.id].update({'state_info': info, 'state': state,}) | 48 | res[line.id].update({'state_info': info, 'state': state,}) |
110 | 47 | return res | 49 | return res |
111 | 48 | 50 | ||
112 | 49 | 51 | ||
113 | === modified file 'bin/addons/analytic_distribution/account_commitment.py' | |||
114 | --- bin/addons/analytic_distribution/account_commitment.py 2020-05-07 10:01:57 +0000 | |||
115 | +++ bin/addons/analytic_distribution/account_commitment.py 2021-05-07 16:01:07 +0000 | |||
116 | @@ -169,6 +169,7 @@ | |||
117 | 169 | aal_obj = self.pool.get('account.analytic.line') | 169 | aal_obj = self.pool.get('account.analytic.line') |
118 | 170 | curr_obj = self.pool.get('res.currency') | 170 | curr_obj = self.pool.get('res.currency') |
119 | 171 | user_obj = self.pool.get('res.users') | 171 | user_obj = self.pool.get('res.users') |
120 | 172 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
121 | 172 | # Browse elements if 'date' in vals | 173 | # Browse elements if 'date' in vals |
122 | 173 | if vals.get('date', False): | 174 | if vals.get('date', False): |
123 | 174 | date = vals.get('date') | 175 | date = vals.get('date') |
124 | @@ -188,8 +189,21 @@ | |||
125 | 188 | raise osv.except_osv(_('Warning'), _('No analytic distribution found for %s %s') % (cl.account_id.code, cl.initial_amount)) | 189 | raise osv.except_osv(_('Warning'), _('No analytic distribution found for %s %s') % (cl.account_id.code, cl.initial_amount)) |
126 | 189 | for distrib_lines in [distrib.cost_center_lines, distrib.funding_pool_lines, distrib.free_1_lines, distrib.free_2_lines]: | 190 | for distrib_lines in [distrib.cost_center_lines, distrib.funding_pool_lines, distrib.free_1_lines, distrib.free_2_lines]: |
127 | 190 | for distrib_line in distrib_lines: | 191 | for distrib_line in distrib_lines: |
130 | 191 | if (distrib_line.analytic_id.date_start and date < distrib_line.analytic_id.date_start) or (distrib_line.analytic_id.date and date > distrib_line.analytic_id.date): | 192 | if distrib_line.analytic_id and \ |
131 | 192 | raise osv.except_osv(_('Error'), _('The analytic account %s is not active for given date.') % (distrib_line.analytic_id.name,)) | 193 | (distrib_line.analytic_id.date_start and date < distrib_line.analytic_id.date_start or |
132 | 194 | distrib_line.analytic_id.date and date >= distrib_line.analytic_id.date): | ||
133 | 195 | raise osv.except_osv(_('Error'), _('The analytic account %s is not active for given date.') % | ||
134 | 196 | (distrib_line.analytic_id.name,)) | ||
135 | 197 | dest_cc_tuples = set() # check each Dest/CC combination only once | ||
136 | 198 | for distrib_cc_l in distrib.cost_center_lines: | ||
137 | 199 | if distrib_cc_l.analytic_id: # non mandatory field | ||
138 | 200 | dest_cc_tuples.add((distrib_cc_l.destination_id, distrib_cc_l.analytic_id)) | ||
139 | 201 | for distrib_fp_l in distrib.funding_pool_lines: | ||
140 | 202 | dest_cc_tuples.add((distrib_fp_l.destination_id, distrib_fp_l.cost_center_id)) | ||
141 | 203 | for dest, cc in dest_cc_tuples: | ||
142 | 204 | if dest_cc_link_obj.is_inactive_dcl(cr, uid, dest.id, cc.id, date, context=context): | ||
143 | 205 | raise osv.except_osv(_('Error'), _("The combination \"%s - %s\" is not active at this date: %s") % | ||
144 | 206 | (dest.code or '', cc.code or '', date)) | ||
145 | 193 | # update the dates and fctal amounts of the related analytic lines | 207 | # update the dates and fctal amounts of the related analytic lines |
146 | 194 | context.update({'currency_date': date}) # same date used for doc, posting and source date of all lines | 208 | context.update({'currency_date': date}) # same date used for doc, posting and source date of all lines |
147 | 195 | for aal in cl.analytic_lines: | 209 | for aal in cl.analytic_lines: |
148 | 196 | 210 | ||
149 | === modified file 'bin/addons/analytic_distribution/analytic_account_view.xml' | |||
150 | --- bin/addons/analytic_distribution/analytic_account_view.xml 2020-10-08 13:11:14 +0000 | |||
151 | +++ bin/addons/analytic_distribution/analytic_account_view.xml 2021-05-07 16:01:07 +0000 | |||
152 | @@ -132,13 +132,28 @@ | |||
153 | 132 | </field> | 132 | </field> |
154 | 133 | </page> | 133 | </page> |
155 | 134 | <page string="Cost Centers" attrs="{'invisible': [('category', '!=', 'DEST')]}"> | 134 | <page string="Cost Centers" attrs="{'invisible': [('category', '!=', 'DEST')]}"> |
158 | 135 | <field name="allow_all_cc" colspan="4" on_change="on_change_allow_all_cc(allow_all_cc, dest_cc_ids)"/> | 135 | <field name="allow_all_cc" colspan="4" on_change="on_change_allow_all_cc(allow_all_cc, dest_cc_link_ids)"/> |
159 | 136 | <button name="button_dest_cc_clear" type="object" string="Remove all" icon="gtk-clear" colspan="4"/> | 136 | <button name="button_dest_cc_clear" type="object" string="Remove all" icon="gtk-clear" colspan="4" |
160 | 137 | confirm="Do you really want to remove all the Cost Centers selected?" | ||
161 | 138 | /> | ||
162 | 137 | <separator/> | 139 | <separator/> |
167 | 138 | <field name="dest_cc_ids" nolabel="1" colspan="4" on_change="on_change_cc_ids(dest_cc_ids)"> | 140 | <group colspan="6" col="4"> |
168 | 139 | <tree string="Cost Centers"> | 141 | <button icon="gtk-add" string="Add several Cost Centers" colspan="1" |
169 | 140 | <field name="code"/> | 142 | name="open_multiple_cc_selection_wizard" type="object" |
170 | 141 | <field name="name"/> | 143 | context="{'current_destination_id': record_id}"/> |
171 | 144 | <label string="" colspan="3"/> | ||
172 | 145 | </group> | ||
173 | 146 | <field name="dest_cc_link_ids" nolabel="1" colspan="4" | ||
174 | 147 | on_change="on_change_cc_ids(dest_cc_link_ids)" | ||
175 | 148 | context="{'current_destination_id': record_id}"> | ||
176 | 149 | <tree string="Cost Centers" editable="bottom"> | ||
177 | 150 | <field name="current_id" invisible="1"/> | ||
178 | 151 | <field name="cc_id" string="Code" | ||
179 | 152 | on_change="on_change_cc_id(cc_id)" | ||
180 | 153 | attrs="{'readonly': [('current_id', '!=', False)]}"/> | ||
181 | 154 | <field name="cc_name" string="Name"/> | ||
182 | 155 | <field name="active_from"/> | ||
183 | 156 | <field name="inactive_from"/> | ||
184 | 142 | </tree> | 157 | </tree> |
185 | 143 | </field> | 158 | </field> |
186 | 144 | </page> | 159 | </page> |
187 | @@ -262,9 +277,10 @@ | |||
188 | 262 | <field name="inherit_id" ref="account.view_account_analytic_account_list"/> | 277 | <field name="inherit_id" ref="account.view_account_analytic_account_list"/> |
189 | 263 | <field name="arch" type="xml"> | 278 | <field name="arch" type="xml"> |
190 | 264 | <tree string="Analytic Accounts" position="replace"> | 279 | <tree string="Analytic Accounts" position="replace"> |
193 | 265 | <tree toolbar="1" colors="red:(date and date<=current_date or dest_without_cc==True)" | 280 | <tree toolbar="1" colors="red:(date and date<=current_date or dest_without_cc==True);grey:selected_in_dest" |
194 | 266 | string="Analytic Accounts"> | 281 | notselectable="selected_in_dest" string="Analytic Accounts"> |
195 | 267 | <field name="dest_without_cc" invisible="1"/> | 282 | <field name="dest_without_cc" invisible="1"/> |
196 | 283 | <field name="selected_in_dest" invisible="1"/> | ||
197 | 268 | <field name="name"/> | 284 | <field name="name"/> |
198 | 269 | <field name="code"/> | 285 | <field name="code"/> |
199 | 270 | <field name="description"/> | 286 | <field name="description"/> |
200 | 271 | 287 | ||
201 | === modified file 'bin/addons/analytic_distribution/analytic_distribution.py' | |||
202 | --- bin/addons/analytic_distribution/analytic_distribution.py 2020-11-02 17:29:34 +0000 | |||
203 | +++ bin/addons/analytic_distribution/analytic_distribution.py 2021-05-07 16:01:07 +0000 | |||
204 | @@ -36,13 +36,16 @@ | |||
205 | 36 | if context is None: | 36 | if context is None: |
206 | 37 | context = {} | 37 | context = {} |
207 | 38 | analytic_acc_obj = self.pool.get('account.analytic.account') | 38 | analytic_acc_obj = self.pool.get('account.analytic.account') |
208 | 39 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
209 | 40 | ret = True # by default if either dest or cc is missing | ||
210 | 39 | if destination_id and cost_center_id: | 41 | if destination_id and cost_center_id: |
217 | 40 | dest = analytic_acc_obj.browse(cr, uid, destination_id, fields_to_fetch=['category', 'allow_all_cc', 'dest_cc_ids'], context=context) | 42 | if analytic_acc_obj.search_exist(cr, uid, [('id', '=', destination_id), ('allow_all_cc', '=', True)], context=context): |
218 | 41 | cc = analytic_acc_obj.browse(cr, uid, cost_center_id, fields_to_fetch=['category'], context=context) | 43 | ret = True |
219 | 42 | if dest and cc and dest.category == 'DEST' and cc.category == 'OC' and not dest.allow_all_cc and \ | 44 | elif dest_cc_link_obj.search_exist(cr, uid, [('dest_id', '=', destination_id), ('cc_id', '=', cost_center_id)], context=context): |
220 | 43 | cc.id not in [c.id for c in dest.dest_cc_ids]: | 45 | ret = True |
221 | 44 | return False | 46 | else: |
222 | 45 | return True | 47 | ret = False |
223 | 48 | return ret | ||
224 | 46 | 49 | ||
225 | 47 | def check_fp_cc_compatibility(self, cr, uid, fp_id, cost_center_id, context=None): | 50 | def check_fp_cc_compatibility(self, cr, uid, fp_id, cost_center_id, context=None): |
226 | 48 | """ | 51 | """ |
227 | @@ -146,6 +149,7 @@ | |||
228 | 146 | if context is None: | 149 | if context is None: |
229 | 147 | context = {} | 150 | context = {} |
230 | 148 | analytic_acc_obj = self.pool.get('account.analytic.account') | 151 | analytic_acc_obj = self.pool.get('account.analytic.account') |
231 | 152 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
232 | 149 | # Have an analytic distribution on another account than analytic-a-holic account make no sense. So their analytic distribution is valid | 153 | # Have an analytic distribution on another account than analytic-a-holic account make no sense. So their analytic distribution is valid |
233 | 150 | if account_id: | 154 | if account_id: |
234 | 151 | account = self.pool.get('account.account').read(cr, uid, account_id, ['is_analytic_addicted']) | 155 | account = self.pool.get('account.account').read(cr, uid, account_id, ['is_analytic_addicted']) |
235 | @@ -153,7 +157,8 @@ | |||
236 | 153 | return 'valid' | 157 | return 'valid' |
237 | 154 | if not distrib_id: | 158 | if not distrib_id: |
238 | 155 | if parent_id: | 159 | if parent_id: |
240 | 156 | return self._get_distribution_state(cr, uid, parent_id, False, account_id, context, amount=amount) | 160 | return self._get_distribution_state(cr, uid, parent_id, False, account_id, context=context, |
241 | 161 | doc_date=doc_date, posting_date=posting_date, manual=manual, amount=amount) | ||
242 | 157 | return 'none' | 162 | return 'none' |
243 | 158 | distrib = self.browse(cr, uid, distrib_id) | 163 | distrib = self.browse(cr, uid, distrib_id) |
244 | 159 | if not distrib.funding_pool_lines: | 164 | if not distrib.funding_pool_lines: |
245 | @@ -183,6 +188,9 @@ | |||
246 | 183 | return 'invalid' | 188 | return 'invalid' |
247 | 184 | if not analytic_acc_obj.is_account_active(fp_line.cost_center_id, posting_date): | 189 | if not analytic_acc_obj.is_account_active(fp_line.cost_center_id, posting_date): |
248 | 185 | return 'invalid' | 190 | return 'invalid' |
249 | 191 | if dest_cc_link_obj.is_inactive_dcl(cr, uid, fp_line.destination_id.id, fp_line.cost_center_id.id, | ||
250 | 192 | posting_date, context=context): | ||
251 | 193 | return 'invalid' | ||
252 | 186 | if doc_date and fp_line.analytic_id and not analytic_acc_obj.is_account_active(fp_line.analytic_id, doc_date): | 194 | if doc_date and fp_line.analytic_id and not analytic_acc_obj.is_account_active(fp_line.analytic_id, doc_date): |
253 | 187 | return 'invalid' | 195 | return 'invalid' |
254 | 188 | if fp_line.destination_id.id not in account.get('destination_ids', []): | 196 | if fp_line.destination_id.id not in account.get('destination_ids', []): |
255 | @@ -206,7 +214,7 @@ | |||
256 | 206 | return 'invalid' | 214 | return 'invalid' |
257 | 207 | return 'valid' | 215 | return 'valid' |
258 | 208 | 216 | ||
260 | 209 | def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, context=None): | 217 | def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, posting_date=False, context=None): |
261 | 210 | """ | 218 | """ |
262 | 211 | Give analytic state from the given information. | 219 | Give analytic state from the given information. |
263 | 212 | Return result and some info if needed. | 220 | Return result and some info if needed. |
264 | @@ -217,6 +225,7 @@ | |||
265 | 217 | # Prepare some values | 225 | # Prepare some values |
266 | 218 | res = 'valid' | 226 | res = 'valid' |
267 | 219 | info = '' | 227 | info = '' |
268 | 228 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
269 | 220 | account = self.pool.get('account.account').browse(cr, uid, account_id, context=context) | 229 | account = self.pool.get('account.account').browse(cr, uid, account_id, context=context) |
270 | 221 | # DISTRIBUTION VERIFICATION | 230 | # DISTRIBUTION VERIFICATION |
271 | 222 | # Check that destination is compatible with account | 231 | # Check that destination is compatible with account |
272 | @@ -225,6 +234,9 @@ | |||
273 | 225 | # Check that Destination and Cost Center are compatible | 234 | # Check that Destination and Cost Center are compatible |
274 | 226 | if not self.check_dest_cc_compatibility(cr, uid, destination_id, cost_center_id, context=context): | 235 | if not self.check_dest_cc_compatibility(cr, uid, destination_id, cost_center_id, context=context): |
275 | 227 | return 'invalid', _('Cost Center not compatible with destination') | 236 | return 'invalid', _('Cost Center not compatible with destination') |
276 | 237 | # Check that their combination is active | ||
277 | 238 | if posting_date and dest_cc_link_obj.is_inactive_dcl(cr, uid, destination_id, cost_center_id, posting_date, context=context): | ||
278 | 239 | return 'invalid', _('Inactive DEST/CC combination') | ||
279 | 228 | # Check that cost center is compatible with FP | 240 | # Check that cost center is compatible with FP |
280 | 229 | if not self.check_fp_cc_compatibility(cr, uid, analytic_id, cost_center_id, context=context): | 241 | if not self.check_fp_cc_compatibility(cr, uid, analytic_id, cost_center_id, context=context): |
281 | 230 | return 'invalid', _('Cost Center not compatible with FP') | 242 | return 'invalid', _('Cost Center not compatible with FP') |
282 | @@ -236,10 +248,11 @@ | |||
283 | 236 | def check_cc_distrib_active(self, cr, uid, distrib_br, posting_date=False, prefix='', from_supply=False): | 248 | def check_cc_distrib_active(self, cr, uid, distrib_br, posting_date=False, prefix='', from_supply=False): |
284 | 237 | """ | 249 | """ |
285 | 238 | Checks the Cost Center Distribution Lines of the distribution in param.: | 250 | Checks the Cost Center Distribution Lines of the distribution in param.: |
287 | 239 | raises an error if the CC or the Dest. used is not active at the posting date selected (or today's date) | 251 | raises an error if the CC, the Dest., or their combination is not active at the posting date selected (or today's date) |
288 | 240 | If needed a "prefix" can be added to the error message. | 252 | If needed a "prefix" can be added to the error message. |
289 | 241 | """ | 253 | """ |
290 | 242 | cc_distrib_line_obj = self.pool.get('cost.center.distribution.line') | 254 | cc_distrib_line_obj = self.pool.get('cost.center.distribution.line') |
291 | 255 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
292 | 243 | if distrib_br: | 256 | if distrib_br: |
293 | 244 | if not posting_date: | 257 | if not posting_date: |
294 | 245 | posting_date = time.strftime('%Y-%m-%d') | 258 | posting_date = time.strftime('%Y-%m-%d') |
295 | @@ -257,6 +270,11 @@ | |||
296 | 257 | else: | 270 | else: |
297 | 258 | raise osv.except_osv(_('Error'), _('%sDestination %s is either inactive at the date %s, or it allows no Cost Center.') % | 271 | raise osv.except_osv(_('Error'), _('%sDestination %s is either inactive at the date %s, or it allows no Cost Center.') % |
298 | 259 | (prefix, cline.destination_id.code or '', posting_date)) | 272 | (prefix, cline.destination_id.code or '', posting_date)) |
299 | 273 | if cline.destination_id and cline.analytic_id and \ | ||
300 | 274 | dest_cc_link_obj.is_inactive_dcl(cr, uid, cline.destination_id.id, cline.analytic_id.id, posting_date): | ||
301 | 275 | raise osv.except_osv(_('Error'), _("%sThe combination \"%s - %s\" is not active at this date: %s") % | ||
302 | 276 | (prefix, cline.destination_id.code or '', cline.analytic_id.code or '', posting_date)) | ||
303 | 277 | |||
304 | 260 | 278 | ||
305 | 261 | 279 | ||
306 | 262 | analytic_distribution() | 280 | analytic_distribution() |
307 | 263 | 281 | ||
308 | === modified file 'bin/addons/analytic_distribution/analytic_line.py' | |||
309 | --- bin/addons/analytic_distribution/analytic_line.py 2020-12-01 17:29:45 +0000 | |||
310 | +++ bin/addons/analytic_distribution/analytic_line.py 2021-05-07 16:01:07 +0000 | |||
311 | @@ -413,6 +413,8 @@ | |||
312 | 413 | ids = [ids] | 413 | ids = [ids] |
313 | 414 | # Prepare some value | 414 | # Prepare some value |
314 | 415 | ad_obj = self.pool.get('analytic.distribution') | 415 | ad_obj = self.pool.get('analytic.distribution') |
315 | 416 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
316 | 417 | period_obj = self.pool.get('account.period') | ||
317 | 416 | account = self.pool.get('account.analytic.account').read(cr, uid, account_id, ['category', 'date_start', 'date'], context=context) | 418 | account = self.pool.get('account.analytic.account').read(cr, uid, account_id, ['category', 'date_start', 'date'], context=context) |
318 | 417 | account_type = account and account.get('category', False) or False | 419 | account_type = account and account.get('category', False) or False |
319 | 418 | res = [] | 420 | res = [] |
320 | @@ -422,6 +424,9 @@ | |||
321 | 422 | date_start = account and account.get('date_start', False) or False | 424 | date_start = account and account.get('date_start', False) or False |
322 | 423 | date_stop = account and account.get('date', False) or False | 425 | date_stop = account and account.get('date', False) or False |
323 | 424 | # Date verification for all lines and fetch all necessary elements sorted by analytic distribution | 426 | # Date verification for all lines and fetch all necessary elements sorted by analytic distribution |
324 | 427 | cmp_dates = {} | ||
325 | 428 | wiz_period_open = period_obj.search_exist(cr, uid, [('date_start', '<=', wiz_date), ('date_stop', '>=', wiz_date), | ||
326 | 429 | ('special', '=', False), ('state', '=', 'draft')], context=context) | ||
327 | 425 | for aline in self.browse(cr, uid, ids): | 430 | for aline in self.browse(cr, uid, ids): |
328 | 426 | # UTP-800: Change date comparison regarding FP. If FP, use document date. Otherwise use date. | 431 | # UTP-800: Change date comparison regarding FP. If FP, use document date. Otherwise use date. |
329 | 427 | aline_cmp_date = aline.date | 432 | aline_cmp_date = aline.date |
330 | @@ -435,13 +440,25 @@ | |||
331 | 435 | if aline.journal_id.type == 'hq' or aline.period_id and aline.period_id.state in ['done', 'mission-closed']: | 440 | if aline.journal_id.type == 'hq' or aline.period_id and aline.period_id.state in ['done', 'mission-closed']: |
332 | 436 | aline_cmp_date = wiz_date | 441 | aline_cmp_date = wiz_date |
333 | 437 | # these lines will be reverted, check if the reverted line is active | 442 | # these lines will be reverted, check if the reverted line is active |
337 | 438 | oc_dest_date_start = max(aline.cost_center_id.date_start, aline.destination_id.date_start) | 443 | if not wiz_period_open: |
335 | 439 | oc_dest_date_stop = min(aline.cost_center_id.date or '9999-01-01', aline.destination_id.date or '9999-01-01') | ||
336 | 440 | if (oc_dest_date_start and wiz_date < oc_dest_date_start) or (oc_dest_date_stop and wiz_date >= oc_dest_date_stop): | ||
338 | 441 | expired_date_ids.append(aline.id) | 444 | expired_date_ids.append(aline.id) |
339 | 445 | else: | ||
340 | 446 | oc_dest_date_start = max(aline.cost_center_id.date_start, aline.destination_id.date_start) | ||
341 | 447 | oc_dest_date_stop = min(aline.cost_center_id.date or '9999-01-01', aline.destination_id.date or '9999-01-01') | ||
342 | 448 | if (oc_dest_date_start and wiz_date < oc_dest_date_start) or (oc_dest_date_stop and wiz_date >= oc_dest_date_stop): | ||
343 | 449 | expired_date_ids.append(aline.id) | ||
344 | 450 | else: | ||
345 | 451 | # check the Dest/CC link validity with the original Dest and CC which will be used in the REV | ||
346 | 452 | destination_id = aline.destination_id and aline.destination_id.id or False | ||
347 | 453 | cost_center_id = aline.cost_center_id and aline.cost_center_id.id or False | ||
348 | 454 | if destination_id and cost_center_id and \ | ||
349 | 455 | dest_cc_link_obj.is_inactive_dcl(cr, uid, destination_id, cost_center_id, wiz_date, context=context): | ||
350 | 456 | expired_date_ids.append(aline.id) | ||
351 | 442 | if (date_start and aline_cmp_date < date_start) or (date_stop and aline_cmp_date >= date_stop): | 457 | if (date_start and aline_cmp_date < date_start) or (date_stop and aline_cmp_date >= date_stop): |
352 | 443 | expired_date_ids.append(aline.id) | 458 | expired_date_ids.append(aline.id) |
353 | 459 | cmp_dates[aline.id] = aline_cmp_date | ||
354 | 444 | # Process regarding account_type | 460 | # Process regarding account_type |
355 | 461 | ids = [i for i in ids if i not in expired_date_ids] # exclude the AJI in expired_date_ids | ||
356 | 445 | if account_type == 'OC': | 462 | if account_type == 'OC': |
357 | 446 | for aline in self.browse(cr, uid, ids): | 463 | for aline in self.browse(cr, uid, ids): |
358 | 447 | # Verify that: | 464 | # Verify that: |
359 | @@ -449,10 +466,11 @@ | |||
360 | 449 | check_accounts = self.pool.get('account.analytic.account').is_blocked_by_a_contract(cr, uid, [aline.account_id.id]) | 466 | check_accounts = self.pool.get('account.analytic.account').is_blocked_by_a_contract(cr, uid, [aline.account_id.id]) |
361 | 450 | if check_accounts and aline.account_id.id in check_accounts: | 467 | if check_accounts and aline.account_id.id in check_accounts: |
362 | 451 | continue | 468 | continue |
367 | 452 | if ad_obj.check_dest_cc_compatibility(cr, uid, aline.destination_id and aline.destination_id.id or False, | 469 | dest_id = aline.destination_id and aline.destination_id.id or False |
368 | 453 | account_id, context=context): | 470 | if ad_obj.check_dest_cc_compatibility(cr, uid, dest_id, account_id, context=context) and \ |
369 | 454 | if ad_obj.check_fp_cc_compatibility(cr, uid, aline.account_id.id, account_id, context=context): | 471 | ad_obj.check_fp_cc_compatibility(cr, uid, aline.account_id.id, account_id, context=context) and \ |
370 | 455 | res.append(aline.id) | 472 | not dest_cc_link_obj.is_inactive_dcl(cr, uid, dest_id, account_id, cmp_dates[aline.id], context=context): |
371 | 473 | res.append(aline.id) | ||
372 | 456 | elif account_type == 'FUNDING': | 474 | elif account_type == 'FUNDING': |
373 | 457 | # Browse all analytic line to verify them | 475 | # Browse all analytic line to verify them |
374 | 458 | for aline in self.browse(cr, uid, ids): | 476 | for aline in self.browse(cr, uid, ids): |
375 | @@ -475,19 +493,16 @@ | |||
376 | 475 | for aline in self.browse(cr, uid, ids, context=context): | 493 | for aline in self.browse(cr, uid, ids, context=context): |
377 | 476 | # the following check is included into check_fp_acc_dest_compatibility: | 494 | # the following check is included into check_fp_acc_dest_compatibility: |
378 | 477 | # account_id in [x.id for x in aline.general_account_id.destination_ids] | 495 | # account_id in [x.id for x in aline.general_account_id.destination_ids] |
381 | 478 | if ad_obj.check_dest_cc_compatibility(cr, uid, account_id, aline.cost_center_id and aline.cost_center_id.id or False, | 496 | cc_id = aline.cost_center_id and aline.cost_center_id.id or False |
382 | 479 | context=context) and \ | 497 | if ad_obj.check_dest_cc_compatibility(cr, uid, account_id, cc_id, context=context) and \ |
383 | 480 | ad_obj.check_fp_acc_dest_compatibility(cr, uid, aline.account_id.id, aline.general_account_id.id, | 498 | ad_obj.check_fp_acc_dest_compatibility(cr, uid, aline.account_id.id, aline.general_account_id.id, |
385 | 481 | account_id, context=context): | 499 | account_id, context=context) and \ |
386 | 500 | not dest_cc_link_obj.is_inactive_dcl(cr, uid, account_id, cc_id, cmp_dates[aline.id], context=context): | ||
387 | 482 | res.append(aline.id) | 501 | res.append(aline.id) |
388 | 483 | else: | 502 | else: |
389 | 484 | # Case of FREE1 and FREE2 lines | 503 | # Case of FREE1 and FREE2 lines |
390 | 485 | for i in ids: | 504 | for i in ids: |
391 | 486 | res.append(i) | 505 | res.append(i) |
392 | 487 | # Delete elements that are in expired_date_ids | ||
393 | 488 | for e in expired_date_ids: | ||
394 | 489 | if e in res: | ||
395 | 490 | res.remove(e) | ||
396 | 491 | return res | 506 | return res |
397 | 492 | 507 | ||
398 | 493 | def check_dest_cc_fp_compatibility(self, cr, uid, ids, | 508 | def check_dest_cc_fp_compatibility(self, cr, uid, ids, |
399 | @@ -513,6 +528,7 @@ | |||
400 | 513 | new_cc_id, new_cc_br, | 528 | new_cc_id, new_cc_br, |
401 | 514 | new_fp_id, new_fp_br): | 529 | new_fp_id, new_fp_br): |
402 | 515 | ad_obj = self.pool.get('analytic.distribution') | 530 | ad_obj = self.pool.get('analytic.distribution') |
403 | 531 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
404 | 516 | if not general_account_br.is_analytic_addicted: | 532 | if not general_account_br.is_analytic_addicted: |
405 | 517 | res.append((id, entry_sequence, '')) | 533 | res.append((id, entry_sequence, '')) |
406 | 518 | return False | 534 | return False |
407 | @@ -549,6 +565,9 @@ | |||
408 | 549 | if not check_date(new_cc_br, posting_date): | 565 | if not check_date(new_cc_br, posting_date): |
409 | 550 | res.append((id, entry_sequence, _('CC date'))) | 566 | res.append((id, entry_sequence, _('CC date'))) |
410 | 551 | return False | 567 | return False |
411 | 568 | if new_dest_id and new_cc_id and dest_cc_link_obj.is_inactive_dcl(cr, uid, new_dest_id, new_cc_id, posting_date, context=context): | ||
412 | 569 | res.append((id, entry_sequence, _('DEST/CC combination date'))) | ||
413 | 570 | return False | ||
414 | 552 | if new_fp_id != msf_pf_id and not \ | 571 | if new_fp_id != msf_pf_id and not \ |
415 | 553 | check_date(new_fp_br, posting_date): | 572 | check_date(new_fp_br, posting_date): |
416 | 554 | res.append((id, entry_sequence, _('FP date'))) | 573 | res.append((id, entry_sequence, _('FP date'))) |
417 | 555 | 574 | ||
418 | === modified file 'bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py' | |||
419 | --- bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2021-04-26 09:35:14 +0000 | |||
420 | +++ bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2021-05-07 16:01:07 +0000 | |||
421 | @@ -1008,6 +1008,7 @@ | |||
422 | 1008 | if isinstance(ids, (int, long)): | 1008 | if isinstance(ids, (int, long)): |
423 | 1009 | ids = [ids] | 1009 | ids = [ids] |
424 | 1010 | distrib_obj = self.pool.get('analytic.distribution') | 1010 | distrib_obj = self.pool.get('analytic.distribution') |
425 | 1011 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
426 | 1011 | for w in self.browse(cr, uid, ids): | 1012 | for w in self.browse(cr, uid, ids): |
427 | 1012 | # UF-1678 | 1013 | # UF-1678 |
428 | 1013 | # For Cost center and destination analytic accounts, check is done on POSTING date. It HAVE TO BE in context to be well processed (filter_active is a function that need a context) | 1014 | # For Cost center and destination analytic accounts, check is done on POSTING date. It HAVE TO BE in context to be well processed (filter_active is a function that need a context) |
429 | @@ -1021,6 +1022,9 @@ | |||
430 | 1021 | if not fpline.destination_id.filter_active: | 1022 | if not fpline.destination_id.filter_active: |
431 | 1022 | raise osv.except_osv(_('Error'), _('Destination %s is either inactive at the date %s, or it allows no Cost Center.') | 1023 | raise osv.except_osv(_('Error'), _('Destination %s is either inactive at the date %s, or it allows no Cost Center.') |
432 | 1023 | % (fpline.destination_id.code or '', w.posting_date)) | 1024 | % (fpline.destination_id.code or '', w.posting_date)) |
433 | 1025 | if dest_cc_link_obj.is_inactive_dcl(cr, uid, fpline.destination_id.id, fpline.cost_center_id.id, w.posting_date): | ||
434 | 1026 | raise osv.except_osv(_('Error'), _("The combination \"%s - %s\" is not active at this date: %s") % | ||
435 | 1027 | (fpline.destination_id.code or '', fpline.cost_center_id.code or '', w.posting_date)) | ||
436 | 1024 | # UF-1678 | 1028 | # UF-1678 |
437 | 1025 | # For funding pool analytic account, check is done on DOCUMENT date. It HAVE TO BE in context to be well processed (filter_active is a function that need a context) | 1029 | # For funding pool analytic account, check is done on DOCUMENT date. It HAVE TO BE in context to be well processed (filter_active is a function that need a context) |
438 | 1026 | if w.distribution_id and w.document_date: | 1030 | if w.distribution_id and w.document_date: |
439 | @@ -1081,7 +1085,7 @@ | |||
440 | 1081 | self.wizard_verifications(cr, uid, wiz.id, context=context) | 1085 | self.wizard_verifications(cr, uid, wiz.id, context=context) |
441 | 1082 | # And do distribution creation if necessary | 1086 | # And do distribution creation if necessary |
442 | 1083 | distrib_id = wiz.distribution_id and wiz.distribution_id.id or False | 1087 | distrib_id = wiz.distribution_id and wiz.distribution_id.id or False |
444 | 1084 | if not distrib_id: | 1088 | if not distrib_id or not self.pool.get('analytic.distribution').exists(cr, uid, distrib_id, context=context): |
445 | 1085 | # create a new analytic distribution | 1089 | # create a new analytic distribution |
446 | 1086 | analytic_vals = {} | 1090 | analytic_vals = {} |
447 | 1087 | if wiz.partner_type:#UF-2138: added the ref to partner type of FO/PO | 1091 | if wiz.partner_type:#UF-2138: added the ref to partner type of FO/PO |
448 | 1088 | 1092 | ||
449 | === modified file 'bin/addons/analytic_override/__init__.py' | |||
450 | --- bin/addons/analytic_override/__init__.py 2014-03-14 09:40:12 +0000 | |||
451 | +++ bin/addons/analytic_override/__init__.py 2021-05-07 16:01:07 +0000 | |||
452 | @@ -22,5 +22,7 @@ | |||
453 | 22 | import analytic_distribution | 22 | import analytic_distribution |
454 | 23 | import analytic_account | 23 | import analytic_account |
455 | 24 | import analytic_line | 24 | import analytic_line |
456 | 25 | import dest_cc_link | ||
457 | 26 | import multiple_cc_selection_wizard | ||
458 | 25 | 27 | ||
459 | 26 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 28 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
460 | 27 | \ No newline at end of file | 29 | \ No newline at end of file |
461 | 28 | 30 | ||
462 | === modified file 'bin/addons/analytic_override/__openerp__.py' | |||
463 | --- bin/addons/analytic_override/__openerp__.py 2014-10-29 13:47:46 +0000 | |||
464 | +++ bin/addons/analytic_override/__openerp__.py 2021-05-07 16:01:07 +0000 | |||
465 | @@ -32,6 +32,8 @@ | |||
466 | 32 | "init_xml" : [], | 32 | "init_xml" : [], |
467 | 33 | "update_xml": [ | 33 | "update_xml": [ |
468 | 34 | 'security/ir.model.access.csv', | 34 | 'security/ir.model.access.csv', |
469 | 35 | 'dest_cc_link.xml', | ||
470 | 36 | 'multiple_cc_selection_wizard.xml', | ||
471 | 35 | ], | 37 | ], |
472 | 36 | 'test': [], | 38 | 'test': [], |
473 | 37 | 'demo_xml': [ | 39 | 'demo_xml': [ |
474 | 38 | 40 | ||
475 | === modified file 'bin/addons/analytic_override/analytic_account.py' | |||
476 | --- bin/addons/analytic_override/analytic_account.py 2020-10-30 17:31:31 +0000 | |||
477 | +++ bin/addons/analytic_override/analytic_account.py 2021-05-07 16:01:07 +0000 | |||
478 | @@ -40,8 +40,8 @@ | |||
479 | 40 | if context is None: | 40 | if context is None: |
480 | 41 | context = {} | 41 | context = {} |
481 | 42 | res = {} | 42 | res = {} |
484 | 43 | for a in self.browse(cr, uid, ids, fields_to_fetch=['category', 'type', 'allow_all_cc', 'dest_cc_ids'], context=context): | 43 | for a in self.browse(cr, uid, ids, fields_to_fetch=['category', 'type', 'allow_all_cc', 'dest_cc_link_ids'], context=context): |
485 | 44 | if a.category == 'DEST' and a.type == 'normal' and not a.allow_all_cc and not a.dest_cc_ids: | 44 | if a.category == 'DEST' and a.type != 'view' and not a.allow_all_cc and not a.dest_cc_link_ids: |
486 | 45 | res[a.id] = True | 45 | res[a.id] = True |
487 | 46 | else: | 46 | else: |
488 | 47 | res[a.id] = False | 47 | res[a.id] = False |
489 | @@ -95,7 +95,7 @@ | |||
490 | 95 | arg.append(('category', '!=', 'DEST')) | 95 | arg.append(('category', '!=', 'DEST')) |
491 | 96 | arg.append(('type', '=', 'view')) | 96 | arg.append(('type', '=', 'view')) |
492 | 97 | arg.append(('allow_all_cc', '=', True)) | 97 | arg.append(('allow_all_cc', '=', True)) |
494 | 98 | arg.append(('dest_cc_ids', '!=', False)) | 98 | arg.append(('dest_cc_link_ids', '!=', False)) |
495 | 99 | # filter: inactive | 99 | # filter: inactive |
496 | 100 | elif x[0] == 'filter_active' and x[2] is False: | 100 | elif x[0] == 'filter_active' and x[2] is False: |
497 | 101 | arg.append('|') | 101 | arg.append('|') |
498 | @@ -106,9 +106,9 @@ | |||
499 | 106 | arg.append('&') | 106 | arg.append('&') |
500 | 107 | arg.append('&') | 107 | arg.append('&') |
501 | 108 | arg.append(('category', '=', 'DEST')) | 108 | arg.append(('category', '=', 'DEST')) |
503 | 109 | arg.append(('type', '=', 'normal')) | 109 | arg.append(('type', '!=', 'view')) |
504 | 110 | arg.append(('allow_all_cc', '=', False)) | 110 | arg.append(('allow_all_cc', '=', False)) |
506 | 111 | arg.append(('dest_cc_ids', '=', False)) | 111 | arg.append(('dest_cc_link_ids', '=', False)) |
507 | 112 | return arg | 112 | return arg |
508 | 113 | 113 | ||
509 | 114 | def _get_fake(self, cr, uid, ids, *a, **b): | 114 | def _get_fake(self, cr, uid, ids, *a, **b): |
510 | @@ -282,11 +282,20 @@ | |||
511 | 282 | cc = arg[2] | 282 | cc = arg[2] |
512 | 283 | if operator != '=' or not isinstance(cc, (int, long)): | 283 | if operator != '=' or not isinstance(cc, (int, long)): |
513 | 284 | raise osv.except_osv(_('Error'), _('Filter not implemented on Destinations.')) | 284 | raise osv.except_osv(_('Error'), _('Filter not implemented on Destinations.')) |
519 | 285 | all_dest_ids = self.search(cr, uid, [('category', '=', 'DEST')], context=context) | 285 | if not cc: |
520 | 286 | compatible_dest_ids = [] | 286 | # by default if no CC is selected display only the Destinations compatible with all CC |
521 | 287 | for dest in self.browse(cr, uid, all_dest_ids, fields_to_fetch=['allow_all_cc', 'dest_cc_ids'], context=context): | 287 | compatible_dest_ids = self.search(cr, uid, [('category', '=', 'DEST'), |
522 | 288 | if dest.allow_all_cc or (cc and cc in [c.id for c in dest.dest_cc_ids]): | 288 | ('type', '!=', 'view'), |
523 | 289 | compatible_dest_ids.append(dest.id) | 289 | ('allow_all_cc', '=', True)], context=context) |
524 | 290 | else: | ||
525 | 291 | compatible_dest_sql = """ | ||
526 | 292 | SELECT id | ||
527 | 293 | FROM account_analytic_account | ||
528 | 294 | WHERE category = 'DEST' AND type != 'view' | ||
529 | 295 | AND (allow_all_cc = 't' OR id IN (SELECT dest_id FROM dest_cc_link WHERE cc_id = %s)); | ||
530 | 296 | """ | ||
531 | 297 | cr.execute(compatible_dest_sql, (cc,)) | ||
532 | 298 | compatible_dest_ids = [x[0] for x in cr.fetchall()] | ||
533 | 290 | dom.append(('id', 'in', compatible_dest_ids)) | 299 | dom.append(('id', 'in', compatible_dest_ids)) |
534 | 291 | return dom | 300 | return dom |
535 | 292 | 301 | ||
536 | @@ -442,6 +451,54 @@ | |||
537 | 442 | } | 451 | } |
538 | 443 | return res | 452 | return res |
539 | 444 | 453 | ||
540 | 454 | def _get_selected_in_dest(self, cr, uid, cc_ids, name=False, args=False, context=None): | ||
541 | 455 | """ | ||
542 | 456 | Returns True for the Cost Centers already selected in the Destination: | ||
543 | 457 | they will be displayed in grey in the list and won't be re-selectable. | ||
544 | 458 | """ | ||
545 | 459 | if context is None: | ||
546 | 460 | context = {} | ||
547 | 461 | if isinstance(cc_ids, (int, long)): | ||
548 | 462 | cc_ids = [cc_ids] | ||
549 | 463 | selected = [] | ||
550 | 464 | dest_id = context.get('current_destination_id') or False | ||
551 | 465 | if dest_id: | ||
552 | 466 | dest = self.browse(cr, uid, dest_id, fields_to_fetch=['dest_cc_link_ids'], context=context) | ||
553 | 467 | selected = [dest_cc_link.cc_id.id for dest_cc_link in dest.dest_cc_link_ids] | ||
554 | 468 | res = {} | ||
555 | 469 | for cc_id in cc_ids: | ||
556 | 470 | res[cc_id] = cc_id in selected | ||
557 | 471 | return res | ||
558 | 472 | |||
559 | 473 | def _get_dest_cc_link_dates(self, cr, uid, ids, field_name, args, context=None): | ||
560 | 474 | """ | ||
561 | 475 | Returns a dict with key = id of the analytic account, | ||
562 | 476 | and value = dict with dest_cc_link_active_from and dest_cc_link_inactive_from dates separated by commas (String). | ||
563 | 477 | Note that the date format is the same in EN and FR, and that empty dates are not ignored. | ||
564 | 478 | E.g.: '2021-03-02,2021-03-01,,2021-03-03,' | ||
565 | 479 | |||
566 | 480 | This is used in Destination Import Tools, in particular for the Export of existing entries used as examples. | ||
567 | 481 | """ | ||
568 | 482 | if context is None: | ||
569 | 483 | context = {} | ||
570 | 484 | if isinstance(ids, (int, long)): | ||
571 | 485 | ids = [ids] | ||
572 | 486 | res = {} | ||
573 | 487 | for a in self.browse(cr, uid, ids, fields_to_fetch=['category', 'dest_cc_link_ids'], context=context): | ||
574 | 488 | active_date_list = [] | ||
575 | 489 | inactive_date_list = [] | ||
576 | 490 | if a.category == 'DEST': | ||
577 | 491 | for cc_link in a.dest_cc_link_ids: | ||
578 | 492 | active_date_str = "%s" % (cc_link.active_from or "") | ||
579 | 493 | active_date_list.append(active_date_str) | ||
580 | 494 | inactive_date_str = "%s" % (cc_link.inactive_from or "") | ||
581 | 495 | inactive_date_list.append(inactive_date_str) | ||
582 | 496 | res[a.id] = { | ||
583 | 497 | 'dest_cc_link_active_from': ",".join(active_date_list), | ||
584 | 498 | 'dest_cc_link_inactive_from': ",".join(inactive_date_list), | ||
585 | 499 | } | ||
586 | 500 | return res | ||
587 | 501 | |||
588 | 445 | _columns = { | 502 | _columns = { |
589 | 446 | 'name': fields.char('Name', size=128, required=True, translate=1), | 503 | 'name': fields.char('Name', size=128, required=True, translate=1), |
590 | 447 | 'code': fields.char('Code', size=24), | 504 | 'code': fields.char('Code', size=24), |
591 | @@ -463,6 +520,17 @@ | |||
592 | 463 | 'dest_cc_ids': fields.many2many('account.analytic.account', 'destination_cost_center_rel', | 520 | 'dest_cc_ids': fields.many2many('account.analytic.account', 'destination_cost_center_rel', |
593 | 464 | 'destination_id', 'cost_center_id', string='Cost Centers', | 521 | 'destination_id', 'cost_center_id', string='Cost Centers', |
594 | 465 | domain="[('type', '!=', 'view'), ('category', '=', 'OC')]"), | 522 | domain="[('type', '!=', 'view'), ('category', '=', 'OC')]"), |
595 | 523 | 'dest_cc_link_ids': fields.one2many('dest.cc.link', 'dest_id', string="Cost Centers", required=False), | ||
596 | 524 | 'dest_cc_link_active_from': fields.function(_get_dest_cc_link_dates, method=True, type='char', | ||
597 | 525 | store=False, readonly=True, | ||
598 | 526 | string='Activation Combination Dest / CC from', | ||
599 | 527 | help="Technical field used for Import Tools only", | ||
600 | 528 | multi="dest_cc_link_dates"), | ||
601 | 529 | 'dest_cc_link_inactive_from': fields.function(_get_dest_cc_link_dates, method=True, type='char', | ||
602 | 530 | store=False, readonly=True, | ||
603 | 531 | string='Inactivation Combination Dest / CC from', | ||
604 | 532 | help="Technical field used for Import Tools only", | ||
605 | 533 | multi="dest_cc_link_dates"), | ||
606 | 466 | 'allow_all_cc': fields.boolean(string="Allow all Cost Centers"), # for the Destinations | 534 | 'allow_all_cc': fields.boolean(string="Allow all Cost Centers"), # for the Destinations |
607 | 467 | 'allow_all_cc_with_fp': fields.boolean(string="Allow all Cost Centers"), # for the Funding Pools | 535 | 'allow_all_cc_with_fp': fields.boolean(string="Allow all Cost Centers"), # for the Funding Pools |
608 | 468 | 'dest_compatible_with_cc_ids': fields.function(_get_fake, method=True, store=False, | 536 | 'dest_compatible_with_cc_ids': fields.function(_get_fake, method=True, store=False, |
609 | @@ -498,6 +566,8 @@ | |||
610 | 498 | 'fp_account_ids': fields.many2many('account.account', 'fp_account_rel', 'fp_id', 'account_id', string='G/L Accounts', | 566 | 'fp_account_ids': fields.many2many('account.account', 'fp_account_rel', 'fp_id', 'account_id', string='G/L Accounts', |
611 | 499 | domain="[('type', '!=', 'view'), ('is_analytic_addicted', '=', True), ('active', '=', 't')]", | 567 | domain="[('type', '!=', 'view'), ('is_analytic_addicted', '=', True), ('active', '=', 't')]", |
612 | 500 | help="G/L accounts linked to the Funding Pool", order_by='code'), | 568 | help="G/L accounts linked to the Funding Pool", order_by='code'), |
613 | 569 | 'selected_in_dest': fields.function(_get_selected_in_dest, string='Selected in Destination', method=True, | ||
614 | 570 | type='boolean', store=False), | ||
615 | 501 | } | 571 | } |
616 | 502 | 572 | ||
617 | 503 | _defaults ={ | 573 | _defaults ={ |
618 | @@ -577,39 +647,49 @@ | |||
619 | 577 | res['domain']['parent_id'] = [('category', '=', category), ('type', '=', 'view')] | 647 | res['domain']['parent_id'] = [('category', '=', category), ('type', '=', 'view')] |
620 | 578 | return res | 648 | return res |
621 | 579 | 649 | ||
623 | 580 | def on_change_allow_all_cc(self, cr, uid, ids, allow_all_cc, cc_ids, acc_type='destination', field_name='allow_all_cc', context=None): | 650 | def on_change_allow_all_cc(self, cr, uid, ids, allow_all_cc, cc_ids, acc_type='destination', field_name='allow_all_cc', |
624 | 651 | m2m=False, context=None): | ||
625 | 581 | """ | 652 | """ |
626 | 582 | If the user tries to tick the box "Allow all Cost Centers" whereas CC are selected, | 653 | If the user tries to tick the box "Allow all Cost Centers" whereas CC are selected, |
627 | 583 | informs him that he has to remove the CC first | 654 | informs him that he has to remove the CC first |
628 | 584 | (acc_type = name of the Analytic Account Type to which the CC are linked, displayed in the warning msg) | 655 | (acc_type = name of the Analytic Account Type to which the CC are linked, displayed in the warning msg) |
629 | 585 | """ | 656 | """ |
630 | 586 | res = {} | 657 | res = {} |
640 | 587 | if allow_all_cc and cc_ids and cc_ids[0][2]: # e.g. [(6, 0, [1, 2])] | 658 | if allow_all_cc: |
641 | 588 | # NOTE: the msg is stored in a variable on purpose, otherwise the ".po" translation files would wrongly contain Python code | 659 | if m2m: |
642 | 589 | msg = 'Please remove the Cost Centers linked to the %s before ticking this box.' % acc_type.title() | 660 | cc_filled_in = cc_ids and cc_ids[0][2] or False # e.g. [(6, 0, [1, 2])] |
643 | 590 | warning = { | 661 | else: |
644 | 591 | 'title': _('Warning!'), | 662 | cc_filled_in = cc_ids or False |
645 | 592 | 'message': _(msg) | 663 | if cc_filled_in: |
646 | 593 | } | 664 | # NOTE: the msg is stored in a variable on purpose, otherwise the ".po" translation files would wrongly contain Python code |
647 | 594 | res['warning'] = warning | 665 | msg = 'Please remove the Cost Centers linked to the %s before ticking this box.' % acc_type.title() |
648 | 595 | res['value'] = {field_name: False, } | 666 | warning = { |
649 | 667 | 'title': _('Warning!'), | ||
650 | 668 | 'message': _(msg) | ||
651 | 669 | } | ||
652 | 670 | res['warning'] = warning | ||
653 | 671 | res['value'] = {field_name: False, } | ||
654 | 596 | return res | 672 | return res |
655 | 597 | 673 | ||
656 | 598 | def on_change_allow_all_cc_with_fp(self, cr, uid, ids, allow_all_cc_with_fp, cost_center_ids, context=None): | 674 | def on_change_allow_all_cc_with_fp(self, cr, uid, ids, allow_all_cc_with_fp, cost_center_ids, context=None): |
657 | 599 | return self.on_change_allow_all_cc(cr, uid, ids, allow_all_cc_with_fp, cost_center_ids, acc_type='funding pool', | 675 | return self.on_change_allow_all_cc(cr, uid, ids, allow_all_cc_with_fp, cost_center_ids, acc_type='funding pool', |
659 | 600 | field_name='allow_all_cc_with_fp', context=context) | 676 | field_name='allow_all_cc_with_fp', m2m=True, context=context) |
660 | 601 | 677 | ||
662 | 602 | def on_change_cc_ids(self, cr, uid, ids, cc_ids, field_name='allow_all_cc', context=None): | 678 | def on_change_cc_ids(self, cr, uid, ids, cc_ids, field_name='allow_all_cc', m2m=False, context=None): |
663 | 603 | """ | 679 | """ |
664 | 604 | If at least a CC is selected, unticks the box "Allow all Cost Centers" | 680 | If at least a CC is selected, unticks the box "Allow all Cost Centers" |
665 | 605 | """ | 681 | """ |
666 | 606 | res = {} | 682 | res = {} |
668 | 607 | if cc_ids and cc_ids[0][2]: # e.g. [(6, 0, [1, 2])] | 683 | if m2m: |
669 | 684 | cc_filled_in = cc_ids and cc_ids[0][2] or False # e.g. [(6, 0, [1, 2])] | ||
670 | 685 | else: | ||
671 | 686 | cc_filled_in = cc_ids or False | ||
672 | 687 | if cc_filled_in: | ||
673 | 608 | res['value'] = {field_name: False, } | 688 | res['value'] = {field_name: False, } |
674 | 609 | return res | 689 | return res |
675 | 610 | 690 | ||
676 | 611 | def on_change_cc_with_fp(self, cr, uid, ids, cost_center_ids, context=None): | 691 | def on_change_cc_with_fp(self, cr, uid, ids, cost_center_ids, context=None): |
678 | 612 | return self.on_change_cc_ids(cr, uid, ids, cost_center_ids, field_name='allow_all_cc_with_fp', context=context) | 692 | return self.on_change_cc_ids(cr, uid, ids, cost_center_ids, field_name='allow_all_cc_with_fp', m2m=True, context=context) |
679 | 613 | 693 | ||
680 | 614 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): | 694 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): |
681 | 615 | if not context: | 695 | if not context: |
682 | @@ -685,6 +765,7 @@ | |||
683 | 685 | if vals['category'] != 'DEST': | 765 | if vals['category'] != 'DEST': |
684 | 686 | vals['destination_ids'] = [(6, 0, [])] | 766 | vals['destination_ids'] = [(6, 0, [])] |
685 | 687 | vals['dest_cc_ids'] = [(6, 0, [])] | 767 | vals['dest_cc_ids'] = [(6, 0, [])] |
686 | 768 | vals['dest_cc_link_ids'] = [] # related dest.cc.links (if any) are deleted in _clean_dest_cc_link | ||
687 | 688 | vals['allow_all_cc'] = False # default value | 769 | vals['allow_all_cc'] = False # default value |
688 | 689 | if vals['category'] != 'FUNDING': | 770 | if vals['category'] != 'FUNDING': |
689 | 690 | vals['tuple_destination_account_ids'] = [(6, 0, [])] | 771 | vals['tuple_destination_account_ids'] = [(6, 0, [])] |
690 | @@ -727,6 +808,7 @@ | |||
691 | 727 | default['tuple_destination_summary'] = [] | 808 | default['tuple_destination_summary'] = [] |
692 | 728 | default['line_ids'] = [] | 809 | default['line_ids'] = [] |
693 | 729 | default['dest_cc_ids'] = [] | 810 | default['dest_cc_ids'] = [] |
694 | 811 | default['dest_cc_link_ids'] = [] | ||
695 | 730 | return super(analytic_account, self).copy(cr, uid, a_id, default, context=context) | 812 | return super(analytic_account, self).copy(cr, uid, a_id, default, context=context) |
696 | 731 | 813 | ||
697 | 732 | def _check_name_unicity(self, cr, uid, ids, context=None): | 814 | def _check_name_unicity(self, cr, uid, ids, context=None): |
698 | @@ -785,6 +867,57 @@ | |||
699 | 785 | self.log(cr, uid, analytic_account_id, _('At least one Analytic Journal Item using the Analytic Account %s ' | 867 | self.log(cr, uid, analytic_account_id, _('At least one Analytic Journal Item using the Analytic Account %s ' |
700 | 786 | 'has a Posting Date outside the activation dates selected.') % (analytic_acc.code)) | 868 | 'has a Posting Date outside the activation dates selected.') % (analytic_acc.code)) |
701 | 787 | 869 | ||
702 | 870 | def _clean_dest_cc_link(self, cr, uid, ids, vals, context=None): | ||
703 | 871 | """ | ||
704 | 872 | In case Dest CC Links are reset in an analytic account: deletes the related existing Dest CC Links if any. | ||
705 | 873 | Probable UC: Dest CC Links selected on a destination, then account changed to another category. | ||
706 | 874 | """ | ||
707 | 875 | if context is None: | ||
708 | 876 | context = {} | ||
709 | 877 | if isinstance(ids, (int, long)): | ||
710 | 878 | ids = [ids] | ||
711 | 879 | if 'dest_cc_link_ids' in vals and not vals['dest_cc_link_ids']: | ||
712 | 880 | dcl_ids = [] | ||
713 | 881 | for analytic_acc in self.browse(cr, uid, ids, fields_to_fetch=['dest_cc_link_ids'], context=context): | ||
714 | 882 | dcl_ids.extend([dcl.id for dcl in analytic_acc.dest_cc_link_ids]) | ||
715 | 883 | if dcl_ids: | ||
716 | 884 | self.pool.get('dest.cc.link').unlink(cr, uid, dcl_ids, context=context) | ||
717 | 885 | return True | ||
718 | 886 | |||
719 | 887 | def _dest_cc_ids_must_be_updated(self, vals, context): | ||
720 | 888 | """ | ||
721 | 889 | Returns True if dest_cc_ids in vals must be changed to dest_cc_link_ids (the goal of this method is to ensure | ||
722 | 890 | that the same condition is used everywhere and that the UC where all CC are removed is taken into account) | ||
723 | 891 | """ | ||
724 | 892 | if context and vals and context.get('sync_update_execution') and vals.get('dest_cc_ids') and vals['dest_cc_ids'][0][2] is not None: | ||
725 | 893 | return True | ||
726 | 894 | return False | ||
727 | 895 | |||
728 | 896 | def _update_synched_dest_cc_ids(self, cr, uid, dest_ids, vals, context): | ||
729 | 897 | """ | ||
730 | 898 | For synch made before or while US-7295 was released: changes the dest_cc_ids into dest_cc_link_ids | ||
731 | 899 | """ | ||
732 | 900 | if self._dest_cc_ids_must_be_updated(vals, context): | ||
733 | 901 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
734 | 902 | if isinstance(dest_ids, (int, long)): | ||
735 | 903 | dest_ids = [dest_ids] | ||
736 | 904 | for dest_id in dest_ids: | ||
737 | 905 | dest = self.browse(cr, uid, dest_id, fields_to_fetch=['dest_cc_link_ids'], context=context) | ||
738 | 906 | # note: after US-7295 patch script no instance has any dest_cc_ids, all CC links are necessarily dest.cc.link | ||
739 | 907 | current_cc_ids = [dest_cc_link.cc_id.id for dest_cc_link in dest.dest_cc_link_ids] | ||
740 | 908 | new_cc_ids = vals['dest_cc_ids'][0][2] or [] # take into account the UC where all CC are removed | ||
741 | 909 | # delete the CC to be deleted | ||
742 | 910 | cc_to_be_deleted = [c for c in current_cc_ids if c not in new_cc_ids] | ||
743 | 911 | if cc_to_be_deleted: | ||
744 | 912 | dcl_to_be_deleted = dest_cc_link_obj.search(cr, uid, [('dest_id', '=', dest_id), ('cc_id', 'in', cc_to_be_deleted)], | ||
745 | 913 | order='NO_ORDER', context=context) | ||
746 | 914 | dest_cc_link_obj.unlink(cr, uid, dcl_to_be_deleted, context=context) | ||
747 | 915 | # create the CC to be created | ||
748 | 916 | for cc_id in [c for c in new_cc_ids if c not in current_cc_ids]: | ||
749 | 917 | dest_cc_link_obj.create(cr, uid, {'dest_id': dest_id, 'cc_id': cc_id}, context=context) | ||
750 | 918 | del vals['dest_cc_ids'] | ||
751 | 919 | return True | ||
752 | 920 | |||
753 | 788 | def create(self, cr, uid, vals, context=None): | 921 | def create(self, cr, uid, vals, context=None): |
754 | 789 | """ | 922 | """ |
755 | 790 | Some verifications before analytic account creation | 923 | Some verifications before analytic account creation |
756 | @@ -797,6 +930,9 @@ | |||
757 | 797 | self._check_date(vals) | 930 | self._check_date(vals) |
758 | 798 | self.set_funding_pool_parent(cr, uid, vals) | 931 | self.set_funding_pool_parent(cr, uid, vals) |
759 | 799 | vals = self.remove_inappropriate_links(vals, context=context) | 932 | vals = self.remove_inappropriate_links(vals, context=context) |
760 | 933 | vals_copy = vals.copy() | ||
761 | 934 | if self._dest_cc_ids_must_be_updated(vals, context): | ||
762 | 935 | del vals['dest_cc_ids'] # replaced by dest_cc_link_ids in _update_synched_dest_cc_ids (called after create as it uses the new id) | ||
763 | 800 | # for auto instance creation, fx gain has been stored, need HQ sync + instance sync to get CC | 936 | # for auto instance creation, fx gain has been stored, need HQ sync + instance sync to get CC |
764 | 801 | if context.get('sync_update_execution') and vals.get('code') and vals.get('category') == 'OC': | 937 | if context.get('sync_update_execution') and vals.get('code') and vals.get('category') == 'OC': |
765 | 802 | param = self.pool.get('ir.config_parameter') | 938 | param = self.pool.get('ir.config_parameter') |
766 | @@ -804,9 +940,11 @@ | |||
767 | 804 | if init_cc_fx_gain and vals.get('code') == init_cc_fx_gain: | 940 | if init_cc_fx_gain and vals.get('code') == init_cc_fx_gain: |
768 | 805 | vals['for_fx_gain_loss'] = True | 941 | vals['for_fx_gain_loss'] = True |
769 | 806 | param.set_param(cr, 1, 'INIT_CC_FX_GAIN', '') | 942 | param.set_param(cr, 1, 'INIT_CC_FX_GAIN', '') |
773 | 807 | ids = super(analytic_account, self).create(cr, uid, vals, context=context) | 943 | analytic_acc_id = super(analytic_account, self).create(cr, uid, vals, context=context) |
774 | 808 | self._check_name_unicity(cr, uid, ids, context=context) | 944 | self._check_name_unicity(cr, uid, analytic_acc_id, context=context) |
775 | 809 | return ids | 945 | self._clean_dest_cc_link(cr, uid, analytic_acc_id, vals, context=context) |
776 | 946 | self._update_synched_dest_cc_ids(cr, uid, analytic_acc_id, vals_copy, context) | ||
777 | 947 | return analytic_acc_id | ||
778 | 810 | 948 | ||
779 | 811 | def write(self, cr, uid, ids, vals, context=None): | 949 | def write(self, cr, uid, ids, vals, context=None): |
780 | 812 | """ | 950 | """ |
781 | @@ -822,7 +960,9 @@ | |||
782 | 822 | self._check_date(vals) | 960 | self._check_date(vals) |
783 | 823 | self.set_funding_pool_parent(cr, uid, vals) | 961 | self.set_funding_pool_parent(cr, uid, vals) |
784 | 824 | vals = self.remove_inappropriate_links(vals, context=context) | 962 | vals = self.remove_inappropriate_links(vals, context=context) |
785 | 963 | self._update_synched_dest_cc_ids(cr, uid, ids, vals, context) | ||
786 | 825 | res = super(analytic_account, self).write(cr, uid, ids, vals, context=context) | 964 | res = super(analytic_account, self).write(cr, uid, ids, vals, context=context) |
787 | 965 | self._clean_dest_cc_link(cr, uid, ids, vals, context=context) | ||
788 | 826 | self.check_access_rule(cr, uid, ids, 'write', context=context) | 966 | self.check_access_rule(cr, uid, ids, 'write', context=context) |
789 | 827 | if context.get('from_web', False) or context.get('from_import_menu', False): | 967 | if context.get('from_web', False) or context.get('from_import_menu', False): |
790 | 828 | cat_instance = self.read(cr, uid, ids, ['category', 'instance_id', 'is_pf'], context=context)[0] | 968 | cat_instance = self.read(cr, uid, ids, ['category', 'instance_id', 'is_pf'], context=context)[0] |
791 | @@ -919,9 +1059,15 @@ | |||
792 | 919 | 1059 | ||
793 | 920 | def button_dest_cc_clear(self, cr, uid, ids, context=None): | 1060 | def button_dest_cc_clear(self, cr, uid, ids, context=None): |
794 | 921 | """ | 1061 | """ |
796 | 922 | Removes all Cost Centers selected in the Destination view | 1062 | Removes all Dest / CC combinations selected in the Cost Centers tab of the Destination form |
797 | 923 | """ | 1063 | """ |
799 | 924 | self.write(cr, uid, ids, {'dest_cc_ids': [(6, 0, [])]}, context=context) | 1064 | if context is None: |
800 | 1065 | context = {} | ||
801 | 1066 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
802 | 1067 | for dest in self.browse(cr, uid, ids, fields_to_fetch=['dest_cc_link_ids'], context=context): | ||
803 | 1068 | dest_cc_link_ids = [dcl.id for dcl in dest.dest_cc_link_ids] | ||
804 | 1069 | if dest_cc_link_ids: | ||
805 | 1070 | dest_cc_link_obj.unlink(cr, uid, dest_cc_link_ids, context=context) | ||
806 | 925 | return True | 1071 | return True |
807 | 926 | 1072 | ||
808 | 927 | def button_dest_clear(self, cr, uid, ids, context=None): | 1073 | def button_dest_clear(self, cr, uid, ids, context=None): |
809 | @@ -968,6 +1114,28 @@ | |||
810 | 968 | return False | 1114 | return False |
811 | 969 | return True | 1115 | return True |
812 | 970 | 1116 | ||
813 | 1117 | def open_multiple_cc_selection_wizard(self, cr, uid, ids, context=None): | ||
814 | 1118 | """ | ||
815 | 1119 | Creates and displays a Multiple CC Selection Wizard linked to the current Destination | ||
816 | 1120 | """ | ||
817 | 1121 | if context is None: | ||
818 | 1122 | context = {} | ||
819 | 1123 | if isinstance(ids, (int, long)): | ||
820 | 1124 | ids = [ids] | ||
821 | 1125 | multiple_cc_wiz_obj = self.pool.get('multiple.cc.selection.wizard') | ||
822 | 1126 | if ids: | ||
823 | 1127 | multiple_cc_wiz_id = multiple_cc_wiz_obj.create(cr, uid, {'dest_id': ids[0]}, context=context) | ||
824 | 1128 | return { | ||
825 | 1129 | 'type': 'ir.actions.act_window', | ||
826 | 1130 | 'res_model': 'multiple.cc.selection.wizard', | ||
827 | 1131 | 'view_type': 'form', | ||
828 | 1132 | 'view_mode': 'form', | ||
829 | 1133 | 'target': 'new', | ||
830 | 1134 | 'res_id': [multiple_cc_wiz_id], | ||
831 | 1135 | 'context': context, | ||
832 | 1136 | } | ||
833 | 1137 | return True | ||
834 | 1138 | |||
835 | 971 | 1139 | ||
836 | 972 | analytic_account() | 1140 | analytic_account() |
837 | 973 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 1141 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
838 | 974 | 1142 | ||
839 | === modified file 'bin/addons/analytic_override/analytic_line.py' | |||
840 | --- bin/addons/analytic_override/analytic_line.py 2021-04-23 12:31:26 +0000 | |||
841 | +++ bin/addons/analytic_override/analytic_line.py 2021-05-07 16:01:07 +0000 | |||
842 | @@ -159,6 +159,7 @@ | |||
843 | 159 | return True | 159 | return True |
844 | 160 | 160 | ||
845 | 161 | account_obj = self.pool.get('account.analytic.account') | 161 | account_obj = self.pool.get('account.analytic.account') |
846 | 162 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
847 | 162 | 163 | ||
848 | 163 | #US-419: Use the document date and not posting date when checking the validity of analytic account | 164 | #US-419: Use the document date and not posting date when checking the validity of analytic account |
849 | 164 | # tech: replaced all date by document_date | 165 | # tech: replaced all date by document_date |
850 | @@ -171,6 +172,8 @@ | |||
851 | 171 | raise osv.except_osv(_('Error'), _("The analytic account selected '%s' is not active.") % (account.name or '',)) | 172 | raise osv.except_osv(_('Error'), _("The analytic account selected '%s' is not active.") % (account.name or '',)) |
852 | 172 | if 'date' in vals and vals['date'] is not False: | 173 | if 'date' in vals and vals['date'] is not False: |
853 | 173 | date = vals['date'] | 174 | date = vals['date'] |
854 | 175 | dest = False | ||
855 | 176 | cc = False | ||
856 | 174 | if vals.get('cost_center_id', False): | 177 | if vals.get('cost_center_id', False): |
857 | 175 | cc = account_obj.browse(cr, uid, vals['cost_center_id'], context=context) | 178 | cc = account_obj.browse(cr, uid, vals['cost_center_id'], context=context) |
858 | 176 | if date < cc.date_start or (cc.date != False and date >= cc.date): | 179 | if date < cc.date_start or (cc.date != False and date >= cc.date): |
859 | @@ -181,6 +184,9 @@ | |||
860 | 181 | if date < dest.date_start or (dest.date != False and date >= dest.date): | 184 | if date < dest.date_start or (dest.date != False and date >= dest.date): |
861 | 182 | if 'from' not in context or context.get('from') != 'mass_reallocation': | 185 | if 'from' not in context or context.get('from') != 'mass_reallocation': |
862 | 183 | raise osv.except_osv(_('Error'), _("The analytic account selected '%s' is not active.") % (dest.name or '',)) | 186 | raise osv.except_osv(_('Error'), _("The analytic account selected '%s' is not active.") % (dest.name or '',)) |
863 | 187 | if context.get('from') != 'mass_reallocation' and dest and cc and \ | ||
864 | 188 | dest_cc_link_obj.is_inactive_dcl(cr, uid, dest.id, cc.id, date, context=context): | ||
865 | 189 | raise osv.except_osv(_('Error'), _("The combination \"%s - %s\" is not active.") % (dest.code or '', cc.code or '')) | ||
866 | 184 | return True | 190 | return True |
867 | 185 | 191 | ||
868 | 186 | def _check_document_date(self, cr, uid, ids): | 192 | def _check_document_date(self, cr, uid, ids): |
869 | 187 | 193 | ||
870 | === added file 'bin/addons/analytic_override/dest_cc_link.py' | |||
871 | --- bin/addons/analytic_override/dest_cc_link.py 1970-01-01 00:00:00 +0000 | |||
872 | +++ bin/addons/analytic_override/dest_cc_link.py 2021-05-07 16:01:07 +0000 | |||
873 | @@ -0,0 +1,174 @@ | |||
874 | 1 | # -*- coding: utf-8 -*- | ||
875 | 2 | ############################################################################## | ||
876 | 3 | # | ||
877 | 4 | # OpenERP, Open Source Management Solution | ||
878 | 5 | # Copyright (C) 2021 MSF, TeMPO Consulting. | ||
879 | 6 | # | ||
880 | 7 | # This program is free software: you can redistribute it and/or modify | ||
881 | 8 | # it under the terms of the GNU Affero General Public License as | ||
882 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
883 | 10 | # License, or (at your option) any later version. | ||
884 | 11 | # | ||
885 | 12 | # This program is distributed in the hope that it will be useful, | ||
886 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
887 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
888 | 15 | # GNU Affero General Public License for more details. | ||
889 | 16 | # | ||
890 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
891 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
892 | 19 | # | ||
893 | 20 | ############################################################################## | ||
894 | 21 | |||
895 | 22 | from osv import osv | ||
896 | 23 | from osv import fields | ||
897 | 24 | from tools.translate import _ | ||
898 | 25 | |||
899 | 26 | |||
900 | 27 | class dest_cc_link(osv.osv): | ||
901 | 28 | _name = "dest.cc.link" | ||
902 | 29 | _description = "Destination / Cost Center Combination" | ||
903 | 30 | _rec_name = "cc_id" | ||
904 | 31 | _trace = True | ||
905 | 32 | |||
906 | 33 | def _get_current_id(self, cr, uid, ids, field_name, args, context=None): | ||
907 | 34 | """ | ||
908 | 35 | Returns a dict with key = value = current DB id. | ||
909 | 36 | |||
910 | 37 | current_id is an internal field used to make the CC read-only except for new lines (= without DB id). | ||
911 | 38 | The goal is to prevent the edition of a Dest CC Link with a CC linked to a different coordo than the previous CC. | ||
912 | 39 | """ | ||
913 | 40 | res = {} | ||
914 | 41 | for i in ids: | ||
915 | 42 | res[i] = i | ||
916 | 43 | return res | ||
917 | 44 | |||
918 | 45 | def _get_cc_code(self, cr, uid, ids, name, args, context=None): | ||
919 | 46 | """ | ||
920 | 47 | Returns a dict with key = Dest CC Link id, and value = related Cost Center code. | ||
921 | 48 | """ | ||
922 | 49 | if context is None: | ||
923 | 50 | context = {} | ||
924 | 51 | if isinstance(ids, (int, long)): | ||
925 | 52 | ids = [ids] | ||
926 | 53 | res = {} | ||
927 | 54 | for dcl in self.browse(cr, uid, ids, fields_to_fetch=['cc_id'], context=context): | ||
928 | 55 | res[dcl.id] = dcl.cc_id.code or '' | ||
929 | 56 | return res | ||
930 | 57 | |||
931 | 58 | def _get_dest_cc_link_to_update(self, cr, uid, analytic_acc_ids, context=None): | ||
932 | 59 | """ | ||
933 | 60 | Returns the list of Dest CC Links for which the CC code should be updated. | ||
934 | 61 | """ | ||
935 | 62 | if context is None: | ||
936 | 63 | context = {} | ||
937 | 64 | if isinstance(analytic_acc_ids, (int, long)): | ||
938 | 65 | analytic_acc_ids = [analytic_acc_ids] | ||
939 | 66 | return self.pool.get('dest.cc.link').search(cr, uid, [('cc_id', 'in', analytic_acc_ids)], order='NO_ORDER', context=context) | ||
940 | 67 | |||
941 | 68 | _columns = { | ||
942 | 69 | 'dest_id': fields.many2one('account.analytic.account', string="Destination", required=True, | ||
943 | 70 | domain="[('category', '=', 'DEST'), ('type', '!=', 'view')]", ondelete='cascade', select=1), | ||
944 | 71 | 'cc_id': fields.many2one('account.analytic.account', string="Cost Center", required=True, sort_column='cc_code', | ||
945 | 72 | domain="[('category', '=', 'OC'), ('type', '!=', 'view')]", ondelete='cascade', select=1), | ||
946 | 73 | 'cc_code': fields.function(_get_cc_code, method=True, string="Cost Center Code", type='char', size=24, | ||
947 | 74 | readonly=True, | ||
948 | 75 | store={ | ||
949 | 76 | 'account.analytic.account': (_get_dest_cc_link_to_update, ['code'], 10), | ||
950 | 77 | 'dest.cc.link': (lambda self, cr, uid, ids, c=None: ids, ['cc_id'], 20), | ||
951 | 78 | }), | ||
952 | 79 | 'cc_name': fields.related('cc_id', 'name', type="char", string="Cost Center Name", readonly=True, write_relate=False, store=False), | ||
953 | 80 | 'active_from': fields.date('Activation Combination Dest / CC from', required=False), | ||
954 | 81 | 'inactive_from': fields.date('Inactivation Combination Dest / CC from', required=False), | ||
955 | 82 | 'current_id': fields.function(_get_current_id, method=1, type='integer', internal=1, string="DB Id (used by the UI)"), | ||
956 | 83 | } | ||
957 | 84 | |||
958 | 85 | _order = 'dest_id, cc_code, id' | ||
959 | 86 | |||
960 | 87 | _sql_constraints = [ | ||
961 | 88 | ('dest_cc_uniq', 'UNIQUE(dest_id, cc_id)', 'Each Cost Center can only be added once to the same Destination.'), | ||
962 | 89 | ('dest_cc_date_check', 'CHECK(active_from < inactive_from)', 'The Activation date of the "Combination Dest / CC" ' | ||
963 | 90 | 'must be before the Inactivation date.') | ||
964 | 91 | ] | ||
965 | 92 | |||
966 | 93 | def _check_analytic_lines(self, cr, uid, ids, context=None): | ||
967 | 94 | """ | ||
968 | 95 | Displays a non-blocking message on the top of the page in case some AJI using the Dest/CC link have been booked | ||
969 | 96 | outside its activation dates. | ||
970 | 97 | """ | ||
971 | 98 | if context is None: | ||
972 | 99 | context = {} | ||
973 | 100 | if not context.get('sync_update_execution'): | ||
974 | 101 | aal_obj = self.pool.get('account.analytic.line') | ||
975 | 102 | if isinstance(ids, (int, long)): | ||
976 | 103 | ids = [ids] | ||
977 | 104 | for dcl in self.browse(cr, uid, ids, context=context): | ||
978 | 105 | if dcl.active_from or dcl.inactive_from: | ||
979 | 106 | dcl_dom = [('cost_center_id', '=', dcl.cc_id.id), ('destination_id', '=', dcl.dest_id.id)] | ||
980 | 107 | if dcl.active_from and dcl.inactive_from: | ||
981 | 108 | dcl_dom.append('|') | ||
982 | 109 | if dcl.active_from: | ||
983 | 110 | dcl_dom.append(('date', '<', dcl.active_from)) | ||
984 | 111 | if dcl.inactive_from: | ||
985 | 112 | dcl_dom.append(('date', '>=', dcl.inactive_from)) | ||
986 | 113 | if aal_obj.search_exist(cr, uid, dcl_dom, context=context): | ||
987 | 114 | self.log(cr, uid, dcl.id, _('At least one Analytic Journal Item using the combination \"%s - %s\" ' | ||
988 | 115 | 'has a Posting Date outside the activation dates selected.') % | ||
989 | 116 | (dcl.dest_id.code or '', dcl.cc_id.code or '')) | ||
990 | 117 | |||
991 | 118 | def create(self, cr, uid, vals, context=None): | ||
992 | 119 | """ | ||
993 | 120 | Creates the Dest CC Combination, and: | ||
994 | 121 | - displays an informative message on the top of the page if existing AJIs are using the combination outside its activation interval. | ||
995 | 122 | - unticks the box "Allow all Cost Centers" from the related Dest. | ||
996 | 123 | (UC: edit a Dest. having the box ticked, untick the box, add a CC and click on Cancel. | ||
997 | 124 | CC isn't removed by the Cancel button as it is a o2m, so the box should remain unticked.) | ||
998 | 125 | """ | ||
999 | 126 | if context is None: | ||
1000 | 127 | context = {} | ||
1001 | 128 | analytic_acc_obj = self.pool.get('account.analytic.account') | ||
1002 | 129 | res = super(dest_cc_link, self).create(cr, uid, vals, context=context) | ||
1003 | 130 | self._check_analytic_lines(cr, uid, res, context=context) | ||
1004 | 131 | dest_id = self.read(cr, uid, res, ['dest_id'], context=context)['dest_id'][0] | ||
1005 | 132 | if analytic_acc_obj.search_exist(cr, uid, [('id', '=', dest_id), ('allow_all_cc', '=', True)], context=context): | ||
1006 | 133 | analytic_acc_obj.write(cr, uid, dest_id, {'allow_all_cc': False}, context=context) | ||
1007 | 134 | return res | ||
1008 | 135 | |||
1009 | 136 | def write(self, cr, uid, ids, vals, context=None): | ||
1010 | 137 | """ | ||
1011 | 138 | See _check_analytic_lines | ||
1012 | 139 | """ | ||
1013 | 140 | res = super(dest_cc_link, self).write(cr, uid, ids, vals, context=context) | ||
1014 | 141 | self._check_analytic_lines(cr, uid, ids, context=context) | ||
1015 | 142 | return res | ||
1016 | 143 | |||
1017 | 144 | def is_inactive_dcl(self, cr, uid, dest_id, cc_id, posting_date, context=None): | ||
1018 | 145 | """ | ||
1019 | 146 | Returns True if the Dest CC Link with the dest_id and cc_id exists and that the posting_date | ||
1020 | 147 | is outside its validity date range. | ||
1021 | 148 | """ | ||
1022 | 149 | if context is None: | ||
1023 | 150 | context = {} | ||
1024 | 151 | inactive_dcl = False | ||
1025 | 152 | if dest_id and cc_id and posting_date: | ||
1026 | 153 | dcl_ids = self.search(cr, uid, [('dest_id', '=', dest_id), ('cc_id', '=', cc_id)], limit=1, context=context) | ||
1027 | 154 | if dcl_ids: | ||
1028 | 155 | dcl = self.browse(cr, uid, dcl_ids[0], fields_to_fetch=['active_from', 'inactive_from'], context=context) | ||
1029 | 156 | inactive_dcl = (dcl.active_from and posting_date < dcl.active_from) or (dcl.inactive_from and posting_date >= dcl.inactive_from) | ||
1030 | 157 | return inactive_dcl | ||
1031 | 158 | |||
1032 | 159 | def on_change_cc_id(self, cr, uid, ids, cc_id): | ||
1033 | 160 | """ | ||
1034 | 161 | Fills in the CC Name as soon as a CC is selected | ||
1035 | 162 | """ | ||
1036 | 163 | res = {} | ||
1037 | 164 | analytic_acc_obj = self.pool.get('account.analytic.account') | ||
1038 | 165 | if cc_id: | ||
1039 | 166 | name = analytic_acc_obj.read(cr, uid, cc_id, ['name'])['name'] | ||
1040 | 167 | else: | ||
1041 | 168 | name = False | ||
1042 | 169 | res['value'] = {'cc_name': name, } | ||
1043 | 170 | return res | ||
1044 | 171 | |||
1045 | 172 | |||
1046 | 173 | dest_cc_link() | ||
1047 | 174 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1048 | 0 | 175 | ||
1049 | === added file 'bin/addons/analytic_override/dest_cc_link.xml' | |||
1050 | --- bin/addons/analytic_override/dest_cc_link.xml 1970-01-01 00:00:00 +0000 | |||
1051 | +++ bin/addons/analytic_override/dest_cc_link.xml 2021-05-07 16:01:07 +0000 | |||
1052 | @@ -0,0 +1,49 @@ | |||
1053 | 1 | <?xml version="1.0"?> | ||
1054 | 2 | <openerp> | ||
1055 | 3 | <data> | ||
1056 | 4 | <!-- DEST CC LINK - FORM VIEW --> | ||
1057 | 5 | <record id="view_dest_cc_link_form" model="ir.ui.view"> | ||
1058 | 6 | <field name="name">dest.cc.link.form</field> | ||
1059 | 7 | <field name="model">dest.cc.link</field> | ||
1060 | 8 | <field name="type">form</field> | ||
1061 | 9 | <field name="arch" type="xml"> | ||
1062 | 10 | <form noteditable="1"> | ||
1063 | 11 | <field name="cc_id"/> | ||
1064 | 12 | <newline/> | ||
1065 | 13 | <field name="active_from"/> | ||
1066 | 14 | <field name="inactive_from"/> | ||
1067 | 15 | </form> | ||
1068 | 16 | </field> | ||
1069 | 17 | </record> | ||
1070 | 18 | |||
1071 | 19 | <!-- DEST CC LINK - TREE VIEW --> | ||
1072 | 20 | <record id="view_dest_cc_link_tree" model="ir.ui.view"> | ||
1073 | 21 | <field name="name">dest.cc.link.tree</field> | ||
1074 | 22 | <field name="model">dest.cc.link</field> | ||
1075 | 23 | <field name="type">tree</field> | ||
1076 | 24 | <field name="arch" type="xml"> | ||
1077 | 25 | <tree> | ||
1078 | 26 | <field name="cc_id"/> | ||
1079 | 27 | <field name="active_from"/> | ||
1080 | 28 | <field name="inactive_from"/> | ||
1081 | 29 | </tree> | ||
1082 | 30 | </field> | ||
1083 | 31 | </record> | ||
1084 | 32 | |||
1085 | 33 | <!-- DEST CC LINK - SEARCH VIEW --> | ||
1086 | 34 | <record id="view_dest_cc_link_search" model="ir.ui.view"> | ||
1087 | 35 | <field name="name">dest.cc.link.search</field> | ||
1088 | 36 | <field name="model">dest.cc.link</field> | ||
1089 | 37 | <field name="type">search</field> | ||
1090 | 38 | <field name="arch" type="xml"> | ||
1091 | 39 | <search> | ||
1092 | 40 | <group> | ||
1093 | 41 | <field name="cc_id"/> | ||
1094 | 42 | <field name="active_from"/> | ||
1095 | 43 | <field name="inactive_from"/> | ||
1096 | 44 | </group> | ||
1097 | 45 | </search> | ||
1098 | 46 | </field> | ||
1099 | 47 | </record> | ||
1100 | 48 | </data> | ||
1101 | 49 | </openerp> | ||
1102 | 0 | 50 | ||
1103 | === added file 'bin/addons/analytic_override/multiple_cc_selection_wizard.py' | |||
1104 | --- bin/addons/analytic_override/multiple_cc_selection_wizard.py 1970-01-01 00:00:00 +0000 | |||
1105 | +++ bin/addons/analytic_override/multiple_cc_selection_wizard.py 2021-05-07 16:01:07 +0000 | |||
1106 | @@ -0,0 +1,56 @@ | |||
1107 | 1 | # -*- coding: utf-8 -*- | ||
1108 | 2 | ############################################################################## | ||
1109 | 3 | # | ||
1110 | 4 | # OpenERP, Open Source Management Solution | ||
1111 | 5 | # Copyright (C) 2021 MSF, TeMPO Consulting. | ||
1112 | 6 | # | ||
1113 | 7 | # This program is free software: you can redistribute it and/or modify | ||
1114 | 8 | # it under the terms of the GNU Affero General Public License as | ||
1115 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
1116 | 10 | # License, or (at your option) any later version. | ||
1117 | 11 | # | ||
1118 | 12 | # This program is distributed in the hope that it will be useful, | ||
1119 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1120 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1121 | 15 | # GNU Affero General Public License for more details. | ||
1122 | 16 | # | ||
1123 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
1124 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1125 | 19 | # | ||
1126 | 20 | ############################################################################## | ||
1127 | 21 | |||
1128 | 22 | from osv import fields | ||
1129 | 23 | from osv import osv | ||
1130 | 24 | |||
1131 | 25 | |||
1132 | 26 | class multiple_cc_selection_wizard(osv.osv_memory): | ||
1133 | 27 | _name = 'multiple.cc.selection.wizard' | ||
1134 | 28 | |||
1135 | 29 | _columns = { | ||
1136 | 30 | 'dest_id': fields.many2one('account.analytic.account', string="Destination", required=True, | ||
1137 | 31 | domain="[('category', '=', 'DEST'), ('type', '!=', 'view')]"), | ||
1138 | 32 | 'cc_ids': fields.many2many('account.analytic.account', 'multiple_cc_wiz_rel', 'wizard_id', 'cost_center_id', | ||
1139 | 33 | string="Cost Centers", domain="[('category', '=', 'OC'), ('type', '!=', 'view')]"), | ||
1140 | 34 | } | ||
1141 | 35 | |||
1142 | 36 | def multiple_cc_add(self, cr, uid, ids, context=None): | ||
1143 | 37 | """ | ||
1144 | 38 | Adds the Cost Centers selected in the wizard to the current destination | ||
1145 | 39 | without filling in the activation and inactivation dates of the related combinations. | ||
1146 | 40 | """ | ||
1147 | 41 | if context is None: | ||
1148 | 42 | context = {} | ||
1149 | 43 | if isinstance(ids, (int, long)): | ||
1150 | 44 | ids = [ids] | ||
1151 | 45 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
1152 | 46 | analytic_acc_obj = self.pool.get('account.analytic.account') | ||
1153 | 47 | wiz = self.browse(cr, uid, ids[0], context=context) | ||
1154 | 48 | if wiz.cc_ids: | ||
1155 | 49 | for cc in wiz.cc_ids: | ||
1156 | 50 | # note: this automatically unticks the box "Allow all Cost Centers" (as for a manual CC addition) | ||
1157 | 51 | dest_cc_link_obj.create(cr, uid, {'dest_id': wiz.dest_id.id, 'cc_id': cc.id}, context=context) | ||
1158 | 52 | return {'type': 'ir.actions.act_window_close'} | ||
1159 | 53 | |||
1160 | 54 | |||
1161 | 55 | multiple_cc_selection_wizard() | ||
1162 | 56 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1163 | 0 | 57 | ||
1164 | === added file 'bin/addons/analytic_override/multiple_cc_selection_wizard.xml' | |||
1165 | --- bin/addons/analytic_override/multiple_cc_selection_wizard.xml 1970-01-01 00:00:00 +0000 | |||
1166 | +++ bin/addons/analytic_override/multiple_cc_selection_wizard.xml 2021-05-07 16:01:07 +0000 | |||
1167 | @@ -0,0 +1,30 @@ | |||
1168 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1169 | 2 | <openerp> | ||
1170 | 3 | <data> | ||
1171 | 4 | |||
1172 | 5 | <!-- MULTIPLE CC SELECTION WIZARD - FORM VIEW --> | ||
1173 | 6 | <record id="multiple_cc_selection_wizard_form_view" model="ir.ui.view"> | ||
1174 | 7 | <field name="name">multiple.cc.selection.wizard.form</field> | ||
1175 | 8 | <field name="model">multiple.cc.selection.wizard</field> | ||
1176 | 9 | <field name="type">form</field> | ||
1177 | 10 | <field name="arch" type="xml"> | ||
1178 | 11 | <form string="Add several Cost Centers"> | ||
1179 | 12 | <label nolabel="1" colspan="6" | ||
1180 | 13 | string="This wizard enables you to select several Cost Centers at once to be added to the Destination. The activation and inactivation dates of the related Dest / CC combinations will remain empty."/> | ||
1181 | 14 | <field name="cc_ids" nolabel="1" colspan="6"> | ||
1182 | 15 | <tree string="Cost Centers"> | ||
1183 | 16 | <field name="code"/> | ||
1184 | 17 | <field name="name"/> | ||
1185 | 18 | </tree> | ||
1186 | 19 | </field> | ||
1187 | 20 | <group colspan="6" col="4"> | ||
1188 | 21 | <label string="" colspan="2"/> | ||
1189 | 22 | <button icon="gtk-cancel" string="Cancel" special="cancel" colspan="1"/> | ||
1190 | 23 | <button icon="gtk-add" string="Add" name="multiple_cc_add" type="object" colspan="1"/> | ||
1191 | 24 | </group> | ||
1192 | 25 | </form> | ||
1193 | 26 | </field> | ||
1194 | 27 | </record> | ||
1195 | 28 | |||
1196 | 29 | </data> | ||
1197 | 30 | </openerp> | ||
1198 | 0 | 31 | ||
1199 | === modified file 'bin/addons/financing_contract/financing_contract_account_quadruplet.py' | |||
1200 | --- bin/addons/financing_contract/financing_contract_account_quadruplet.py 2020-11-20 15:52:12 +0000 | |||
1201 | +++ bin/addons/financing_contract/financing_contract_account_quadruplet.py 2021-05-07 16:01:07 +0000 | |||
1202 | @@ -89,14 +89,15 @@ | |||
1203 | 89 | funding_pool_associated_destinations fpad, | 89 | funding_pool_associated_destinations fpad, |
1204 | 90 | account_destination_link lnk, | 90 | account_destination_link lnk, |
1205 | 91 | account_analytic_account dest | 91 | account_analytic_account dest |
1207 | 92 | LEFT JOIN destination_cost_center_rel dest_cc_rel ON dest_cc_rel.destination_id = dest.id | 92 | LEFT JOIN dest_cc_link ON dest_cc_link.dest_id = dest.id |
1208 | 93 | |||
1209 | 93 | WHERE | 94 | WHERE |
1210 | 94 | fpacc.funding_pool_id = fp.id AND | 95 | fpacc.funding_pool_id = fp.id AND |
1211 | 95 | fpacc.cost_center_id = cc.id AND | 96 | fpacc.cost_center_id = cc.id AND |
1212 | 96 | lnk.id = fpad.tuple_id AND | 97 | lnk.id = fpad.tuple_id AND |
1213 | 97 | fp.id = fpad.funding_pool_id AND | 98 | fp.id = fpad.funding_pool_id AND |
1214 | 98 | lnk.destination_id = dest.id AND | 99 | lnk.destination_id = dest.id AND |
1216 | 99 | (dest.allow_all_cc = 't' or dest_cc_rel.cost_center_id = cc.id) | 100 | (dest.allow_all_cc = 't' or dest_cc_link.cc_id = cc.id) |
1217 | 100 | 101 | ||
1218 | 101 | UNION | 102 | UNION |
1219 | 102 | 103 | ||
1220 | @@ -111,7 +112,7 @@ | |||
1221 | 111 | account_destination_link lnk, | 112 | account_destination_link lnk, |
1222 | 112 | account_account gl_account, | 113 | account_account gl_account, |
1223 | 113 | account_analytic_account dest | 114 | account_analytic_account dest |
1225 | 114 | LEFT JOIN destination_cost_center_rel dest_cc_rel ON dest_cc_rel.destination_id = dest.id | 115 | LEFT JOIN dest_cc_link ON dest_cc_link.dest_id = dest.id |
1226 | 115 | where | 116 | where |
1227 | 116 | fp.allow_all_cc_with_fp = 't' and | 117 | fp.allow_all_cc_with_fp = 't' and |
1228 | 117 | cc.type != 'view' and | 118 | cc.type != 'view' and |
1229 | @@ -123,7 +124,7 @@ | |||
1230 | 123 | fp_account_rel.account_id= gl_account.id and | 124 | fp_account_rel.account_id= gl_account.id and |
1231 | 124 | lnk.account_id = gl_account.id and | 125 | lnk.account_id = gl_account.id and |
1232 | 125 | lnk.destination_id = dest.id and | 126 | lnk.destination_id = dest.id and |
1234 | 126 | (dest.allow_all_cc = 't' or dest_cc_rel.cost_center_id = cc.id) | 127 | (dest.allow_all_cc = 't' or dest_cc_link.cc_id = cc.id) |
1235 | 127 | 128 | ||
1236 | 128 | UNION | 129 | UNION |
1237 | 129 | 130 | ||
1238 | @@ -138,7 +139,7 @@ | |||
1239 | 138 | account_destination_link lnk, | 139 | account_destination_link lnk, |
1240 | 139 | account_account gl_account, | 140 | account_account gl_account, |
1241 | 140 | account_analytic_account dest | 141 | account_analytic_account dest |
1243 | 141 | LEFT JOIN destination_cost_center_rel dest_cc_rel ON dest_cc_rel.destination_id = dest.id | 142 | LEFT JOIN dest_cc_link ON dest_cc_link.dest_id = dest.id |
1244 | 142 | where | 143 | where |
1245 | 143 | fp.allow_all_cc_with_fp = 'f' and | 144 | fp.allow_all_cc_with_fp = 'f' and |
1246 | 144 | fpacc.funding_pool_id = fp.id and | 145 | fpacc.funding_pool_id = fp.id and |
1247 | @@ -148,7 +149,7 @@ | |||
1248 | 148 | fp_account_rel.account_id= gl_account.id and | 149 | fp_account_rel.account_id= gl_account.id and |
1249 | 149 | lnk.account_id = gl_account.id and | 150 | lnk.account_id = gl_account.id and |
1250 | 150 | lnk.destination_id = dest.id and | 151 | lnk.destination_id = dest.id and |
1252 | 151 | (dest.allow_all_cc = 't' or dest_cc_rel.cost_center_id = cc.id) | 152 | (dest.allow_all_cc = 't' or dest_cc_link.cc_id = cc.id) |
1253 | 152 | 153 | ||
1254 | 153 | UNION | 154 | UNION |
1255 | 154 | 155 | ||
1256 | @@ -162,7 +163,7 @@ | |||
1257 | 162 | account_target_costcenter target, | 163 | account_target_costcenter target, |
1258 | 163 | account_destination_link lnk, | 164 | account_destination_link lnk, |
1259 | 164 | account_analytic_account dest | 165 | account_analytic_account dest |
1261 | 165 | LEFT JOIN destination_cost_center_rel dest_cc_rel ON dest_cc_rel.destination_id = dest.id | 166 | LEFT JOIN dest_cc_link ON dest_cc_link.dest_id = dest.id |
1262 | 166 | where | 167 | where |
1263 | 167 | fp.allow_all_cc_with_fp = 't' and | 168 | fp.allow_all_cc_with_fp = 't' and |
1264 | 168 | cc.type != 'view' and | 169 | cc.type != 'view' and |
1265 | @@ -173,7 +174,7 @@ | |||
1266 | 173 | lnk.id = fpad.tuple_id and | 174 | lnk.id = fpad.tuple_id and |
1267 | 174 | fp.id = fpad.funding_pool_id and | 175 | fp.id = fpad.funding_pool_id and |
1268 | 175 | lnk.destination_id = dest.id and | 176 | lnk.destination_id = dest.id and |
1270 | 176 | (dest.allow_all_cc = 't' or dest_cc_rel.cost_center_id = cc.id) | 177 | (dest.allow_all_cc = 't' or dest_cc_link.cc_id = cc.id) |
1271 | 177 | ) AS combinations | 178 | ) AS combinations |
1272 | 178 | )""") | 179 | )""") |
1273 | 179 | return res | 180 | return res |
1274 | 180 | 181 | ||
1275 | === modified file 'bin/addons/msf_audittrail/__openerp__.py' | |||
1276 | --- bin/addons/msf_audittrail/__openerp__.py 2021-05-05 16:04:38 +0000 | |||
1277 | +++ bin/addons/msf_audittrail/__openerp__.py 2021-05-07 16:01:07 +0000 | |||
1278 | @@ -57,7 +57,11 @@ | |||
1279 | 57 | 'data/audittrail_account_account.yml', | 57 | 'data/audittrail_account_account.yml', |
1280 | 58 | 'data/audittrail_account_tax.yml', | 58 | 'data/audittrail_account_tax.yml', |
1281 | 59 | 'data/audittrail_res_company.yml', | 59 | 'data/audittrail_res_company.yml', |
1282 | 60 | <<<<<<< TREE | ||
1283 | 60 | 'data/audittrail_hq_entry.yml', | 61 | 'data/audittrail_hq_entry.yml', |
1284 | 62 | ======= | ||
1285 | 63 | 'data/audittrail_dest_cc_link.yml', | ||
1286 | 64 | >>>>>>> MERGE-SOURCE | ||
1287 | 61 | 'audittrail_report.xml', | 65 | 'audittrail_report.xml', |
1288 | 62 | 'audittrail_invoice_data.yml', | 66 | 'audittrail_invoice_data.yml', |
1289 | 63 | ], | 67 | ], |
1290 | 64 | 68 | ||
1291 | === added file 'bin/addons/msf_audittrail/data/audittrail_dest_cc_link.yml' | |||
1292 | --- bin/addons/msf_audittrail/data/audittrail_dest_cc_link.yml 1970-01-01 00:00:00 +0000 | |||
1293 | +++ bin/addons/msf_audittrail/data/audittrail_dest_cc_link.yml 2021-05-07 16:01:07 +0000 | |||
1294 | @@ -0,0 +1,39 @@ | |||
1295 | 1 | - | ||
1296 | 2 | For Dest CC Links (dest.cc.link), track the changes on the Destinations | ||
1297 | 3 | - | ||
1298 | 4 | !python {model: audittrail.rule}: | | ||
1299 | 5 | name = 'Dest / CC Combinations' | ||
1300 | 6 | object_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', 'dest.cc.link')], context=context) | ||
1301 | 7 | rule_id = self.search(cr, uid, [('object_id', 'in', object_ids)], context=context) | ||
1302 | 8 | if object_ids: | ||
1303 | 9 | # Create the rule | ||
1304 | 10 | fields = ['cc_id', 'active_from', 'inactive_from'] | ||
1305 | 11 | fields_ids = self.pool.get('ir.model.fields').search(cr, uid, [('model', '=', 'dest.cc.link'), ('name', 'in', fields)], context=context) | ||
1306 | 12 | field_name = self.pool.get('ir.model.fields').search(cr, uid, [('model', '=', 'dest.cc.link'), ('name', '=', 'cc_id')], context=context) | ||
1307 | 13 | field_parent = self.pool.get('ir.model.fields').search(cr, uid, [('model', '=', 'dest.cc.link'), ('name', '=', 'dest_id')], context=context) | ||
1308 | 14 | |||
1309 | 15 | name_id = False | ||
1310 | 16 | parent_id = False | ||
1311 | 17 | |||
1312 | 18 | if field_parent: | ||
1313 | 19 | parent_id = field_parent[0] | ||
1314 | 20 | if field_name: | ||
1315 | 21 | name_id = field_name[0] | ||
1316 | 22 | |||
1317 | 23 | vals = { | ||
1318 | 24 | 'name': name, | ||
1319 | 25 | 'object_id': object_ids[0], | ||
1320 | 26 | 'log_write': True, | ||
1321 | 27 | 'log_unlink': True, | ||
1322 | 28 | 'log_create': True, | ||
1323 | 29 | 'field_ids': [(6, 0, fields_ids)], | ||
1324 | 30 | 'parent_field_id': parent_id, | ||
1325 | 31 | 'name_get_field_id': name_id, | ||
1326 | 32 | } | ||
1327 | 33 | |||
1328 | 34 | if not rule_id: | ||
1329 | 35 | rule_id = self.create(cr, uid, vals, context=context) | ||
1330 | 36 | elif rule_id: | ||
1331 | 37 | self.write(cr, uid, rule_id, vals, context=context) | ||
1332 | 38 | # Subscribe to the rule | ||
1333 | 39 | self.subscribe(cr, uid, rule_id) | ||
1334 | 0 | 40 | ||
1335 | === modified file 'bin/addons/msf_doc_import/msf_import_export.py' | |||
1336 | --- bin/addons/msf_doc_import/msf_import_export.py 2019-05-27 10:02:18 +0000 | |||
1337 | +++ bin/addons/msf_doc_import/msf_import_export.py 2021-05-07 16:01:07 +0000 | |||
1338 | @@ -32,6 +32,7 @@ | |||
1339 | 32 | from tempfile import TemporaryFile | 32 | from tempfile import TemporaryFile |
1340 | 33 | from lxml import etree | 33 | from lxml import etree |
1341 | 34 | from lxml.etree import XMLSyntaxError | 34 | from lxml.etree import XMLSyntaxError |
1342 | 35 | from datetime import datetime | ||
1343 | 35 | 36 | ||
1344 | 36 | from msf_doc_import.wizard.abstract_wizard_import import ImportHeader | 37 | from msf_doc_import.wizard.abstract_wizard_import import ImportHeader |
1345 | 37 | from msf_doc_import.msf_import_export_conf import MODEL_DICT | 38 | from msf_doc_import.msf_import_export_conf import MODEL_DICT |
1346 | @@ -626,6 +627,58 @@ | |||
1347 | 626 | # thread.join(wait_time) | 627 | # thread.join(wait_time) |
1348 | 627 | return self.bg_import(cr, uid, wiz, expected_headers, rows, raise_on_error=raise_on_error, context=context) | 628 | return self.bg_import(cr, uid, wiz, expected_headers, rows, raise_on_error=raise_on_error, context=context) |
1349 | 628 | 629 | ||
1350 | 630 | def _handle_dest_cc_dates(self, cr, uid, data, dest_cc_list, dest_cc_tuple_list, context=None): | ||
1351 | 631 | """ | ||
1352 | 632 | Gets and checks the dest_cc_link_active_from and dest_cc_link_inactive_from dates. | ||
1353 | 633 | Updates the dest_cc_tuple_list with tuples containing (cost_center, active_date, inactive_date) | ||
1354 | 634 | """ | ||
1355 | 635 | if context is None: | ||
1356 | 636 | context = {} | ||
1357 | 637 | dest_cc_active_date_list = [] | ||
1358 | 638 | dest_cc_inactive_date_list = [] | ||
1359 | 639 | active_from = (True, 'dest_cc_link_active_from', _("Activation Combination Dest / CC from")) | ||
1360 | 640 | inactive_from = (False, 'dest_cc_link_inactive_from', _("Inactivation Combination Dest / CC from")) | ||
1361 | 641 | for t in [active_from, inactive_from]: | ||
1362 | 642 | active = t[0] | ||
1363 | 643 | col_name = t[1] | ||
1364 | 644 | col_str = t[2] | ||
1365 | 645 | dest_cc_date_list = [] | ||
1366 | 646 | if data.get(col_name): | ||
1367 | 647 | split_char = ';' | ||
1368 | 648 | if split_char not in data.get(col_name): | ||
1369 | 649 | split_char = ',' | ||
1370 | 650 | for cost_center_date in data.get(col_name).split(split_char): | ||
1371 | 651 | cc_date = cost_center_date.strip() | ||
1372 | 652 | if cc_date: | ||
1373 | 653 | cc_date = cc_date.replace(' 00:00:00.00', '') # can be if there is only one date in the cell | ||
1374 | 654 | try: | ||
1375 | 655 | cc_date = datetime.strptime(cc_date, "%Y-%m-%d") | ||
1376 | 656 | except ValueError: | ||
1377 | 657 | raise Exception(_('The dates in the column "%s" should use the format YYYY-MM-DD.') % col_str) | ||
1378 | 658 | else: | ||
1379 | 659 | cc_date = False # the related Dest/CC combination has no activation/inactivation date | ||
1380 | 660 | dest_cc_date_list.append(cc_date) | ||
1381 | 661 | del data[col_name] | ||
1382 | 662 | if len(dest_cc_date_list) > len(dest_cc_list): | ||
1383 | 663 | raise Exception(_('The number of dates in the column "%s" exceeds the number of Cost Centers indicated.') % col_str) | ||
1384 | 664 | if active: | ||
1385 | 665 | dest_cc_active_date_list = dest_cc_date_list[:] | ||
1386 | 666 | else: | ||
1387 | 667 | dest_cc_inactive_date_list = dest_cc_date_list[:] | ||
1388 | 668 | for num, cc in enumerate(dest_cc_list): | ||
1389 | 669 | try: | ||
1390 | 670 | dest_cc_active_date = dest_cc_active_date_list[num] | ||
1391 | 671 | except IndexError: | ||
1392 | 672 | dest_cc_active_date = False | ||
1393 | 673 | try: | ||
1394 | 674 | dest_cc_inactive_date = dest_cc_inactive_date_list[num] | ||
1395 | 675 | except IndexError: | ||
1396 | 676 | dest_cc_inactive_date = False | ||
1397 | 677 | if dest_cc_active_date and dest_cc_inactive_date and dest_cc_active_date >= dest_cc_inactive_date: | ||
1398 | 678 | cc_code = self.pool.get('account.analytic.account').read(cr, uid, cc, ['code'], context=context)['code'] or '' | ||
1399 | 679 | raise Exception(_('The activation date related to the Cost Center %s must be before the inactivation date.') % cc_code) | ||
1400 | 680 | dest_cc_tuple_list.append((cc, dest_cc_active_date, dest_cc_inactive_date)) | ||
1401 | 681 | |||
1402 | 629 | def bg_import(self, cr, uid, import_brw, headers, rows, raise_on_error=False, context=None): | 682 | def bg_import(self, cr, uid, import_brw, headers, rows, raise_on_error=False, context=None): |
1403 | 630 | """ | 683 | """ |
1404 | 631 | Run the import of lines in background | 684 | Run the import of lines in background |
1405 | @@ -647,6 +700,7 @@ | |||
1406 | 647 | acc_obj = self.pool.get('account.account') | 700 | acc_obj = self.pool.get('account.account') |
1407 | 648 | acc_analytic_obj = self.pool.get('account.analytic.account') | 701 | acc_analytic_obj = self.pool.get('account.analytic.account') |
1408 | 649 | acc_dest_obj = self.pool.get('account.destination.link') | 702 | acc_dest_obj = self.pool.get('account.destination.link') |
1409 | 703 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
1410 | 650 | 704 | ||
1411 | 651 | cost_centers_cache = {} | 705 | cost_centers_cache = {} |
1412 | 652 | gl_account_cache = {} | 706 | gl_account_cache = {} |
1413 | @@ -731,7 +785,7 @@ | |||
1414 | 731 | # custom process to retrieve CC, Destination_ids | 785 | # custom process to retrieve CC, Destination_ids |
1415 | 732 | custom_m2m = [] | 786 | custom_m2m = [] |
1416 | 733 | if import_brw.model_list_selection == 'destinations': | 787 | if import_brw.model_list_selection == 'destinations': |
1418 | 734 | custom_m2m = ['dest_cc_ids', 'destination_ids'] | 788 | custom_m2m = ['destination_ids'] |
1419 | 735 | elif import_brw.model_list_selection == 'funding_pools': | 789 | elif import_brw.model_list_selection == 'funding_pools': |
1420 | 736 | custom_m2m = ['cost_center_ids', 'tuple_destination_account_ids'] | 790 | custom_m2m = ['cost_center_ids', 'tuple_destination_account_ids'] |
1421 | 737 | for c_m2m in custom_m2m: | 791 | for c_m2m in custom_m2m: |
1422 | @@ -1025,6 +1079,7 @@ | |||
1423 | 1025 | data['tuple_destination_account_ids'] = [(6, 0, [])] | 1079 | data['tuple_destination_account_ids'] = [(6, 0, [])] |
1424 | 1026 | 1080 | ||
1425 | 1027 | # Destinations | 1081 | # Destinations |
1426 | 1082 | dest_cc_tuple_list = [] | ||
1427 | 1028 | if import_brw.model_list_selection == 'destinations': | 1083 | if import_brw.model_list_selection == 'destinations': |
1428 | 1029 | context['from_import_menu'] = True | 1084 | context['from_import_menu'] = True |
1429 | 1030 | data['category'] = 'DEST' | 1085 | data['category'] = 'DEST' |
1430 | @@ -1042,14 +1097,14 @@ | |||
1431 | 1042 | if data['type'] not in ['normal', 'view']: | 1097 | if data['type'] not in ['normal', 'view']: |
1432 | 1043 | raise Exception(_('The Type must be either "Normal" or "View".')) | 1098 | raise Exception(_('The Type must be either "Normal" or "View".')) |
1433 | 1044 | # Cost Centers | 1099 | # Cost Centers |
1435 | 1045 | if data.get('dest_cc_ids'): | 1100 | dest_cc_list = [] |
1436 | 1101 | if data.get('dest_cc_link_ids'): | ||
1437 | 1046 | if data.get('allow_all_cc'): | 1102 | if data.get('allow_all_cc'): |
1438 | 1047 | raise Exception(_("Please either list the Cost Centers to allow, or allow all Cost Centers.")) | 1103 | raise Exception(_("Please either list the Cost Centers to allow, or allow all Cost Centers.")) |
1439 | 1048 | dest_cc_list = [] | ||
1440 | 1049 | split_char = ';' | 1104 | split_char = ';' |
1442 | 1050 | if split_char not in data.get('dest_cc_ids'): | 1105 | if split_char not in data.get('dest_cc_link_ids'): |
1443 | 1051 | split_char = ',' | 1106 | split_char = ',' |
1445 | 1052 | for cost_center in data.get('dest_cc_ids').split(split_char): | 1107 | for cost_center in data.get('dest_cc_link_ids').split(split_char): |
1446 | 1053 | cc = cost_center.strip() | 1108 | cc = cost_center.strip() |
1447 | 1054 | if cc not in cost_centers_cache: | 1109 | if cc not in cost_centers_cache: |
1448 | 1055 | cc_dom = [('category', '=', 'OC'), ('type', '=', 'normal'), ('code', '=', cc)] | 1110 | cc_dom = [('category', '=', 'OC'), ('type', '=', 'normal'), ('code', '=', cc)] |
1449 | @@ -1059,9 +1114,7 @@ | |||
1450 | 1059 | dest_cc_list.append(cc_ids[0]) | 1114 | dest_cc_list.append(cc_ids[0]) |
1451 | 1060 | else: | 1115 | else: |
1452 | 1061 | raise Exception(_('Cost Center "%s" not found.') % cc) | 1116 | raise Exception(_('Cost Center "%s" not found.') % cc) |
1456 | 1062 | data['dest_cc_ids'] = [(6, 0, dest_cc_list)] | 1117 | self._handle_dest_cc_dates(cr, uid, data, dest_cc_list, dest_cc_tuple_list, context=context) |
1454 | 1063 | else: | ||
1455 | 1064 | data['dest_cc_ids'] = [(6, 0, [])] | ||
1457 | 1065 | # Accounts | 1118 | # Accounts |
1458 | 1066 | if data.get('destination_ids'): # "destinations_ids" corresponds to G/L accounts... | 1119 | if data.get('destination_ids'): # "destinations_ids" corresponds to G/L accounts... |
1459 | 1067 | acc_list = [] | 1120 | acc_list = [] |
1460 | @@ -1089,8 +1142,6 @@ | |||
1461 | 1089 | # in case of empty columns on non-required fields, existing values should be deleted | 1142 | # in case of empty columns on non-required fields, existing values should be deleted |
1462 | 1090 | if 'date' not in data: | 1143 | if 'date' not in data: |
1463 | 1091 | data['date'] = False | 1144 | data['date'] = False |
1464 | 1092 | if 'dest_cc_ids' not in data: | ||
1465 | 1093 | data['dest_cc_ids'] = [(6, 0, [])] | ||
1466 | 1094 | if 'allow_all_cc' not in data: | 1145 | if 'allow_all_cc' not in data: |
1467 | 1095 | data['allow_all_cc'] = False | 1146 | data['allow_all_cc'] = False |
1468 | 1096 | if 'destination_ids' not in data: | 1147 | if 'destination_ids' not in data: |
1469 | @@ -1164,6 +1215,7 @@ | |||
1470 | 1164 | 1215 | ||
1471 | 1165 | data.update(forced_values) | 1216 | data.update(forced_values) |
1472 | 1166 | 1217 | ||
1473 | 1218 | id_created = False | ||
1474 | 1167 | if data.get('comment') == '[DELETE]': | 1219 | if data.get('comment') == '[DELETE]': |
1475 | 1168 | impobj.unlink(cr, uid, ids_to_update, context=context) | 1220 | impobj.unlink(cr, uid, ids_to_update, context=context) |
1476 | 1169 | nb_lines_deleted += len(ids_to_update) | 1221 | nb_lines_deleted += len(ids_to_update) |
1477 | @@ -1182,11 +1234,66 @@ | |||
1478 | 1182 | line_created = impobj.create(cr, uid, data, context=context) | 1234 | line_created = impobj.create(cr, uid, data, context=context) |
1479 | 1183 | lines_already_updated.append(line_created) | 1235 | lines_already_updated.append(line_created) |
1480 | 1184 | else: | 1236 | else: |
1482 | 1185 | impobj.create(cr, uid, data, context=context) | 1237 | id_created = impobj.create(cr, uid, data, context=context) |
1483 | 1186 | nb_succes += 1 | 1238 | nb_succes += 1 |
1484 | 1187 | processed.append((row_index+1, line_data)) | 1239 | processed.append((row_index+1, line_data)) |
1485 | 1188 | if allow_partial: | 1240 | if allow_partial: |
1486 | 1189 | cr.commit() | 1241 | cr.commit() |
1487 | 1242 | # For Dest CC Links: create, update or delete the links if necessary | ||
1488 | 1243 | if import_brw.model_list_selection == 'destinations': | ||
1489 | 1244 | if isinstance(ids_to_update, (int, long)): | ||
1490 | 1245 | ids_to_update = [ids_to_update] | ||
1491 | 1246 | if not dest_cc_tuple_list and ids_to_update: | ||
1492 | 1247 | # UC1: Dest CC Link column empty => delete all current Dest/CC combinations attached to the Dest | ||
1493 | 1248 | old_dcl_ids = dest_cc_link_obj.search(cr, uid, [('dest_id', 'in', ids_to_update)], order='NO_ORDER', context=context) | ||
1494 | 1249 | if old_dcl_ids: | ||
1495 | 1250 | dest_cc_link_obj.unlink(cr, uid, old_dcl_ids, context=context) | ||
1496 | 1251 | else: | ||
1497 | 1252 | # UC2: new dest | ||
1498 | 1253 | if id_created: | ||
1499 | 1254 | for cc, active_date, inactive_date in dest_cc_tuple_list: | ||
1500 | 1255 | dest_cc_link_obj.create(cr, uid, {'cc_id': cc, 'dest_id': id_created, | ||
1501 | 1256 | 'active_from': active_date, 'inactive_from': inactive_date}, | ||
1502 | 1257 | context=context) | ||
1503 | 1258 | elif ids_to_update: | ||
1504 | 1259 | for dest_id in ids_to_update: | ||
1505 | 1260 | dest = acc_analytic_obj.browse(cr, uid, dest_id, fields_to_fetch=['dest_cc_link_ids'], context=context) | ||
1506 | 1261 | current_cc_ids = [dest_cc_link.cc_id.id for dest_cc_link in dest.dest_cc_link_ids] | ||
1507 | 1262 | new_cc_ids = [] | ||
1508 | 1263 | for cc, active_date, inactive_date in dest_cc_tuple_list: | ||
1509 | 1264 | new_cc_ids.append(cc) | ||
1510 | 1265 | # UC3: new combinations in existing Destinations | ||
1511 | 1266 | if cc not in current_cc_ids: | ||
1512 | 1267 | dest_cc_link_obj.create(cr, uid, {'cc_id': cc, 'dest_id': dest_id, | ||
1513 | 1268 | 'active_from': active_date, 'inactive_from': inactive_date}, | ||
1514 | 1269 | context=context) | ||
1515 | 1270 | else: | ||
1516 | 1271 | # UC4: combinations to be updated with new dates | ||
1517 | 1272 | dcl_ids = dest_cc_link_obj.search(cr, uid, | ||
1518 | 1273 | [('dest_id', '=', dest_id), ('cc_id', '=', cc)], | ||
1519 | 1274 | limit=1, context=context) | ||
1520 | 1275 | if dcl_ids: | ||
1521 | 1276 | dest_cc_link = dest_cc_link_obj.read(cr, uid, dcl_ids[0], | ||
1522 | 1277 | ['active_from', 'inactive_from'], context=context) | ||
1523 | 1278 | if dest_cc_link['active_from']: | ||
1524 | 1279 | current_active_dt = datetime.strptime(dest_cc_link['active_from'], "%Y-%m-%d") | ||
1525 | 1280 | else: | ||
1526 | 1281 | current_active_dt = False | ||
1527 | 1282 | if dest_cc_link['inactive_from']: | ||
1528 | 1283 | current_inactive_dt = datetime.strptime(dest_cc_link['inactive_from'], "%Y-%m-%d") | ||
1529 | 1284 | else: | ||
1530 | 1285 | current_inactive_dt = False | ||
1531 | 1286 | if (current_active_dt != active_date) or (current_inactive_dt != inactive_date): | ||
1532 | 1287 | dest_cc_link_obj.write(cr, uid, dest_cc_link['id'], | ||
1533 | 1288 | {'active_from': active_date, 'inactive_from': inactive_date}, | ||
1534 | 1289 | context=context) | ||
1535 | 1290 | # UC5: combinations to be deleted in existing Destinations | ||
1536 | 1291 | cc_to_be_deleted = [c for c in current_cc_ids if c not in new_cc_ids] | ||
1537 | 1292 | if cc_to_be_deleted: | ||
1538 | 1293 | dcl_to_be_deleted = dest_cc_link_obj.search(cr, uid, | ||
1539 | 1294 | [('dest_id', '=', dest_id), ('cc_id', 'in', cc_to_be_deleted)], | ||
1540 | 1295 | order='NO_ORDER', context=context) | ||
1541 | 1296 | dest_cc_link_obj.unlink(cr, uid, dcl_to_be_deleted, context=context) | ||
1542 | 1190 | except (osv.except_osv, orm.except_orm) , e: | 1297 | except (osv.except_osv, orm.except_orm) , e: |
1543 | 1191 | logging.getLogger('import data').info('Error %s' % e.value) | 1298 | logging.getLogger('import data').info('Error %s' % e.value) |
1544 | 1192 | if raise_on_error: | 1299 | if raise_on_error: |
1545 | 1193 | 1300 | ||
1546 | === modified file 'bin/addons/msf_doc_import/msf_import_export_conf.py' | |||
1547 | --- bin/addons/msf_doc_import/msf_import_export_conf.py 2019-05-27 09:37:55 +0000 | |||
1548 | +++ bin/addons/msf_doc_import/msf_import_export_conf.py 2021-05-07 16:01:07 +0000 | |||
1549 | @@ -549,7 +549,9 @@ | |||
1550 | 549 | 'type', | 549 | 'type', |
1551 | 550 | 'date_start', | 550 | 'date_start', |
1552 | 551 | 'date', # "inactive from" | 551 | 'date', # "inactive from" |
1554 | 552 | 'dest_cc_ids', | 552 | 'dest_cc_link_ids', |
1555 | 553 | 'dest_cc_link_active_from', | ||
1556 | 554 | 'dest_cc_link_inactive_from', | ||
1557 | 553 | 'destination_ids', | 555 | 'destination_ids', |
1558 | 554 | 'allow_all_cc', | 556 | 'allow_all_cc', |
1559 | 555 | ], | 557 | ], |
1560 | 556 | 558 | ||
1561 | === modified file 'bin/addons/msf_homere_interface/hr_payroll.py' | |||
1562 | --- bin/addons/msf_homere_interface/hr_payroll.py 2020-10-13 10:14:53 +0000 | |||
1563 | +++ bin/addons/msf_homere_interface/hr_payroll.py 2021-05-07 16:01:07 +0000 | |||
1564 | @@ -43,6 +43,7 @@ | |||
1565 | 43 | # Prepare some values | 43 | # Prepare some values |
1566 | 44 | res = {} | 44 | res = {} |
1567 | 45 | ad_obj = self.pool.get('analytic.distribution') | 45 | ad_obj = self.pool.get('analytic.distribution') |
1568 | 46 | dest_cc_link_obj = self.pool.get('dest.cc.link') | ||
1569 | 46 | # Search MSF Private Fund element, because it's valid with all accounts | 47 | # Search MSF Private Fund element, because it's valid with all accounts |
1570 | 47 | try: | 48 | try: |
1571 | 48 | fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', | 49 | fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', |
1572 | @@ -84,6 +85,10 @@ | |||
1573 | 84 | if dest and dest.filter_active is False: | 85 | if dest and dest.filter_active is False: |
1574 | 85 | res[line.id] = 'invalid' | 86 | res[line.id] = 'invalid' |
1575 | 86 | continue | 87 | continue |
1576 | 88 | if line.destination_id and line.cost_center_id: | ||
1577 | 89 | if dest_cc_link_obj.is_inactive_dcl(cr, uid, line.destination_id.id, line.cost_center_id.id, line.date, context=context): | ||
1578 | 90 | res[line.id] = 'invalid' | ||
1579 | 91 | continue | ||
1580 | 87 | # G Check | 92 | # G Check |
1581 | 88 | if line.funding_pool_id: | 93 | if line.funding_pool_id: |
1582 | 89 | fp = self.pool.get('account.analytic.account').browse(cr, uid, line.funding_pool_id.id, context={'date': line.document_date}) | 94 | fp = self.pool.get('account.analytic.account').browse(cr, uid, line.funding_pool_id.id, context={'date': line.document_date}) |
1583 | @@ -202,6 +207,26 @@ | |||
1584 | 202 | ]) | 207 | ]) |
1585 | 203 | return to_update | 208 | return to_update |
1586 | 204 | 209 | ||
1587 | 210 | def _get_trigger_state_dest_cc_link(self, cr, uid, ids, context=None): | ||
1588 | 211 | """ | ||
1589 | 212 | Returns the list of Payroll Entries for which the AD state should be re-computed | ||
1590 | 213 | """ | ||
1591 | 214 | if context is None: | ||
1592 | 215 | context = {} | ||
1593 | 216 | if isinstance(ids, (int, long)): | ||
1594 | 217 | ids = [ids] | ||
1595 | 218 | cc_ids = [] | ||
1596 | 219 | dest_ids = [] | ||
1597 | 220 | payroll_obj = self.pool.get('hr.payroll.msf') | ||
1598 | 221 | for dest_cc_link in self.browse(cr, uid, ids, context=context): | ||
1599 | 222 | cc_ids.append(dest_cc_link.cc_id.id) | ||
1600 | 223 | dest_ids.append(dest_cc_link.dest_id.id) | ||
1601 | 224 | payroll_ids = payroll_obj.search(cr, uid, [('state', '=', 'draft'), | ||
1602 | 225 | '|', | ||
1603 | 226 | ('cost_center_id', 'in', cc_ids), | ||
1604 | 227 | ('destination_id', 'in', dest_ids)], order='NO_ORDER', context=context) | ||
1605 | 228 | return payroll_ids | ||
1606 | 229 | |||
1607 | 205 | def _has_third_party(self, cr, uid, ids, name, arg, context=None): | 230 | def _has_third_party(self, cr, uid, ids, name, arg, context=None): |
1608 | 206 | """ | 231 | """ |
1609 | 207 | Returns True if the Payroll entry is linked to either an Employee or a Supplier | 232 | Returns True if the Payroll entry is linked to either an Employee or a Supplier |
1610 | @@ -242,12 +267,14 @@ | |||
1611 | 242 | 'hr.payroll.msf': (lambda self, cr, uid, ids, c=None: ids, ['account_id', 'cost_center_id', 'funding_pool_id', 'destination_id'], 10), | 267 | 'hr.payroll.msf': (lambda self, cr, uid, ids, c=None: ids, ['account_id', 'cost_center_id', 'funding_pool_id', 'destination_id'], 10), |
1612 | 243 | 'account.account': (_get_trigger_state_account, ['user_type_code', 'destination_ids'], 20), | 268 | 'account.account': (_get_trigger_state_account, ['user_type_code', 'destination_ids'], 20), |
1613 | 244 | 'account.analytic.account': (_get_trigger_state_ana, ['date', 'date_start', 'allow_all_cc', | 269 | 'account.analytic.account': (_get_trigger_state_ana, ['date', 'date_start', 'allow_all_cc', |
1615 | 245 | 'dest_cc_ids', 'allow_all_cc_with_fp', | 270 | 'allow_all_cc_with_fp', |
1616 | 246 | 'cost_center_ids', 'select_accounts_only', | 271 | 'cost_center_ids', 'select_accounts_only', |
1617 | 247 | 'fp_account_ids', | 272 | 'fp_account_ids', |
1618 | 248 | 'tuple_destination_account_ids'], | 273 | 'tuple_destination_account_ids'], |
1619 | 249 | 20), | 274 | 20), |
1620 | 250 | 'account.destination.link': (_get_trigger_state_dest_link, ['account_id', 'destination_id'], 30), | 275 | 'account.destination.link': (_get_trigger_state_dest_link, ['account_id', 'destination_id'], 30), |
1621 | 276 | 'dest.cc.link': (_get_trigger_state_dest_cc_link, | ||
1622 | 277 | ['cc_id', 'dest_id', 'active_from', 'inactive_from'], 40), | ||
1623 | 251 | } | 278 | } |
1624 | 252 | ), | 279 | ), |
1625 | 253 | 'partner_type': fields.function(_get_third_parties, type='reference', method=True, string="Third Parties", readonly=True, | 280 | 'partner_type': fields.function(_get_third_parties, type='reference', method=True, string="Third Parties", readonly=True, |
1626 | 254 | 281 | ||
1627 | === modified file 'bin/addons/msf_profile/data/patches.xml' | |||
1628 | --- bin/addons/msf_profile/data/patches.xml 2021-02-25 15:48:01 +0000 | |||
1629 | +++ bin/addons/msf_profile/data/patches.xml 2021-05-07 16:01:07 +0000 | |||
1630 | @@ -647,9 +647,17 @@ | |||
1631 | 647 | <field name="method">us_6796_hide_prod_status_inconsistencies</field> | 647 | <field name="method">us_6796_hide_prod_status_inconsistencies</field> |
1632 | 648 | </record> | 648 | </record> |
1633 | 649 | 649 | ||
1634 | 650 | <<<<<<< TREE | ||
1635 | 650 | <record id="us_8166_hide_consolidated_sm_report" model="patch.scripts"> | 651 | <record id="us_8166_hide_consolidated_sm_report" model="patch.scripts"> |
1636 | 651 | <field name="method">us_8166_hide_consolidated_sm_report</field> | 652 | <field name="method">us_8166_hide_consolidated_sm_report</field> |
1637 | 652 | </record> | 653 | </record> |
1638 | 653 | 654 | ||
1639 | 655 | ======= | ||
1640 | 656 | <!-- UF21.0 --> | ||
1641 | 657 | <record id="us_7295_update_new_dest_cc_link" model="patch.scripts"> | ||
1642 | 658 | <field name="method">us_7295_update_new_dest_cc_link</field> | ||
1643 | 659 | </record> | ||
1644 | 660 | |||
1645 | 661 | >>>>>>> MERGE-SOURCE | ||
1646 | 654 | </data> | 662 | </data> |
1647 | 655 | </openerp> | 663 | </openerp> |
1648 | 656 | 664 | ||
1649 | === modified file 'bin/addons/msf_profile/i18n/fr_MF.po' | |||
1650 | --- bin/addons/msf_profile/i18n/fr_MF.po 2021-05-06 15:52:15 +0000 | |||
1651 | +++ bin/addons/msf_profile/i18n/fr_MF.po 2021-05-07 16:01:07 +0000 | |||
1652 | @@ -21113,6 +21113,7 @@ | |||
1653 | 21113 | #: report:kitting.order.report:0 | 21113 | #: report:kitting.order.report:0 |
1654 | 21114 | #: field:replenishment.inventory.review.line.exp,name:0 | 21114 | #: field:replenishment.inventory.review.line.exp,name:0 |
1655 | 21115 | #: field:replenishment.segment.line.amc.month_exp,name:0 | 21115 | #: field:replenishment.segment.line.amc.month_exp,name:0 |
1656 | 21116 | #: view:account.analytic.account:0 | ||
1657 | 21116 | #, python-format | 21117 | #, python-format |
1658 | 21117 | msgid "Name" | 21118 | msgid "Name" |
1659 | 21118 | msgstr "Nom" | 21119 | msgstr "Nom" |
1660 | @@ -34812,6 +34813,7 @@ | |||
1661 | 34812 | #: field:products.situation.report,p_code:0 | 34813 | #: field:products.situation.report,p_code:0 |
1662 | 34813 | #: report:addons/msf_tools/report/report_stock_pipe_per_product_instance_xls.mako:86 | 34814 | #: report:addons/msf_tools/report/report_stock_pipe_per_product_instance_xls.mako:86 |
1663 | 34814 | #: field:account.target.costcenter,cost_center_code:0 | 34815 | #: field:account.target.costcenter,cost_center_code:0 |
1664 | 34816 | #: view:account.analytic.account:0 | ||
1665 | 34815 | #, python-format | 34817 | #, python-format |
1666 | 34816 | msgid "Code" | 34818 | msgid "Code" |
1667 | 34817 | msgstr "Code" | 34819 | msgstr "Code" |
1668 | @@ -44531,9 +44533,10 @@ | |||
1669 | 44531 | msgid "No donation account found for this line: %s. (product: %s)" | 44533 | msgid "No donation account found for this line: %s. (product: %s)" |
1670 | 44532 | msgstr "No donation account found for this line: %s. (product: %s)" | 44534 | msgstr "No donation account found for this line: %s. (product: %s)" |
1671 | 44533 | 44535 | ||
1673 | 44534 | #. modules: account, base | 44536 | #. modules: account, base, analytic_override |
1674 | 44535 | #: view:account.addtmpl.wizard:0 | 44537 | #: view:account.addtmpl.wizard:0 |
1675 | 44536 | #: view:res.widget.wizard:0 | 44538 | #: view:res.widget.wizard:0 |
1676 | 44539 | #: view:multiple.cc.selection.wizard:0 | ||
1677 | 44537 | msgid "Add" | 44540 | msgid "Add" |
1678 | 44538 | msgstr "Ajouter" | 44541 | msgstr "Ajouter" |
1679 | 44539 | 44542 | ||
1680 | @@ -47155,7 +47158,7 @@ | |||
1681 | 47155 | #: code:addons/analytic_distribution/wizard/commitment_analytic_reallocation.py:140 | 47158 | #: code:addons/analytic_distribution/wizard/commitment_analytic_reallocation.py:140 |
1682 | 47156 | #, python-format | 47159 | #, python-format |
1683 | 47157 | msgid "Non compatible entries found: %s" | 47160 | msgid "Non compatible entries found: %s" |
1685 | 47158 | msgstr "Non compatible entries found: %s" | 47161 | msgstr "Ecritures non compatibles trouvées : %s" |
1686 | 47159 | 47162 | ||
1687 | 47160 | #. modules: delivery_mechanism, tender_flow, analytic_distribution_supply, product_nomenclature, return_claim, sync_client, res_currency_tables, supplier_catalogue, import_data, stock_batch_recall, stock, product, reason_types_moves, consumption_calculation, register_accounting, specific_rules, kit, base, account_period_closing_level, account_subscription, msf_cross_docking, purchase, account, msf_outgoing, resource, procurement_auto, msf_config_locations, sale, account_override, sourcing, sync_so, res_currency_functional, account_hq_entries | 47163 | #. modules: delivery_mechanism, tender_flow, analytic_distribution_supply, product_nomenclature, return_claim, sync_client, res_currency_tables, supplier_catalogue, import_data, stock_batch_recall, stock, product, reason_types_moves, consumption_calculation, register_accounting, specific_rules, kit, base, account_period_closing_level, account_subscription, msf_cross_docking, purchase, account, msf_outgoing, resource, procurement_auto, msf_config_locations, sale, account_override, sourcing, sync_so, res_currency_functional, account_hq_entries |
1688 | 47161 | #: code:addons/account/account.py:445 | 47164 | #: code:addons/account/account.py:445 |
1689 | @@ -66095,6 +66098,9 @@ | |||
1690 | 66095 | #: report:addons/account/report/free_allocation_report.mako:176 | 66098 | #: report:addons/account/report/free_allocation_report.mako:176 |
1691 | 66096 | #: field:free.allocation.wizard,cost_center_ids:0 | 66099 | #: field:free.allocation.wizard,cost_center_ids:0 |
1692 | 66097 | #: field:account.analytic.account,dest_cc_ids:0 | 66100 | #: field:account.analytic.account,dest_cc_ids:0 |
1693 | 66101 | #: field:account.analytic.account,dest_cc_link_ids:0 | ||
1694 | 66102 | #: view:multiple.cc.selection.wizard:0 | ||
1695 | 66103 | #: field:multiple.cc.selection.wizard,cc_ids:0 | ||
1696 | 66098 | msgid "Cost Centers" | 66104 | msgid "Cost Centers" |
1697 | 66099 | msgstr "Centres de Coût" | 66105 | msgstr "Centres de Coût" |
1698 | 66100 | 66106 | ||
1699 | @@ -80576,6 +80582,7 @@ | |||
1700 | 80576 | #: code:addons/register_accounting/wizard/wizard_register_import.py:570 | 80582 | #: code:addons/register_accounting/wizard/wizard_register_import.py:570 |
1701 | 80577 | #: report:addons/account/report/free_allocation_report.mako:205 | 80583 | #: report:addons/account/report/free_allocation_report.mako:205 |
1702 | 80578 | #: code:addons/msf_doc_import/wizard/wizard_po_simulation_screen.py:606 | 80584 | #: code:addons/msf_doc_import/wizard/wizard_po_simulation_screen.py:606 |
1703 | 80585 | #: field:dest.cc.link,cc_id:0 | ||
1704 | 80579 | #, python-format | 80586 | #, python-format |
1705 | 80580 | msgid "Cost Center" | 80587 | msgid "Cost Center" |
1706 | 80581 | msgstr "Centre de Coût" | 80588 | msgstr "Centre de Coût" |
1707 | @@ -94527,6 +94534,8 @@ | |||
1708 | 94527 | #: code:addons/stock_override/report/report_stock_move.py:759 | 94534 | #: code:addons/stock_override/report/report_stock_move.py:759 |
1709 | 94528 | #: report:addons/account/report/invoice_excel_export.mako:75 | 94535 | #: report:addons/account/report/invoice_excel_export.mako:75 |
1710 | 94529 | #: field:financing.contract.account.quadruplet,account_destination_id:0 | 94536 | #: field:financing.contract.account.quadruplet,account_destination_id:0 |
1711 | 94537 | #: field:dest.cc.link,dest_id:0 | ||
1712 | 94538 | #: field:multiple.cc.selection.wizard,dest_id:0 | ||
1713 | 94530 | #, python-format | 94539 | #, python-format |
1714 | 94531 | msgid "Destination" | 94540 | msgid "Destination" |
1715 | 94532 | msgstr "Destination" | 94541 | msgstr "Destination" |
1716 | @@ -95899,7 +95908,7 @@ | |||
1717 | 95899 | msgid "Search Uninvoiced Lines" | 95908 | msgid "Search Uninvoiced Lines" |
1718 | 95900 | msgstr "Rechercher Lignes non-facturées" | 95909 | msgstr "Rechercher Lignes non-facturées" |
1719 | 95901 | 95910 | ||
1721 | 95902 | #. modules: res_currency_functional, financing_contract, msf_tools, account_hq_entries, account_override, product_attributes, base_report_designer, register_accounting, procurement_cycle, msf_accrual, finance, sync_client, purchase_followup, account_mcdb, res_currency_tables, supplier_catalogue, procurement_request, purchase_compare_rfq, board, stock_override, msf_doc_import, analytic_distribution, threshold_value, msf_homere_interface, msf_instance, account_reconciliation, consumption_calculation, purchase_override, specific_rules, kit, base, account_period_closing_level, msf_currency_revaluation, msf_supply_doc_export, product_list, procurement_report, msf_budget, account_corrections, account, msf_outgoing, stock_move_tracking, purchase_allocation_report, procurement_auto, documents_done, sale, msf_config_locations, sales_followup, vertical_integration, procurement, sourcing, purchase, msf_audittrail, tender_flow, stock, msf_profile | 95911 | #. modules: res_currency_functional, financing_contract, msf_tools, account_hq_entries, account_override, product_attributes, base_report_designer, register_accounting, procurement_cycle, msf_accrual, finance, sync_client, purchase_followup, account_mcdb, res_currency_tables, supplier_catalogue, procurement_request, purchase_compare_rfq, board, stock_override, msf_doc_import, analytic_distribution, threshold_value, msf_homere_interface, msf_instance, account_reconciliation, consumption_calculation, purchase_override, specific_rules, kit, base, account_period_closing_level, msf_currency_revaluation, msf_supply_doc_export, product_list, procurement_report, msf_budget, account_corrections, account, msf_outgoing, stock_move_tracking, purchase_allocation_report, procurement_auto, documents_done, sale, msf_config_locations, sales_followup, vertical_integration, procurement, sourcing, purchase, msf_audittrail, tender_flow, stock, msf_profile, analytic_override |
1722 | 95903 | #: view:account.addtmpl.wizard:0 | 95912 | #: view:account.addtmpl.wizard:0 |
1723 | 95904 | #: view:account.aged.trial.balance:0 | 95913 | #: view:account.aged.trial.balance:0 |
1724 | 95905 | #: view:account.analytic.Journal.report:0 | 95914 | #: view:account.analytic.Journal.report:0 |
1725 | @@ -96133,6 +96142,7 @@ | |||
1726 | 96133 | #: view:product.stock_out:0 | 96142 | #: view:product.stock_out:0 |
1727 | 96134 | #: view:replenishment.parent.segment:0 | 96143 | #: view:replenishment.parent.segment:0 |
1728 | 96135 | #: view:view.expired.expiring.stock:0 | 96144 | #: view:view.expired.expiring.stock:0 |
1729 | 96145 | #: view:multiple.cc.selection.wizard:0 | ||
1730 | 96136 | #, python-format | 96146 | #, python-format |
1731 | 96137 | msgid "Cancel" | 96147 | msgid "Cancel" |
1732 | 96138 | msgstr "Annuler" | 96148 | msgstr "Annuler" |
1733 | @@ -99911,6 +99921,12 @@ | |||
1734 | 99911 | msgstr "%s: FP inactif (%s)" | 99921 | msgstr "%s: FP inactif (%s)" |
1735 | 99912 | 99922 | ||
1736 | 99913 | #. module: account_hq_entries | 99923 | #. module: account_hq_entries |
1737 | 99924 | #: code:addons/account_hq_entries/hq_entries.py:94 | ||
1738 | 99925 | #, python-format | ||
1739 | 99926 | msgid "%s: inactive combination (%s - %s)" | ||
1740 | 99927 | msgstr "%s: combinaison inactive (%s - %s)" | ||
1741 | 99928 | |||
1742 | 99929 | #. module: account_hq_entries | ||
1743 | 99914 | #: field:hq.entries,is_account_partner_compatible:0 | 99930 | #: field:hq.entries,is_account_partner_compatible:0 |
1744 | 99915 | msgid "Account and partner compatible ?" | 99931 | msgid "Account and partner compatible ?" |
1745 | 99916 | msgstr "Compte et partenaire compatibles ?" | 99932 | msgstr "Compte et partenaire compatibles ?" |
1746 | @@ -100222,11 +100238,23 @@ | |||
1747 | 100222 | msgstr "Date du CC" | 100238 | msgstr "Date du CC" |
1748 | 100223 | 100239 | ||
1749 | 100224 | #. module: analytic_distribution | 100240 | #. module: analytic_distribution |
1750 | 100241 | #: code:addons/analytic_distribution/analytic_line.py:563 | ||
1751 | 100242 | #, python-format | ||
1752 | 100243 | msgid "DEST/CC combination date" | ||
1753 | 100244 | msgstr "Date de la combinaison DEST/CC" | ||
1754 | 100245 | |||
1755 | 100246 | #. module: analytic_distribution | ||
1756 | 100225 | #: code:addons/analytic_distribution/analytic_line.py:548 | 100247 | #: code:addons/analytic_distribution/analytic_line.py:548 |
1757 | 100226 | #, python-format | 100248 | #, python-format |
1758 | 100227 | msgid "FP date" | 100249 | msgid "FP date" |
1759 | 100228 | msgstr "Date du FP" | 100250 | msgstr "Date du FP" |
1760 | 100229 | 100251 | ||
1761 | 100252 | #. module: analytic_distribution | ||
1762 | 100253 | #: code:addons/analytic_distribution/analytic_distribution.py:237 | ||
1763 | 100254 | #, python-format | ||
1764 | 100255 | msgid "Inactive DEST/CC combination" | ||
1765 | 100256 | msgstr "Combinaison DEST/CC inactive" | ||
1766 | 100257 | |||
1767 | 100230 | #. module: msf_printed_documents | 100258 | #. module: msf_printed_documents |
1768 | 100231 | #: code:addons/msf_printed_documents/report/report_reception.py:80 | 100259 | #: code:addons/msf_printed_documents/report/report_reception.py:80 |
1769 | 100232 | #, python-format | 100260 | #, python-format |
1770 | @@ -112023,3 +112051,124 @@ | |||
1771 | 112023 | #, python-format | 112051 | #, python-format |
1772 | 112024 | msgid "You must have at least one line to create the Internal Move" | 112052 | msgid "You must have at least one line to create the Internal Move" |
1773 | 112025 | msgstr "Vous devez avoir au moins une ligne pour pouvoir créer le Mouvement Interne" | 112053 | msgstr "Vous devez avoir au moins une ligne pour pouvoir créer le Mouvement Interne" |
1774 | 112054 | |||
1775 | 112055 | #. module: analytic_distribution | ||
1776 | 112056 | #: view:account.analytic.account:0 | ||
1777 | 112057 | msgid "Remove all" | ||
1778 | 112058 | msgstr "Supprimer tout" | ||
1779 | 112059 | |||
1780 | 112060 | #. module: analytic_distribution | ||
1781 | 112061 | #: view:account.analytic.account:0 | ||
1782 | 112062 | msgid "Do you really want to remove all the Cost Centers selected?" | ||
1783 | 112063 | msgstr "Voulez-vous vraiment supprimer tous les Centres de Coût sélectionnés ?" | ||
1784 | 112064 | |||
1785 | 112065 | #. modules: analytic_override, analytic_distribution | ||
1786 | 112066 | #: view:account.analytic.account:0 | ||
1787 | 112067 | #: view:multiple.cc.selection.wizard:0 | ||
1788 | 112068 | msgid "Add several Cost Centers" | ||
1789 | 112069 | msgstr "Ajouter plusieurs Centres de Coût" | ||
1790 | 112070 | |||
1791 | 112071 | #. modules: msf_doc_import, analytic_override | ||
1792 | 112072 | #: field:account.analytic.account,dest_cc_link_active_from:0 | ||
1793 | 112073 | #: field:dest.cc.link,active_from:0 | ||
1794 | 112074 | #: code:addons/msf_doc_import/msf_import_export.py:639 | ||
1795 | 112075 | #, python-format | ||
1796 | 112076 | msgid "Activation Combination Dest / CC from" | ||
1797 | 112077 | msgstr "Activation Combinaison Dest / CC à partir du" | ||
1798 | 112078 | |||
1799 | 112079 | #. modules: msf_doc_import, analytic_override | ||
1800 | 112080 | #: field:account.analytic.account,dest_cc_link_inactive_from:0 | ||
1801 | 112081 | #: field:dest.cc.link,inactive_from:0 | ||
1802 | 112082 | #: code:addons/msf_doc_import/msf_import_export.py:640 | ||
1803 | 112083 | #, python-format | ||
1804 | 112084 | msgid "Inactivation Combination Dest / CC from" | ||
1805 | 112085 | msgstr "Inactivation Combinaison Dest / CC à partir du" | ||
1806 | 112086 | |||
1807 | 112087 | #. module: analytic_override | ||
1808 | 112088 | #: help:account.analytic.account,dest_cc_link_active_from:0 | ||
1809 | 112089 | #: help:account.analytic.account,dest_cc_link_inactive_from:0 | ||
1810 | 112090 | msgid "Technical field used for Import Tools only" | ||
1811 | 112091 | msgstr "Champ technique utilisé pour les Outils d'Import uniquement" | ||
1812 | 112092 | |||
1813 | 112093 | #. module: analytic_override | ||
1814 | 112094 | #: field:account.analytic.account,selected_in_dest:0 | ||
1815 | 112095 | msgid "Selected in Destination" | ||
1816 | 112096 | msgstr "Sélectionné dans la Destination" | ||
1817 | 112097 | |||
1818 | 112098 | #. module: analytic_override | ||
1819 | 112099 | #: model:ir.model,name:analytic_override.model_dest_cc_link | ||
1820 | 112100 | msgid "Destination / Cost Center Combination" | ||
1821 | 112101 | msgstr "Combinaison Destination / Centre de Coût" | ||
1822 | 112102 | |||
1823 | 112103 | #. module: analytic_override | ||
1824 | 112104 | #: field:dest.cc.link,cc_code:0 | ||
1825 | 112105 | msgid "Cost Center Code" | ||
1826 | 112106 | msgstr "Code du Centre de Coût" | ||
1827 | 112107 | |||
1828 | 112108 | #. module: analytic_override | ||
1829 | 112109 | #: field:dest.cc.link,cc_name:0 | ||
1830 | 112110 | msgid "Cost Center Name" | ||
1831 | 112111 | msgstr "Nom du Centre de Coût" | ||
1832 | 112112 | |||
1833 | 112113 | #. module: analytic_override | ||
1834 | 112114 | #: sql_constraint:dest.cc.link:0 | ||
1835 | 112115 | msgid "Each Cost Center can only be added once to the same Destination." | ||
1836 | 112116 | msgstr "Chaque Centre de Coût ne peut être ajouté qu'une seule fois à une même Destination." | ||
1837 | 112117 | |||
1838 | 112118 | #. module: analytic_override | ||
1839 | 112119 | #: sql_constraint:dest.cc.link:0 | ||
1840 | 112120 | msgid "The Activation date of the \"Combination Dest / CC\" must be before the Inactivation date." | ||
1841 | 112121 | msgstr "La date d'Activation de la \"Combinaison Dest / CC\" doit précéder la date d'Inactivation." | ||
1842 | 112122 | |||
1843 | 112123 | #. module: msf_doc_import | ||
1844 | 112124 | #: code:addons/msf_doc_import/msf_import_export.py:663 | ||
1845 | 112125 | #, python-format | ||
1846 | 112126 | msgid "The number of dates in the column \"%s\" exceeds the number of Cost Centers indicated." | ||
1847 | 112127 | msgstr "Le nombre de dates dans la colonne \"%s\" dépasse le nombre de Centres de Coût indiqués." | ||
1848 | 112128 | |||
1849 | 112129 | #. module: msf_doc_import | ||
1850 | 112130 | #: code:addons/msf_doc_import/msf_import_export.py:679 | ||
1851 | 112131 | #, python-format | ||
1852 | 112132 | msgid "The activation date related to the Cost Center %s must be before the inactivation date." | ||
1853 | 112133 | msgstr "La date d'activation associée au Centre de Coût %s doit précéder la date d'inactivation." | ||
1854 | 112134 | |||
1855 | 112135 | #. module: msf_doc_import | ||
1856 | 112136 | #: code:addons/msf_doc_import/msf_import_export.py:657 | ||
1857 | 112137 | #, python-format | ||
1858 | 112138 | msgid "The dates in the column \"%s\" should use the format YYYY-MM-DD." | ||
1859 | 112139 | msgstr "Les dates dans la colonne \"%s\" doivent utiliser le format AAAA-MM-JJ." | ||
1860 | 112140 | |||
1861 | 112141 | #. module: analytic_override | ||
1862 | 112142 | #: view:multiple.cc.selection.wizard:0 | ||
1863 | 112143 | msgid "This wizard enables you to select several Cost Centers at once to be added to the Destination. The activation and inactivation dates of the related Dest / CC combinations will remain empty." | ||
1864 | 112144 | msgstr "Cet assistant vous permet de sélectionner en une fois plusieurs Centres de Coût à ajouter à la Destination. Les dates d'activation et d'inactivation des Combinaisons Dest / CC associées resteront vides." | ||
1865 | 112145 | |||
1866 | 112146 | #. module: analytic_override | ||
1867 | 112147 | #: field:dest.cc.link,current_id:0 | ||
1868 | 112148 | msgid "DB Id (used by the UI)" | ||
1869 | 112149 | msgstr "Id BD (utilisé par l'UI)" | ||
1870 | 112150 | |||
1871 | 112151 | #. module: analytic_override | ||
1872 | 112152 | #: code:addons/analytic_override/analytic_line.py:192 | ||
1873 | 112153 | #, python-format | ||
1874 | 112154 | msgid "The combination \"%s - %s\" is not active." | ||
1875 | 112155 | msgstr "La combinaison \"%s - %s\" n'est pas active." | ||
1876 | 112156 | |||
1877 | 112157 | #. module: analytic_distribution | ||
1878 | 112158 | #: code:addons/analytic_distribution/wizard/analytic_distribution_wizard.py:1024 | ||
1879 | 112159 | #: code:addons/analytic_distribution/account_commitment.py:204 | ||
1880 | 112160 | #, python-format | ||
1881 | 112161 | msgid "The combination \"%s - %s\" is not active at this date: %s" | ||
1882 | 112162 | msgstr "La combinaison \"%s - %s\" n'est pas active à cette date : %s" | ||
1883 | 112163 | |||
1884 | 112164 | #. module: analytic_distribution | ||
1885 | 112165 | #: code:addons/analytic_distribution/analytic_distribution.py:264 | ||
1886 | 112166 | #, python-format | ||
1887 | 112167 | msgid "%sThe combination \"%s - %s\" is not active at this date: %s" | ||
1888 | 112168 | msgstr "%sLa combinaison \"%s - %s\" n'est pas active à cette date : %s" | ||
1889 | 112169 | |||
1890 | 112170 | #. module: analytic_override | ||
1891 | 112171 | #: code:addons/analytic_override/dest_cc_link.py:72 | ||
1892 | 112172 | #, python-format | ||
1893 | 112173 | msgid "At least one Analytic Journal Item using the combination \"%s - %s\" has a Posting Date outside the activation dates selected." | ||
1894 | 112174 | msgstr "Au moins une Ligne d'Ecriture Analytique utilisant la combinaison \"%s - %s\" a une Date de Comptabilisation en dehors des dates d'activation sélectionnées." | ||
1895 | 112026 | 112175 | ||
1896 | === modified file 'bin/addons/msf_profile/msf_profile.py' | |||
1897 | --- bin/addons/msf_profile/msf_profile.py 2021-05-05 07:42:20 +0000 | |||
1898 | +++ bin/addons/msf_profile/msf_profile.py 2021-05-07 16:01:07 +0000 | |||
1899 | @@ -52,6 +52,7 @@ | |||
1900 | 52 | 'model': lambda *a: 'patch.scripts', | 52 | 'model': lambda *a: 'patch.scripts', |
1901 | 53 | } | 53 | } |
1902 | 54 | 54 | ||
1903 | 55 | <<<<<<< TREE | ||
1904 | 55 | # UF21.0 | 56 | # UF21.0 |
1905 | 56 | def us_8166_hide_consolidated_sm_report(self, cr, uid, *a, **b): | 57 | def us_8166_hide_consolidated_sm_report(self, cr, uid, *a, **b): |
1906 | 57 | instance = self.pool.get('res.users').browse(cr, uid, uid, fields_to_fetch=['company_id']).company_id.instance_id | 58 | instance = self.pool.get('res.users').browse(cr, uid, uid, fields_to_fetch=['company_id']).company_id.instance_id |
1907 | @@ -61,6 +62,22 @@ | |||
1908 | 61 | self.pool.get('ir.ui.menu').write(cr, uid, consolidated_sm_report_menu_id, {'active': instance.level == 'coordo'}, context={}) | 62 | self.pool.get('ir.ui.menu').write(cr, uid, consolidated_sm_report_menu_id, {'active': instance.level == 'coordo'}, context={}) |
1909 | 62 | return True | 63 | return True |
1910 | 63 | 64 | ||
1911 | 65 | ======= | ||
1912 | 66 | # UF21.0 | ||
1913 | 67 | def us_7295_update_new_dest_cc_link(self, cr, uid, *a, **b): | ||
1914 | 68 | """ | ||
1915 | 69 | CC Tab of the Destinations: replaces the old field "dest_cc_ids" by the new field "dest_cc_link_ids" | ||
1916 | 70 | => recreates the links without activation/inactivation dates | ||
1917 | 71 | """ | ||
1918 | 72 | cr.execute(""" | ||
1919 | 73 | INSERT INTO dest_cc_link(dest_id, cc_id) | ||
1920 | 74 | SELECT destination_id, cost_center_id FROM destination_cost_center_rel | ||
1921 | 75 | """) | ||
1922 | 76 | cr.execute("DELETE FROM destination_cost_center_rel") | ||
1923 | 77 | self._logger.warn('Destinations: %s Dest CC Links generated.', cr.rowcount) | ||
1924 | 78 | return True | ||
1925 | 79 | |||
1926 | 80 | >>>>>>> MERGE-SOURCE | ||
1927 | 64 | # UF20.0 | 81 | # UF20.0 |
1928 | 65 | def us_7866_fill_in_target_cc_code(self, cr, uid, *a, **b): | 82 | def us_7866_fill_in_target_cc_code(self, cr, uid, *a, **b): |
1929 | 66 | """ | 83 | """ |
1930 | 67 | 84 | ||
1931 | === modified file 'bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv' | |||
1932 | --- bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv 2021-04-12 09:46:40 +0000 | |||
1933 | +++ bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv 2021-05-07 16:01:07 +0000 | |||
1934 | @@ -34,6 +34,7 @@ | |||
1935 | 34 | msf_sync_data_server.fys_state,TRUE,TRUE,TRUE,TRUE,bidirectional,Up,[],"['state', 'fy_id/id', 'instance_id/id']",HQ + MISSION,account.fiscalyear.state,,Fiscal years states,Valid,,130 | 34 | msf_sync_data_server.fys_state,TRUE,TRUE,TRUE,TRUE,bidirectional,Up,[],"['state', 'fy_id/id', 'instance_id/id']",HQ + MISSION,account.fiscalyear.state,,Fiscal years states,Valid,,130 |
1936 | 35 | msf_sync_data_server.cost_center_cc_intermission,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('category' , '=' , 'OC'), ('code', '=', 'cc-intermission')]","['category', 'code', 'date', 'date_start', 'description', 'name', 'type']",OC,account.analytic.account,,CC-Intermission,Valid,,140 | 35 | msf_sync_data_server.cost_center_cc_intermission,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('category' , '=' , 'OC'), ('code', '=', 'cc-intermission')]","['category', 'code', 'date', 'date_start', 'description', 'name', 'type']",OC,account.analytic.account,,CC-Intermission,Valid,,140 |
1937 | 36 | msf_sync_data_server.destination_cc,TRUE,TRUE,TRUE,TRUE,bidirectional,Down,"[('category' , '=' , 'DEST')]","['dest_cc_ids/id', 'allow_all_cc']",OC,account.analytic.account,,Destinations: Cost Center fields,Valid,,145 | 36 | msf_sync_data_server.destination_cc,TRUE,TRUE,TRUE,TRUE,bidirectional,Down,"[('category' , '=' , 'DEST')]","['dest_cc_ids/id', 'allow_all_cc']",OC,account.analytic.account,,Destinations: Cost Center fields,Valid,,145 |
1938 | 37 | msf_sync_data_server.dest_cc_link,TRUE,TRUE,TRUE,TRUE,bidirectional,Bidirectional-Private,"[]","['dest_id/id', 'cc_id/id', 'active_from', 'inactive_from']",OC,dest.cc.link,cc_id,Destination / Cost Center Combinations,Valid,,146 | ||
1939 | 37 | msf_sync_data_server.gl_accounts_reconciliation,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,[],"['reconciliation_debit_account_id/id', 'reconciliation_credit_account_id/id']",OC,account.account,,GL Accounts Reconciliation Accounts,Valid,,150 | 38 | msf_sync_data_server.gl_accounts_reconciliation,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,[],"['reconciliation_debit_account_id/id', 'reconciliation_credit_account_id/id']",OC,account.account,,GL Accounts Reconciliation Accounts,Valid,,150 |
1940 | 38 | msf_sync_data_server.analytic_distribution,FALSE,TRUE,FALSE,FALSE,bidirectional,Bidirectional,[],['name'],HQ + MISSION,analytic.distribution,,Analytic Distribution,Valid,,200 | 39 | msf_sync_data_server.analytic_distribution,FALSE,TRUE,FALSE,FALSE,bidirectional,Bidirectional,[],['name'],HQ + MISSION,analytic.distribution,,Analytic Distribution,Valid,,200 |
1941 | 39 | msf_sync_data_server.cost_center_distribution_line,TRUE,TRUE,TRUE,FALSE,bidirectional,Bidirectional,"[('partner_type','=','internal')]","['amount', 'analytic_id/id', 'currency_id/id', 'date', 'destination_id/id', 'distribution_id/id', 'name', 'percentage', 'partner_type', 'source_date']",HQ + MISSION,cost.center.distribution.line,analytic_id,Cost Center Distribution Line - Internal partner,Valid,,201 | 40 | msf_sync_data_server.cost_center_distribution_line,TRUE,TRUE,TRUE,FALSE,bidirectional,Bidirectional,"[('partner_type','=','internal')]","['amount', 'analytic_id/id', 'currency_id/id', 'date', 'destination_id/id', 'distribution_id/id', 'name', 'percentage', 'partner_type', 'source_date']",HQ + MISSION,cost.center.distribution.line,analytic_id,Cost Center Distribution Line - Internal partner,Valid,,201 |
1942 | 40 | 41 | ||
1943 | === modified file 'bin/addons/sync_client/update.py' | |||
1944 | --- bin/addons/sync_client/update.py 2021-01-18 14:22:04 +0000 | |||
1945 | +++ bin/addons/sync_client/update.py 2021-05-07 16:01:07 +0000 | |||
1946 | @@ -58,6 +58,7 @@ | |||
1947 | 58 | 'account.mcdb', | 58 | 'account.mcdb', |
1948 | 59 | 'wizard.template', | 59 | 'wizard.template', |
1949 | 60 | 'account.analytic.account', | 60 | 'account.analytic.account', |
1950 | 61 | 'dest.cc.link', | ||
1951 | 61 | ] | 62 | ] |
1952 | 62 | 63 | ||
1953 | 63 | 64 | ||
1954 | 64 | 65 | ||
1955 | === modified file 'bin/addons/sync_common/common.py' | |||
1956 | --- bin/addons/sync_common/common.py 2020-10-20 07:15:50 +0000 | |||
1957 | +++ bin/addons/sync_common/common.py 2021-05-07 16:01:07 +0000 | |||
1958 | @@ -168,6 +168,7 @@ | |||
1959 | 168 | 'cash.request.liquidity.total', | 168 | 'cash.request.liquidity.total', |
1960 | 169 | 'hr.payment.method', | 169 | 'hr.payment.method', |
1961 | 170 | 'wizard.template', | 170 | 'wizard.template', |
1962 | 171 | 'dest.cc.link', | ||
1963 | 171 | ] | 172 | ] |
1964 | 172 | 173 | ||
1965 | 173 | OC_LIST = ['OCA', 'OCB', 'OCBA', 'OCG', 'OCP'] | 174 | OC_LIST = ['OCA', 'OCB', 'OCBA', 'OCG', 'OCP'] |
1966 | 174 | 175 | ||
1967 | === modified file 'bin/addons/sync_so/specific_xml_id.py' | |||
1968 | --- bin/addons/sync_so/specific_xml_id.py 2020-11-09 10:40:25 +0000 | |||
1969 | +++ bin/addons/sync_so/specific_xml_id.py 2021-05-07 16:01:07 +0000 | |||
1970 | @@ -307,6 +307,30 @@ | |||
1971 | 307 | 307 | ||
1972 | 308 | account_analytic_account() | 308 | account_analytic_account() |
1973 | 309 | 309 | ||
1974 | 310 | class dest_cc_link(osv.osv): | ||
1975 | 311 | _inherit = 'dest.cc.link' | ||
1976 | 312 | |||
1977 | 313 | def get_destination_name(self, cr, uid, ids, dest_field, context=None): | ||
1978 | 314 | ''' | ||
1979 | 315 | same destination as CC | ||
1980 | 316 | ''' | ||
1981 | 317 | if not ids: | ||
1982 | 318 | return [] | ||
1983 | 319 | |||
1984 | 320 | if isinstance(ids, (long, int)): | ||
1985 | 321 | ids = [ids] | ||
1986 | 322 | res = dict.fromkeys(ids, False) | ||
1987 | 323 | mapping = {} | ||
1988 | 324 | uniq_cc_ids = {} | ||
1989 | 325 | for dest_cc_link in self.browse(cr, uid, ids, fields_to_fetch=['cc_id'], context=context): | ||
1990 | 326 | mapping[dest_cc_link.id] = dest_cc_link.cc_id.id | ||
1991 | 327 | uniq_cc_ids[dest_cc_link.cc_id.id] = True | ||
1992 | 328 | cc_destination = self.pool.get('account.analytic.account').get_destination_name(cr, uid, uniq_cc_ids.keys(), 'category', context) | ||
1993 | 329 | for dest_cc_link_id in mapping: | ||
1994 | 330 | res[dest_cc_link_id] = cc_destination.get(mapping[dest_cc_link_id], []) | ||
1995 | 331 | return res | ||
1996 | 332 | |||
1997 | 333 | dest_cc_link() | ||
1998 | 310 | 334 | ||
1999 | 311 | #US-113: Sync only to the mission with attached prop instance | 335 | #US-113: Sync only to the mission with attached prop instance |
2000 | 312 | class financing_contract_contract(osv.osv): | 336 | class financing_contract_contract(osv.osv): |
2001 | 313 | 337 | ||
2002 | === modified file 'bin/osv/orm.py' | |||
2003 | --- bin/osv/orm.py 2021-02-02 10:20:51 +0000 | |||
2004 | +++ bin/osv/orm.py 2021-05-07 16:01:07 +0000 | |||
2005 | @@ -733,12 +733,21 @@ | |||
2006 | 733 | 733 | ||
2007 | 734 | if no_data: | 734 | if no_data: |
2008 | 735 | dt = '' | 735 | dt = '' |
2009 | 736 | rel_table_name = r[0]._table_name | ||
2010 | 737 | name_relation = self.pool.get(rel_table_name)._rec_name | ||
2011 | 738 | if isinstance(r[0][name_relation], browse_record): | ||
2012 | 739 | rel = True | ||
2013 | 740 | rel_table_name = r[0][name_relation]._table_name | ||
2014 | 741 | all_rr = [rr[name_relation].id for rr in r] | ||
2015 | 742 | else: | ||
2016 | 743 | rel = False | ||
2017 | 744 | all_rr = [rr.id for rr in r] | ||
2018 | 745 | all_name_get = dict(self.pool.get(rel_table_name).name_get(cr, uid, all_rr, context=context)) | ||
2019 | 736 | for rr in r: | 746 | for rr in r: |
2025 | 737 | name_relation = self.pool.get(rr._table_name)._rec_name | 747 | if not rel: |
2026 | 738 | if isinstance(rr[name_relation], browse_record): | 748 | rr_name = all_name_get.get(rr.id, '') |
2027 | 739 | rr = rr[name_relation] | 749 | else: |
2028 | 740 | rr_name = self.pool.get(rr._table_name).name_get(cr, uid, [rr.id], context=context) | 750 | rr_name = all_name_get.get(rr[name_relation].id, '') |
2024 | 741 | rr_name = rr_name and rr_name[0] and rr_name[0][1] or '' | ||
2029 | 742 | dt += tools.ustr(rr_name or '') + ',' | 751 | dt += tools.ustr(rr_name or '') + ',' |
2030 | 743 | data[fpos] = dt[:-1] | 752 | data[fpos] = dt[:-1] |
2031 | 744 | break | 753 | break |