Merge lp:~julie-w/unifield-server/US-5608 into lp:unifield-server
- US-5608
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 5548 |
Proposed branch: | lp:~julie-w/unifield-server/US-5608 |
Merge into: | lp:unifield-server |
Diff against target: |
339 lines (+127/-18) 9 files modified
bin/addons/account/account.py (+28/-4) bin/addons/account/account_invoice_view.xml (+3/-1) bin/addons/account/account_view.xml (+1/-0) bin/addons/account/invoice.py (+46/-8) bin/addons/account/wizard/account_invoice_refund.py (+5/-4) bin/addons/msf_partner/partner.py (+21/-0) bin/addons/msf_profile/i18n/fr_MF.po (+20/-0) bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv (+1/-1) bin/addons/sync_client/update.py (+2/-0) |
To merge this branch: | bzr merge lp:~julie-w/unifield-server/US-5608 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email: mp+373139@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/account.py' |
2 | --- bin/addons/account/account.py 2019-07-30 09:13:43 +0000 |
3 | +++ bin/addons/account/account.py 2019-09-24 13:32:21 +0000 |
4 | @@ -1909,6 +1909,9 @@ |
5 | 'parent_id':fields.many2one('account.tax', 'Parent Tax Account', select=True), |
6 | 'child_ids':fields.one2many('account.tax', 'parent_id', 'Child Tax Accounts'), |
7 | 'child_depend':fields.boolean('Tax on Children', help="Set if the tax computation is based on the computation of child taxes rather than on the total amount."), |
8 | + 'partner_id': fields.many2one('res.partner', 'Partner', |
9 | + domain=[('partner_type', '=', 'external'), ('active', '=', True)], |
10 | + ondelete='restrict'), |
11 | 'python_compute':fields.text('Python Code'), |
12 | 'python_compute_inv':fields.text('Python Code (reverse)'), |
13 | 'python_applicable':fields.text('Python Code'), |
14 | @@ -1963,11 +1966,31 @@ |
15 | ids = self.search(cr, user, args, limit=limit, context=context or {}) |
16 | return self.name_get(cr, user, ids, context=context) |
17 | |
18 | + def _check_tax_partner(self, cr, uid, vals, context=None): |
19 | + """ |
20 | + Raises an error in case the partner selected for the tax isn't allowed |
21 | + """ |
22 | + if context is None: |
23 | + context = {} |
24 | + partner_obj = self.pool.get('res.partner') |
25 | + if vals.get('partner_id'): |
26 | + partner = partner_obj.browse(cr, uid, vals['partner_id'], fields_to_fetch=['active', 'partner_type', 'name'], context=context) |
27 | + if not partner.active or partner.partner_type != 'external': |
28 | + raise osv.except_osv(_('Error'), |
29 | + _("You can't link the tax to the Partner %s: only active external partners are allowed.") % partner.name) |
30 | + |
31 | + def create(self, cr, uid, vals, context=None): |
32 | + if context is None: |
33 | + context = {} |
34 | + self._check_tax_partner(cr, uid, vals, context=context) |
35 | + return super(account_tax, self).create(cr, uid, vals, context=context) |
36 | + |
37 | def write(self, cr, uid, ids, vals, context=None): |
38 | if not ids: |
39 | return True |
40 | if vals.get('type', False) and vals['type'] in ('none', 'code'): |
41 | vals.update({'amount': 0.0}) |
42 | + self._check_tax_partner(cr, uid, vals, context=context) |
43 | return super(account_tax, self).write(cr, uid, ids, vals, context=context) |
44 | |
45 | def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): |
46 | @@ -2041,9 +2064,9 @@ |
47 | obj_partener_address = self.pool.get('res.partner.address') |
48 | for tax in taxes: |
49 | # we compute the amount for the current tax object and append it to the result |
50 | - |
51 | + description = "%s%s%s" % (tax.name, partner and ' - ' or '', partner and partner.name or '') # tax name and INVOICE partner name |
52 | data = {'id':tax.id, |
53 | - 'name':tax.description and tax.description + " - " + tax.name or tax.name, |
54 | + 'name': description, |
55 | 'account_collected_id':tax.account_collected_id.id, |
56 | 'account_paid_id':tax.account_paid_id.id, |
57 | 'base_code_id': tax.base_code_id.id, |
58 | @@ -2200,10 +2223,11 @@ |
59 | todo = 0 |
60 | else: |
61 | todo = 1 |
62 | + description = "%s%s%s" % (tax.name, partner and ' - ' or '', partner and partner.name or '') # tax name and INVOICE partner name |
63 | res.append({ |
64 | 'id': tax.id, |
65 | 'todo': todo, |
66 | - 'name': tax.name, |
67 | + 'name': description, |
68 | 'amount': amount, |
69 | 'account_collected_id': tax.account_collected_id.id, |
70 | 'account_paid_id': tax.account_paid_id.id, |
71 | @@ -2245,7 +2269,7 @@ |
72 | tax = {'name':'', 'amount':0.0, 'account_collected_id':1, 'account_paid_id':2} |
73 | one tax for each tax id in IDS and their children |
74 | """ |
75 | - res = self._unit_compute_inv(cr, uid, taxes, price_unit, address_id, product, partner=None) |
76 | + res = self._unit_compute_inv(cr, uid, taxes, price_unit, address_id, product, partner=partner) |
77 | total = 0.0 |
78 | obj_precision = self.pool.get('decimal.precision') |
79 | for r in res: |
80 | |
81 | === modified file 'bin/addons/account/account_invoice_view.xml' |
82 | --- bin/addons/account/account_invoice_view.xml 2019-07-29 15:00:38 +0000 |
83 | +++ bin/addons/account/account_invoice_view.xml 2019-09-24 13:32:21 +0000 |
84 | @@ -216,13 +216,15 @@ |
85 | <field name="tax_line" nolabel="1" attrs="{'invisible': [('vat_ok', '=', False)], 'readonly': ['|', ('state','!=', 'draft'), '&', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"> |
86 | <tree editable="bottom" string="Taxes"> |
87 | <field name="invoice_id" invisible="True"/> |
88 | - <field name="account_tax_id" on_change="tax_code_change(account_tax_id,parent.amount_untaxed,context)"/> |
89 | + <field name="account_tax_id" on_change="tax_code_change(account_tax_id, parent.amount_untaxed, parent.partner_id, context)"/> |
90 | <field name="name"/> |
91 | |
92 | <field name="account_id" groups="account.group_account_invoice" |
93 | domain="[('type', 'not in', ['view', 'consolidation']), |
94 | ('user_type_code', '=', 'tax')]"/> |
95 | |
96 | + <field name="partner_id" readonly="1"/> |
97 | + |
98 | <field name="base" on_change="base_change(base,parent.currency_id,parent.company_id,parent.date_invoice)" readonly="1"/> |
99 | <field name="amount" on_change="amount_change(amount,parent.currency_id,parent.company_id,parent.date_invoice)"/> |
100 | |
101 | |
102 | === modified file 'bin/addons/account/account_view.xml' |
103 | --- bin/addons/account/account_view.xml 2019-01-31 14:39:54 +0000 |
104 | +++ bin/addons/account/account_view.xml 2019-09-24 13:32:21 +0000 |
105 | @@ -972,6 +972,7 @@ |
106 | <field name="type_tax_use"/> |
107 | <field name="price_include"/> |
108 | <field name="active"/> |
109 | + <field name="partner_id"/> |
110 | <field name="company_id" widget="selection" groups="base.group_multi_company"/> |
111 | </group> |
112 | <notebook colspan="4"> |
113 | |
114 | === modified file 'bin/addons/account/invoice.py' |
115 | --- bin/addons/account/invoice.py 2019-07-25 14:58:06 +0000 |
116 | +++ bin/addons/account/invoice.py 2019-09-24 13:32:21 +0000 |
117 | @@ -1111,7 +1111,7 @@ |
118 | def line_get_convert(self, cr, uid, x, part, date, context=None): |
119 | return { |
120 | 'date_maturity': x.get('date_maturity', False), |
121 | - 'partner_id': part, |
122 | + 'partner_id': x.get('partner_id') or part, |
123 | 'name': x['name'][:64], |
124 | 'date': date, |
125 | 'debit_currency': x['price']>0 and x['price'], |
126 | @@ -1856,13 +1856,35 @@ |
127 | raise osv.except_osv(_('Warning !'), _('The Untaxed Amount is zero. Please press the Save & Edit button before saving the %s tax.') % (vals['name'])) |
128 | return True |
129 | |
130 | + def _update_tax_partner(self, cr, uid, vals, context=None): |
131 | + """ |
132 | + Updates vals with the partner of the related tax |
133 | + |
134 | + Note that in case a partner_id is already in vals, it is used (e.g. in case of a SI refund the SR tax lines must be exactly |
135 | + the same as the SI ones, even if the partner linked to the related account.tax has changed in the meantime) |
136 | + """ |
137 | + if context is None: |
138 | + context = {} |
139 | + tax_obj = self.pool.get('account.tax') |
140 | + if 'partner_id' not in vals and 'account_tax_id' in vals: |
141 | + tax_partner_id = False |
142 | + if vals['account_tax_id']: # note that at doc level it's possible not to have any link to a tax from the system |
143 | + tax = tax_obj.browse(cr, uid, vals['account_tax_id'], fields_to_fetch=['partner_id'], context=context) |
144 | + tax_partner_id = tax.partner_id and tax.partner_id.id or False |
145 | + vals.update({'partner_id': tax_partner_id}) |
146 | |
147 | def create(self, cr, uid, vals, context=None): |
148 | - if context == None: |
149 | + if context is None: |
150 | context = {} |
151 | self._check_untaxed_amount(cr, uid, vals, context) |
152 | + self._update_tax_partner(cr, uid, vals, context=context) |
153 | return super(account_invoice_tax, self).create(cr, uid, vals, context=context) |
154 | |
155 | + def write(self, cr, uid, ids, vals, context=None): |
156 | + if context is None: |
157 | + context = {} |
158 | + self._update_tax_partner(cr, uid, vals, context=context) |
159 | + return super(account_invoice_tax, self).write(cr, uid, ids, vals, context=context) |
160 | |
161 | def _count_factor(self, cr, uid, ids, name, args, context=None): |
162 | res = {} |
163 | @@ -1896,16 +1918,31 @@ |
164 | 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), |
165 | 'factor_base': fields.function(_count_factor, method=True, string='Multipication factor for Base code', type='float', multi="all"), |
166 | 'factor_tax': fields.function(_count_factor, method=True, string='Multipication factor Tax code', type='float', multi="all"), |
167 | - 'account_tax_id': fields.many2one('account.tax', 'Tax', domain=[('price_include', '=', False)]) |
168 | + 'account_tax_id': fields.many2one('account.tax', 'Tax', domain=[('price_include', '=', False)]), |
169 | + 'partner_id': fields.many2one('res.partner', 'Partner', ondelete='restrict'), |
170 | } |
171 | |
172 | - |
173 | - def tax_code_change(self, cr, uid, ids, account_tax_id, amount_untaxed, context=None): |
174 | + def tax_code_change(self, cr, uid, ids, account_tax_id, amount_untaxed, inv_partner_id, context=None): |
175 | + if context is None: |
176 | + context = {} |
177 | ret = {} |
178 | if account_tax_id: |
179 | atx_obj = self.pool.get('account.tax') |
180 | - atx = atx_obj.browse(cr, uid, account_tax_id, context=context) |
181 | - ret = {'value': {'account_id': atx.account_collected_id.id, 'name': "{0} - {1}".format(atx.name, atx.description or ''), 'base_amount': amount_untaxed, 'amount': self._calculate_tax(cr, uid, account_tax_id, amount_untaxed)}} |
182 | + partner_obj = self.pool.get('res.partner') |
183 | + inv_partner = inv_partner_id and partner_obj.browse(cr, uid, inv_partner_id, |
184 | + fields_to_fetch=['name', 'lang'], context=context) or None |
185 | + inv_partner_name = inv_partner and inv_partner.name or '' |
186 | + # use the language of the partner for the tax name (to be consistent with what's done when clicking on Compute Taxes) |
187 | + inv_partner_lang = inv_partner and inv_partner.lang or '' |
188 | + new_context = context.copy() |
189 | + if inv_partner_lang: |
190 | + new_context.update({'lang': inv_partner_lang}) |
191 | + tax = atx_obj.browse(cr, uid, account_tax_id, fields_to_fetch=['name', 'account_collected_id'], context=new_context) |
192 | + description = "%s%s%s" % (tax.name, inv_partner_name and ' - ' or '', inv_partner_name or '') |
193 | + ret = {'value': {'account_id': tax.account_collected_id and tax.account_collected_id.id or False, |
194 | + 'name': description, |
195 | + 'base_amount': amount_untaxed, |
196 | + 'amount': self._calculate_tax(cr, uid, account_tax_id, amount_untaxed)}} |
197 | return ret |
198 | |
199 | def _calculate_tax(self, cr, uid, account_tax_id, amount_untaxed): |
200 | @@ -2023,7 +2060,8 @@ |
201 | 'price': t['amount'] or 0.0, |
202 | 'account_id': t['account_id'], |
203 | 'tax_code_id': t['tax_code_id'], |
204 | - 'tax_amount': t['tax_amount'] |
205 | + 'tax_amount': t['tax_amount'], |
206 | + 'partner_id': t['partner_id'], |
207 | }) |
208 | return res |
209 | |
210 | |
211 | === modified file 'bin/addons/account/wizard/account_invoice_refund.py' |
212 | --- bin/addons/account/wizard/account_invoice_refund.py 2019-07-25 15:47:28 +0000 |
213 | +++ bin/addons/account/wizard/account_invoice_refund.py 2019-09-24 13:32:21 +0000 |
214 | @@ -116,11 +116,12 @@ |
215 | def _get_reconcilable_amls(self, aml_list, to_reconcile_dict): |
216 | """ |
217 | Fill in to_reconcile_dict with the aml from aml_list having a reconcilable account |
218 | - (key = account id, value = list of aml ids) |
219 | + key = tuple with (account id, partner_id, is_counterpart) |
220 | + value = list of aml ids |
221 | """ |
222 | for ml in aml_list: |
223 | if ml.account_id.reconcile: |
224 | - key = (ml.account_id.id, ml.is_counterpart) |
225 | + key = (ml.account_id.id, ml.partner_id and ml.partner_id.id or False, ml.is_counterpart) |
226 | to_reconcile_dict.setdefault(key, []).append(ml.id) |
227 | |
228 | def compute_refund(self, cr, uid, ids, mode='refund', context=None): |
229 | @@ -234,8 +235,8 @@ |
230 | self._get_reconcilable_amls(movelines, to_reconcile) |
231 | self._get_reconcilable_amls(refund.move_id.line_id, to_reconcile) |
232 | # reconcile the lines grouped by account |
233 | - for account_id, is_counterpart in to_reconcile: |
234 | - account_m_line_obj.reconcile(cr, uid, to_reconcile[(account_id, is_counterpart)], |
235 | + for account_id, partner_id, is_counterpart in to_reconcile: |
236 | + account_m_line_obj.reconcile(cr, uid, to_reconcile[(account_id, partner_id, is_counterpart)], |
237 | writeoff_period_id=period, |
238 | writeoff_journal_id = inv.journal_id.id, |
239 | writeoff_acc_id=account_id |
240 | |
241 | === modified file 'bin/addons/msf_partner/partner.py' |
242 | --- bin/addons/msf_partner/partner.py 2019-02-08 16:27:30 +0000 |
243 | +++ bin/addons/msf_partner/partner.py 2019-09-24 13:32:21 +0000 |
244 | @@ -666,6 +666,26 @@ |
245 | |
246 | return True |
247 | |
248 | + def _check_existing_tax_partner(self, cr, uid, ids, context=None): |
249 | + """ |
250 | + Raises an error in case the partner has been used in a tax (to be used when trying to de-activate partners) |
251 | + """ |
252 | + if context is None: |
253 | + context = {} |
254 | + tax_obj = self.pool.get('account.tax') |
255 | + inv_obj = self.pool.get('account.invoice') |
256 | + inv_tax_obj = self.pool.get('account.invoice.tax') |
257 | + if tax_obj.search_exist(cr, uid, [('partner_id', 'in', ids)], context=context): |
258 | + raise osv.except_osv(_('Warning'), |
259 | + _("Impossible to deactivate a partner used for a tax.")) |
260 | + # use case: partner linked to a tax, related tax lines generated and partner removed from the tax |
261 | + # Note that only draft account.invoices need to be checked as other ones have generated JIs (so are already checked) |
262 | + draft_invoice_ids = inv_obj.search(cr, uid, [('state', '=', 'draft')], order='NO_ORDER', context=context) |
263 | + if draft_invoice_ids: |
264 | + if inv_tax_obj.search_exist(cr, uid, [('partner_id', 'in', ids), ('invoice_id', 'in', draft_invoice_ids)], context=context): |
265 | + raise osv.except_osv(_('Warning'), |
266 | + _("Impossible to deactivate a partner used in the tax line of an invoice.")) |
267 | + |
268 | def write(self, cr, uid, ids, vals, context=None): |
269 | if not ids: |
270 | return True |
271 | @@ -701,6 +721,7 @@ |
272 | raise osv.except_osv(_('Warning'), |
273 | _("""The following documents linked to the partner need to be closed before deactivating the partner: %s""" |
274 | ) % (objects_linked_to_partner)) |
275 | + self._check_existing_tax_partner(cr, uid, ids, context=context) |
276 | |
277 | if vals.get('name'): |
278 | vals['name'] = vals['name'].replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ').strip() |
279 | |
280 | === modified file 'bin/addons/msf_profile/i18n/fr_MF.po' |
281 | --- bin/addons/msf_profile/i18n/fr_MF.po 2019-09-17 16:00:23 +0000 |
282 | +++ bin/addons/msf_profile/i18n/fr_MF.po 2019-09-24 13:32:21 +0000 |
283 | @@ -49841,6 +49841,8 @@ |
284 | #: report:addons/stock/report/stock_delivery_report_xls.mako:186 |
285 | #: report:addons/stock/report/stock_delivery_report_xls.mako:211 |
286 | #: field:stock.delivery.wizard,partner_id:0 |
287 | +#: field:account.invoice.tax,partner_id:0 |
288 | +#: field:account.tax,partner_id:0 |
289 | #, python-format |
290 | msgid "Partner" |
291 | msgstr "Partenaire" |
292 | @@ -107372,3 +107374,21 @@ |
293 | #: report:purchase.order.merged:0 |
294 | msgid "Functional total cost :" |
295 | msgstr "Total Coût Fonctionnel :" |
296 | + |
297 | +#. module: msf_partner |
298 | +#: code:addons/msf_partner/partner.py:680 |
299 | +#, python-format |
300 | +msgid "Impossible to deactivate a partner used for a tax." |
301 | +msgstr "Impossible de désactiver un partenaire utilisé pour une taxe." |
302 | + |
303 | +#. module: msf_partner |
304 | +#: code:addons/msf_partner/partner.py:687 |
305 | +#, python-format |
306 | +msgid "Impossible to deactivate a partner used in the tax line of an invoice." |
307 | +msgstr "Impossible de désactiver un partenaire utilisé dans la ligne de taxe d'une facture." |
308 | + |
309 | +#. module: account |
310 | +#: code:addons/account/account.py:1980 |
311 | +#, python-format |
312 | +msgid "You can't link the tax to the Partner %s: only active external partners are allowed." |
313 | +msgstr "Vous ne pouvez pas lier la taxe au partenaire %s : seuls les partenaires externes actifs sont autorisés." |
314 | |
315 | === modified file 'bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv' |
316 | --- bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv 2019-08-08 13:55:43 +0000 |
317 | +++ bin/addons/msf_sync_data_server/data/sync_server.sync_rule.csv 2019-09-24 13:32:21 +0000 |
318 | @@ -126,7 +126,7 @@ |
319 | msf_sync_data_server.standard_product_list_line,TRUE,TRUE,TRUE,TRUE,bidirectional,Down,"[('list_id' , 'in', ('product.list', 'id', [('standard_list_ok','=','True')]))]","['comment','list_id/id','ref','name/id']",OC,product.list.line,,Standard Product List Line,Valid,,606 |
320 | msf_sync_data_server.tax_code,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,[],"['code', 'info', 'name', 'notprintable', 'sign']",OC,account.tax.code,,Tax Code,Valid,,610 |
321 | msf_sync_data_server.tax_code_tree,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('parent_id','!=','')]",['parent_id/id'],OC,account.tax.code,,Tax Code Tree,Valid,,611 |
322 | -msf_sync_data_server.account_tax,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,[],"['account_collected_id/id', 'account_paid_id/id', 'active', 'amount', 'applicable_type', 'base_code_id/id', 'base_sign', 'child_depend', 'description', 'domain', 'include_base_amount', 'name', 'price_include', 'python_applicable', 'python_compute', 'python_compute_inv', 'ref_base_code_id/id', 'ref_base_sign', 'ref_tax_code_id/id', 'ref_tax_sign', 'sequence', 'tax_code_id/id', 'tax_sign', 'type', 'type_tax_use']",OC,account.tax,,Account Tax,Valid,,612 |
323 | +msf_sync_data_server.account_tax,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,[],"['account_collected_id/id', 'account_paid_id/id', 'active', 'amount', 'applicable_type', 'base_code_id/id', 'base_sign', 'child_depend', 'description', 'domain', 'include_base_amount', 'name', 'price_include', 'python_applicable', 'python_compute', 'python_compute_inv', 'ref_base_code_id/id', 'ref_base_sign', 'ref_tax_code_id/id', 'ref_tax_sign', 'sequence', 'tax_code_id/id', 'tax_sign', 'type', 'type_tax_use', 'partner_id/id']",OC,account.tax,,Account Tax,Valid,,612 |
324 | msf_sync_data_server.account_tax_tree,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('parent_id','!=','')]",['parent_id/id'],OC,account.tax,,Account Tax Tree,Valid,,613 |
325 | msf_sync_data_server.composition_kit,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('state','=','completed'),('composition_type','=','theoretical')]","['active', 'composition_creation_date', 'composition_description', 'composition_product_id/id', 'composition_type', 'composition_version', 'composition_version_txt', 'name', 'state']",OC,composition.kit,,Theoretical Kit Composition List,Valid,,620 |
326 | msf_sync_data_server.composition_item,TRUE,TRUE,FALSE,TRUE,bidirectional,Down,"[('item_kit_id' , 'in' , ('composition.kit' , 'id' , [('state','=','completed'),('composition_type','=','theoretical')]))]","['item_asset_id/id', 'item_kit_id/id', 'item_module', 'item_product_id/id', 'item_qty', 'item_uom_id/id']",OC,composition.item,,Theoretical Kit Composition List Line,Valid,,621 |
327 | |
328 | === modified file 'bin/addons/sync_client/update.py' |
329 | --- bin/addons/sync_client/update.py 2019-04-03 09:52:48 +0000 |
330 | +++ bin/addons/sync_client/update.py 2019-09-24 13:32:21 +0000 |
331 | @@ -964,6 +964,8 @@ |
332 | |
333 | if update.model == 'res.partner.address' and field == 'partner_id/id': |
334 | return {'res': False, 'error_message': 'partner_id %s not found' % xmlid} |
335 | + if update.model == 'account.tax' and field == 'partner_id/id': |
336 | + return {'res': False, 'error_message': 'partner_id %s not found' % xmlid} |
337 | if update.model == 'account.analytic.line' and field in ('cost_center_id/id', 'destination_id/id'): |
338 | return {'res': False, 'error_message': 'Analytic Account %s not found' % xmlid} |
339 | fb = fallback.get(field, False) |