Merge lp:~mukunde/unifield-server/US-9389 into lp:unifield-server

Proposed by jftempo
Status: Needs review
Proposed branch: lp:~mukunde/unifield-server/US-9389
Merge into: lp:unifield-server
Diff against target: 1839 lines (+1229/-19) (has conflicts)
16 files modified
bin/addons/account/__openerp__.py (+1/-0)
bin/addons/account/account_report.xml (+13/-0)
bin/addons/account/report/__init__.py (+1/-0)
bin/addons/account/report/export_cv.mako (+206/-0)
bin/addons/account/report/export_cv.py (+34/-0)
bin/addons/account/report/export_invoice.mako (+82/-0)
bin/addons/account/wizard/__init__.py (+1/-0)
bin/addons/account/wizard/account_cv_import.py (+394/-0)
bin/addons/account/wizard/account_cv_import.xml (+49/-0)
bin/addons/account/wizard/account_invoice_import.py (+74/-3)
bin/addons/account/wizard/account_invoice_import.xml (+2/-2)
bin/addons/analytic_distribution/account_commitment.py (+32/-5)
bin/addons/analytic_distribution/account_commitment_view.xml (+7/-0)
bin/addons/analytic_distribution/analytic_distribution.py (+12/-1)
bin/addons/base/ir/ir_model.py (+4/-1)
bin/addons/msf_profile/i18n/fr_MF.po (+317/-7)
Text conflict in bin/addons/msf_profile/i18n/fr_MF.po
To merge this branch: bzr merge lp:~mukunde/unifield-server/US-9389
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+428378@code.launchpad.net
To post a comment you must log in.
lp:~mukunde/unifield-server/US-9389 updated
6275. By Gaël Mukunde

US-9732 [IMP] Fix export of AD type of lines + uninitialized distrib_id var fix

6276. By Gaël Mukunde

US-9732 [IMP] Fix FP cell borders when no AD at header nor line level

6277. By Gaël Mukunde

US-9732 [IMP] Put back the line break on Note field

6278. By Gaël Mukunde

US-9732 [IMP] Remove test flags in mako file

6279. By Gaël Mukunde

US-9732 [IMP] Check analytic account activation status on Invoice posting date, or if empty, at today's date

6280. By Gaël Mukunde

US-9732 [IMP] When AD is SPLIT, keep other fields while ignoring AD fields

6281. By Gaël Mukunde

[MERGE] lp:~mukunde/unifield-server/US-9389

6282. By Gaël Mukunde

US-9732 [IMP] Fix uninitialized vars

6283. By Gaël Mukunde

US-9732 [IMP] Set AD cell editable if it contains SPLIT.

6284. By Gaël Mukunde

US-9732 [MERGE] lp:~jfb-tempo-consulting/unifield-server/US-9389

Unmerged revisions

6284. By Gaël Mukunde

US-9732 [MERGE] lp:~jfb-tempo-consulting/unifield-server/US-9389

6283. By Gaël Mukunde

US-9732 [IMP] Set AD cell editable if it contains SPLIT.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/account/__openerp__.py'
2--- bin/addons/account/__openerp__.py 2022-05-06 15:09:54 +0000
3+++ bin/addons/account/__openerp__.py 2022-10-10 10:18:59 +0000
4@@ -113,6 +113,7 @@
5 "wizard/account_report_balance_sheet_view.xml",
6 "wizard/account_report_liquidity_balance_view.xml",
7 "wizard/account_report_employee_ledger_view.xml",
8+ 'wizard/account_cv_import.xml',
9 ],
10 'demo_xml': [
11 'account_demo.xml',
12
13=== modified file 'bin/addons/account/account_report.xml'
14--- bin/addons/account/account_report.xml 2022-05-06 15:09:54 +0000
15+++ bin/addons/account/account_report.xml 2022-10-10 10:18:59 +0000
16@@ -196,5 +196,18 @@
17 header="False"
18 auto="False"
19 menu="False"/>
20+
21+ <!-- Export CV report -->
22+ <report id="export_cv"
23+ string="Export - CV"
24+ target_filename="Export - CV"
25+ model="account.commitment"
26+ name="account.export_cv"
27+ file="account/report/export_cv.mako"
28+ report_type="webkit"
29+ header="False"
30+ auto="False"
31+ menu="False"/>
32+
33 </data>
34 </openerp>
35
36=== modified file 'bin/addons/account/report/__init__.py'
37--- bin/addons/account/report/__init__.py 2022-05-06 15:09:54 +0000
38+++ bin/addons/account/report/__init__.py 2022-10-10 10:18:59 +0000
39@@ -45,6 +45,7 @@
40 import invoice_excel_export
41 import export_invoice
42 import account_employee_ledger
43+import export_cv
44
45 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
46
47
48=== added file 'bin/addons/account/report/export_cv.mako'
49--- bin/addons/account/report/export_cv.mako 1970-01-01 00:00:00 +0000
50+++ bin/addons/account/report/export_cv.mako 2022-10-10 10:18:59 +0000
51@@ -0,0 +1,206 @@
52+<?xml version="1.0"?>
53+<?mso-application progid="Excel.Sheet"?>
54+<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
55+ xmlns:o="urn:schemas-microsoft-com:office:office"
56+ xmlns:x="urn:schemas-microsoft-com:office:excel"
57+ xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
58+ xmlns:html="http://www.w3.org/TR/REC-html40">
59+ <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
60+ <Title>${_('Export - CV')}</Title>
61+ </DocumentProperties>
62+ <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
63+ <WindowHeight>13170</WindowHeight>
64+ <WindowWidth>19020</WindowWidth>
65+ <WindowTopX>120</WindowTopX>
66+ <WindowTopY>60</WindowTopY>
67+ <ProtectStructure>False</ProtectStructure>
68+ <ProtectWindows>False</ProtectWindows>
69+ </ExcelWorkbook>
70+<Styles>
71+ <Style ss:ID="editable">
72+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
73+ <Borders>
74+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
75+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
76+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
77+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
78+ </Borders>
79+ <Protection ss:Protected="0"/>
80+ </Style>
81+ <Style ss:ID="editable_number">
82+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
83+ <Borders>
84+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
85+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
86+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
87+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
88+ </Borders>
89+ <NumberFormat ss:Format="Standard"/>
90+ <Protection ss:Protected="0"/>
91+ </Style>
92+ <Style ss:ID="non_editable">
93+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
94+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
95+ <Borders>
96+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
97+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
98+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
99+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
100+ </Borders>
101+ <Protection/>
102+ </Style>
103+ <Style ss:ID="non_editable_red_bold">
104+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
105+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
106+ <Font ss:Bold="1" ss:Color="#FF0000"/>
107+ <Borders>
108+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
109+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
110+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
111+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
112+ </Borders>
113+ <Protection/>
114+ </Style>
115+ <Style ss:ID="non_editable_number">
116+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
117+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
118+ <Borders>
119+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
120+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
121+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
122+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
123+ </Borders>
124+ <NumberFormat ss:Format="Standard"/>
125+ <Protection/>
126+ </Style>
127+ <Style ss:ID="non_editable_date">
128+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
129+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
130+ <Borders>
131+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
132+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
133+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
134+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
135+ </Borders>
136+ <NumberFormat ss:Format="Short Date"/>
137+ <Protection/>
138+ </Style>
139+</Styles>
140+% for o in objects:
141+<!-- Sheet must be protected otherwise the protection on the cells has no effect -->
142+<!-- Default Sheet name is "Sheet1" (we can export only one cv at a time) -->
143+<ss:Worksheet ss:Name="${o.name or "%s%s" % (_('Sheet'), 1)|x}" ss:Protected="1">
144+<Table x:FullColumns="1" x:FullRows="1">
145+ <Column ss:AutoFitWidth="1" ss:Width="50"/>
146+ <Column ss:AutoFitWidth="1" ss:Width="150"/>
147+ <Column ss:AutoFitWidth="1" ss:Width="50"/>
148+ <Column ss:AutoFitWidth="1" ss:Width="100"/>
149+ <Column ss:AutoFitWidth="1" ss:Width="150" ss:Span="1"/>
150+ <Column ss:AutoFitWidth="1" ss:Width="300" ss:Span="1"/>
151+
152+ <Row>
153+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Journal')}</Data></Cell>
154+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.journal_id.code or ''|x}</Data></Cell>
155+ </Row>
156+ <Row>
157+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Number')}</Data></Cell>
158+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.name or ''|x}</Data></Cell>
159+ </Row>
160+ <Row>
161+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Commitment Date')}</Data></Cell>
162+ % if isDate(o.date):
163+ <Cell ss:StyleID="non_editable_date" ss:MergeAcross="1"><Data ss:Type="DateTime">${o.date|n}T00:00:00.000</Data></Cell>
164+ % else:
165+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String"></Data></Cell>
166+ % endif
167+ </Row>
168+ <Row>
169+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Currency')}</Data></Cell>
170+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.currency_id.name or ''|x}</Data></Cell>
171+ </Row>
172+ <Row>
173+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Description')}</Data></Cell>
174+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.description or ''|x}</Data></Cell>
175+ </Row>
176+ <Row>
177+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Supplier')}</Data></Cell>
178+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.partner_id.name or ''|x}</Data></Cell>
179+ </Row>
180+ <Row>
181+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Source Document')}</Data></Cell>
182+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.purchase_id and o.purchase_id.name or o.sale_id and o.sale_id.name or ''|x}</Data></Cell>
183+ </Row>
184+ <Row>
185+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Period')}</Data></Cell>
186+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${o.period_id.name or ''|x}</Data></Cell>
187+ </Row>
188+ <Row>
189+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${_('Type')}</Data></Cell>
190+ <Cell ss:StyleID="non_editable" ss:MergeAcross="1"><Data ss:Type="String">${getSel(o, 'type')|x}</Data></Cell>
191+ </Row>
192+
193+ <Row><Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell></Row>
194+
195+ <Row>
196+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Internal ID')}</Data></Cell>
197+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Commitment Voucher Lines')}</Data></Cell>
198+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Line number')}</Data></Cell>
199+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Account')}</Data></Cell>
200+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Initial Amount')}</Data></Cell>
201+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Left Amount')}</Data></Cell>
202+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Analytic Distribution')}</Data></Cell>
203+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Cost Center')}</Data></Cell>
204+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Destination')}</Data></Cell>
205+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Funding Pool')}</Data></Cell>
206+ </Row>
207+
208+ % for cv_line in o.line_ids:
209+ <Row>
210+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${cv_line.id or ''|x}</Data></Cell>
211+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${cv_line.line_product_id and cv_line.line_product_id.default_code or ''|x}</Data></Cell>
212+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${cv_line.line_number or ''|x}</Data></Cell>
213+ <Cell ss:StyleID="editable"><Data ss:Type="String">${cv_line.account_id and cv_line.account_id.code or ''|x}</Data></Cell>
214+ <Cell ss:StyleID="non_editable_number"><Data ss:Type="Number">${cv_line.initial_amount|x}</Data></Cell>
215+ <Cell ss:StyleID="non_editable_number"><Data ss:Type="Number">${cv_line.amount|x}</Data></Cell>
216+ <% ad_obj = cv_line.analytic_distribution_id or cv_line.commit_id.analytic_distribution_id or False %>
217+ % if ad_obj and len(ad_obj.funding_pool_lines) == 1 :
218+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${'100%'|x}</Data></Cell>
219+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].cost_center_id.code or ''|x}</Data></Cell>
220+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].destination_id.code or ''|x}</Data></Cell>
221+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].analytic_id.code or ''|x}</Data></Cell>
222+ % elif ad_obj and len(ad_obj.funding_pool_lines) > 1:
223+ <Cell ss:StyleID="non_editable_red_bold"><Data ss:Type="String">${'SPLIT'|x}</Data></Cell>
224+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
225+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
226+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
227+ % else:
228+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
229+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
230+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
231+ <Cell ss:StyleID="editable"><Data ss:Type="String"></Data></Cell>
232+ % endif
233+ </Row>
234+ % endfor
235+
236+</Table>
237+<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
238+ <FitToPage/>
239+ <PageSetup>
240+ <Layout x:Orientation="Portrait"/>
241+ <Header x:Margin="0.4921259845"/>
242+ <Footer x:Margin="0.4921259845"/>
243+ <PageMargins x:Bottom="0.984251969" x:Left="0.78740157499999996" x:Right="0.78740157499999996" x:Top="0.984251969"/>
244+ </PageSetup>
245+ <Print>
246+ <ValidPrinterInfo/>
247+ <PaperSizeIndex>9</PaperSizeIndex>
248+ <HorizontalResolution>600</HorizontalResolution>
249+ <VerticalResolution>600</VerticalResolution>
250+ </Print>
251+ <Selected/>
252+ <ProtectObjects>False</ProtectObjects>
253+ <ProtectScenarios>False</ProtectScenarios>
254+</WorksheetOptions>
255+</ss:Worksheet>
256+% endfor
257+</Workbook>
258
259=== added file 'bin/addons/account/report/export_cv.py'
260--- bin/addons/account/report/export_cv.py 1970-01-01 00:00:00 +0000
261+++ bin/addons/account/report/export_cv.py 2022-10-10 10:18:59 +0000
262@@ -0,0 +1,34 @@
263+# -*- coding: utf-8 -*-
264+##############################################################################
265+#
266+# OpenERP, Open Source Management Solution
267+# Copyright (C) 2022 TeMPO Consulting, MSF. All Rights Reserved
268+#
269+# This program is free software: you can redistribute it and/or modify
270+# it under the terms of the GNU Affero General Public License as
271+# published by the Free Software Foundation, either version 3 of the
272+# License, or (at your option) any later version.
273+#
274+# This program is distributed in the hope that it will be useful,
275+# but WITHOUT ANY WARRANTY; without even the implied warranty of
276+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
277+# GNU Affero General Public License for more details.
278+#
279+# You should have received a copy of the GNU Affero General Public License
280+# along with this program. If not, see <http://www.gnu.org/licenses/>.
281+#
282+##############################################################################
283+
284+from report import report_sxw
285+from spreadsheet_xml.spreadsheet_xml_write import SpreadsheetReport
286+
287+
288+class export_cv(report_sxw.rml_parse):
289+
290+ def __init__(self, cr, uid, name, context=None):
291+ super(export_cv, self).__init__(cr, uid, name, context=context)
292+
293+
294+SpreadsheetReport('report.account.export_cv', 'account.commitment',
295+ 'addons/account/report/export_cv.mako', parser=export_cv)
296+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
297
298=== modified file 'bin/addons/account/report/export_invoice.mako'
299--- bin/addons/account/report/export_invoice.mako 2021-12-16 15:56:46 +0000
300+++ bin/addons/account/report/export_invoice.mako 2022-10-10 10:18:59 +0000
301@@ -27,6 +27,17 @@
302 </Borders>
303 <Protection ss:Protected="0"/>
304 </Style>
305+ <Style ss:ID="editable_red_bold">
306+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
307+ <Font ss:Bold="1" ss:Color="#FF0000"/>
308+ <Borders>
309+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
310+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
311+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
312+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
313+ </Borders>
314+ <Protection ss:Protected="0"/>
315+ </Style>
316 <Style ss:ID="editable_number">
317 <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
318 <Borders>
319@@ -49,6 +60,18 @@
320 </Borders>
321 <Protection/>
322 </Style>
323+ <Style ss:ID="non_editable_red_bold">
324+ <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
325+ <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
326+ <Font ss:Bold="1" ss:Color="#FF0000"/>
327+ <Borders>
328+ <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
329+ <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
330+ <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
331+ <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
332+ </Borders>
333+ <Protection/>
334+ </Style>
335 <Style ss:ID="non_editable_number">
336 <Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1"/>
337 <Interior ss:Color="#ffcc99" ss:Pattern="Solid"/>
338@@ -132,6 +155,10 @@
339 <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Unit Price')}</Data></Cell>
340 <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Description')}</Data></Cell>
341 <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Notes')}</Data></Cell>
342+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Analytic Distribution')}</Data></Cell>
343+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Cost Center')}</Data></Cell>
344+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Destination')}</Data></Cell>
345+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${_('Funding Pool')}</Data></Cell>
346 </Row>
347
348 <% is_ro = is_readonly(o) %>
349@@ -158,8 +185,63 @@
350
351 <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.name or ''|x}</Data></Cell>
352
353+
354 <!-- export Notes including line breaks (|xn) -->
355 <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.note or ''|xn}</Data></Cell>
356+ % if (inv_line.analytic_distribution_id and len(inv_line.analytic_distribution_id.cost_center_lines) == 1) :
357+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${'100%'|x}</Data></Cell>
358+ % elif (inv_line.analytic_distribution_id and len(inv_line.analytic_distribution_id.cost_center_lines) > 1):
359+ <Cell ss:StyleID="editable_red_bold"><Data ss:Type="String">${'SPLIT'|x}</Data></Cell>
360+ % elif (inv_line.invoice_id.analytic_distribution_id and len(inv_line.invoice_id.analytic_distribution_id.cost_center_lines) == 1):
361+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${'100%'|x}</Data></Cell>
362+ % elif (inv_line.invoice_id.analytic_distribution_id and len(inv_line.invoice_id.analytic_distribution_id.cost_center_lines) > 1):
363+ <Cell ss:StyleID="editable_red_bold"><Data ss:Type="String">${'SPLIT'|x}</Data></Cell>
364+ % endif
365+ % if not inv_line.analytic_distribution_id and not inv_line.invoice_id.analytic_distribution_id:
366+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
367+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
368+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
369+ <!-- export Funding Pool including line breaks (|xn) -->
370+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|xn}</Data></Cell>
371+ % elif inv_line.analytic_distribution_id:
372+ % if len(inv_line.analytic_distribution_id.cost_center_lines) == 1:
373+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.analytic_distribution_id.cost_center_lines[0].analytic_id.code or ''|x}</Data></Cell>
374+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.analytic_distribution_id.cost_center_lines[0].destination_id.code or ''|x}</Data></Cell>
375+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.analytic_distribution_id.funding_pool_lines[0].analytic_id.code or ''|xn}</Data></Cell>
376+ % elif len(inv_line.analytic_distribution_id.cost_center_lines) > 1:
377+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
378+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
379+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|xn}</Data></Cell>
380+ % endif
381+ % elif inv_line.invoice_id.analytic_distribution_id:
382+ % if len(inv_line.invoice_id.analytic_distribution_id.cost_center_lines) == 1:
383+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.invoice_id.analytic_distribution_id.cost_center_lines[0].analytic_id.code or ''|x}</Data></Cell>
384+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.invoice_id.analytic_distribution_id.cost_center_lines[0].destination_id.code or ''|x}</Data></Cell>
385+ <Cell ss:StyleID="editable"><Data ss:Type="String">${inv_line.invoice_id.analytic_distribution_id.funding_pool_lines[0].analytic_id.code or ''|xn}</Data></Cell>
386+ % elif len(inv_line.invoice_id.analytic_distribution_id.cost_center_lines) > 1:
387+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
388+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
389+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|xn}</Data></Cell>
390+ % endif
391+ % endif
392+
393+ <% ad_obj = inv_line.account_id.is_analytic_addicted and (inv_line.analytic_distribution_id or inv_line.invoice_id.analytic_distribution_id) or False %>
394+ % if ad_obj and len(ad_obj.funding_pool_lines) == 1 :
395+ <Cell ss:StyleID="non_editable"><Data ss:Type="String">${'100%'|x}</Data></Cell>
396+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].cost_center_id.code or ''|x}</Data></Cell>
397+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].destination_id.code or ''|x}</Data></Cell>
398+ <Cell ss:StyleID="editable"><Data ss:Type="String">${ad_obj.funding_pool_lines[0].analytic_id.code or ''|x}</Data></Cell>
399+ % elif ad_obj and len(ad_obj.funding_pool_lines) > 1:
400+ <Cell ss:StyleID="non_editable_red_bold"><Data ss:Type="String">${'SPLIT'|x}</Data></Cell>
401+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
402+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
403+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
404+ % else:
405+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
406+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
407+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
408+ <Cell ss:StyleID="editable"><Data ss:Type="String">${''|x}</Data></Cell>
409+ % endif
410 </Row>
411 % endfor
412
413
414=== modified file 'bin/addons/account/wizard/__init__.py'
415--- bin/addons/account/wizard/__init__.py 2022-05-10 09:49:15 +0000
416+++ bin/addons/account/wizard/__init__.py 2022-10-10 10:18:59 +0000
417@@ -70,4 +70,5 @@
418 import account_report_common_employee
419 import account_report_employee_balance
420 import account_report_employee_ledger
421+import account_cv_import
422 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
423
424=== added file 'bin/addons/account/wizard/account_cv_import.py'
425--- bin/addons/account/wizard/account_cv_import.py 1970-01-01 00:00:00 +0000
426+++ bin/addons/account/wizard/account_cv_import.py 2022-10-10 10:18:59 +0000
427@@ -0,0 +1,394 @@
428+#!/usr/bin/env python
429+#-*- encoding:utf-8 -*-
430+##############################################################################
431+#
432+# OpenERP, Open Source Management Solution
433+# Copyright (C) TeMPO Consulting (<http://www.tempo-consulting.fr/>), MSF.
434+# All Rights Reserved
435+#
436+# This program is free software: you can redistribute it and/or modify
437+# it under the terms of the GNU Affero General Public License as
438+# published by the Free Software Foundation, either version 3 of the
439+# License, or (at your option) any later version.
440+#
441+# This program is distributed in the hope that it will be useful,
442+# but WITHOUT ANY WARRANTY; without even the implied warranty of
443+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
444+# GNU Affero General Public License for more details.
445+#
446+# You should have received a copy of the GNU Affero General Public License
447+# along with this program. If not, see <http://www.gnu.org/licenses/>.
448+#
449+##############################################################################
450+
451+from osv import osv
452+from osv import fields
453+from tools.translate import _
454+from tempfile import NamedTemporaryFile
455+from base64 import decodestring
456+from spreadsheet_xml.spreadsheet_xml import SpreadsheetXML
457+import threading
458+import pooler
459+import logging
460+import tools
461+
462+
463+class account_cv_import(osv.osv_memory):
464+ _name = 'account.cv.import'
465+ _inherit = 'account.invoice.import'
466+
467+ _columns = {
468+ 'error_ids': fields.one2many('account.cv.import.errors', 'wizard_id', "Errors", readonly=True),
469+ 'commit_id': fields.many2one('account.commitment', 'Commitment Voucher', required=True, readonly=True),
470+ }
471+
472+ def create(self, cr, uid, vals, context=None):
473+ """
474+ Creation of the wizard using the realUid to allow the process for the non-admin users
475+ """
476+ real_uid = hasattr(uid, 'realUid') and uid.realUid or uid
477+ return super(account_cv_import, self).create(cr, real_uid, vals, context=context)
478+
479+ def _import(self, dbname, uid, ids, context=None):
480+ """
481+ Checks file data, and either updates the lines or displays the errors found
482+ """
483+ if context is None:
484+ context = {}
485+ cr = pooler.get_db(dbname).cursor()
486+ errors = []
487+ ad_errors = []
488+ cv_obj = self.pool.get('account.commitment')
489+ cv_line_obj = self.pool.get('account.commitment.line')
490+ currency_obj = self.pool.get('res.currency')
491+ partner_obj = self.pool.get('res.partner')
492+ account_obj = self.pool.get('account.account')
493+ import_cell_data_obj = self.pool.get('import.cell.data')
494+ errors_obj = self.pool.get('account.cv.import.errors')
495+ ana_obj = self.pool.get('analytic.distribution')
496+ aac_obj = self.pool.get('account.analytic.account')
497+
498+ try:
499+ for wiz in self.browse(cr, uid, ids, context):
500+ self.write(cr, uid, [wiz.id], {'message': _('Checking file…'), 'progression': 1.00}, context)
501+ if not wiz.file:
502+ raise osv.except_osv(_('Error'), _('Nothing to import.'))
503+ fileobj = NamedTemporaryFile('w+b', delete=False)
504+ fileobj.write(decodestring(wiz.file))
505+ fileobj.close()
506+ content = SpreadsheetXML(xmlfile=fileobj.name, context=context)
507+ if not content:
508+ raise osv.except_osv(_('Warning'), _('No content.'))
509+ cv = wiz.commit_id
510+ if cv.state != 'draft':
511+ raise osv.except_osv(_('Warning'), _('The import is allowed only in Draft state.'))
512+ rows = content.getRows()
513+ nb_rows = len([x for x in content.getRows()])
514+ self.write(cr, uid, [wiz.id], {'message': _('Checking header…'), 'progression': 5.00}, context)
515+ # indexes of the file columns:
516+ cols = {
517+ 'cv_line_id': 0,
518+ 'product_code': 1,
519+ 'line_number': 2,
520+ 'account': 3,
521+ 'initial_amount': 4,
522+ 'left_amount': 5,
523+ 'analytic_distribution': 6,
524+ 'cost_center': 7,
525+ 'destination': 8,
526+ 'funding_pool': 9,
527+ }
528+ # number of the first line in the file containing data (not header)
529+ base_num = 12
530+ rows.next() # journal is ignored
531+ number_line = import_cell_data_obj.get_line_values(cr, uid, ids, rows.next())
532+ try:
533+ name = number_line[2]
534+ except IndexError as e:
535+ raise osv.except_osv(_('Warning'), _('No CV number found.'))
536+ cv_ids = cv_obj.search(cr, uid, [('name', '=', name)], context=context)
537+ if not cv_ids:
538+ raise osv.except_osv(_('Error'), _("CV with number: %s not found.") % (name or '',))
539+
540+ # date ingored
541+ rows.next()
542+
543+ currency_line = import_cell_data_obj.get_line_values(cr, uid, ids, rows.next())
544+ try:
545+ currency_name = currency_line[2]
546+ except IndexError as e:
547+ raise osv.except_osv(_('Warning'), _('No currency found.'))
548+ currency_ids = currency_obj.search(cr, uid, [('name', '=', currency_name), ('active', '=', True)],
549+ limit=1, context=context)
550+ if not currency_ids:
551+ raise osv.except_osv(_('Error'), _("Currency %s not found or inactive.") % (currency_name or '',))
552+ rows.next() # description is ignored
553+ partner_line = import_cell_data_obj.get_line_values(cr, uid, ids, rows.next())
554+ try:
555+ partner_name = partner_line[2]
556+ except IndexError as e:
557+ raise osv.except_osv(_('Warning'), _('No supplier found.'))
558+ partner_ids = partner_obj.search(cr, uid, [('name', '=', partner_name), ('active', '=', True)],
559+ context=context)
560+ if not partner_ids:
561+ raise osv.except_osv(_('Error'), _("Supplier %s not found or inactive.") % (partner_name or '',))
562+ source_line = import_cell_data_obj.get_line_values(cr, uid, ids, rows.next())
563+ try:
564+ source_doc = source_line[2] or ''
565+ except IndexError as e:
566+ raise osv.except_osv(_('Warning'), _('No source document found.'))
567+
568+ rows.next() # period is ignored
569+ type_line = import_cell_data_obj.get_line_values(cr, uid, ids, rows.next())
570+ try:
571+ type_desc = type_line[2]
572+ except IndexError as e:
573+ raise osv.except_osv(_('Warning'), _('No CV type found.'))
574+
575+ cv_type = False
576+ for type_key, type_value in cv_obj.get_cv_type(cr, uid, context=context):
577+ if type_value == type_desc:
578+ cv_type = type_key
579+ if not cv_type:
580+ raise osv.except_osv(_('Error'), _("CV type '%s' not found or doesn't exist.") % (type_desc or '',))
581+
582+
583+ cv_dom = [('id', '=', cv.id), ('name', '=', name), ('currency_id', '=', currency_ids[0]),
584+ ('partner_id', '=', partner_ids[0]), ('type', '=', cv_type)]
585+
586+ if not cv_obj.search_exist(cr, uid, cv_dom, context=context) or \
587+ wiz.commit_id.purchase_id and wiz.commit_id.purchase_id.name != source_doc or \
588+ wiz.commit_id.sale_id and wiz.commit_id.sale_id.name != source_doc:
589+ raise osv.except_osv(_('Warning'),
590+ _("The combination \"CV Number, Currency, Supplier, Source Document and CV Type\" of the imported file "
591+ "doesn't match with the current commitment voucher."))
592+ # ignore: empty line, line with titles
593+ for i in range(2):
594+ rows.next()
595+ header_percent = 10 # percentage of the process reached AFTER having checked the header
596+ self.write(cr, uid, [wiz.id], {'message': _('Checking lines…'), 'progression': header_percent}, context)
597+ lines_percent = 99 # % of the process to be reached AFTER having checked and updated the lines
598+ # check the lines
599+ new_ad_only = 0
600+ new_account_only = 0
601+ new_ad_account = 0
602+
603+ for num, r in enumerate(rows):
604+ current_line_num = num + base_num
605+ vals = {}
606+ line = import_cell_data_obj.get_line_values(cr, uid, ids, r)
607+ line.extend([False for i in range(len(cols) - len(line))])
608+ # get the data
609+ cv_line_id = line[cols['cv_line_id']]
610+ cv_line_product = line[cols['product_code']] or False
611+ line_number = line[cols['line_number']] or False
612+ account_code = line[cols['account']] and tools.ustr(line[cols['account']]).strip()
613+ analytic_distribution_type = line[cols['analytic_distribution']] and tools.ustr(line[cols['analytic_distribution']])
614+ cost_center_code = line[cols['cost_center']] and tools.ustr(line[cols['cost_center']])
615+ destination_code = line[cols['destination']] and tools.ustr(line[cols['destination']])
616+ funding_pool_code = line[cols['funding_pool']] and tools.ustr(line[cols['funding_pool']])
617+
618+
619+ if not cv_line_id:
620+ errors.append(_('Line %s: the internal id is missing.') % (current_line_num,))
621+ continue
622+ try:
623+ cv_line_id = int(cv_line_id)
624+ except ValueError as e:
625+ errors.append(_("Line %s: the internal id format is incorrect.") % (current_line_num,))
626+ continue
627+
628+ if line_number:
629+ try:
630+ line_number = int(line_number)
631+ except ValueError as e:
632+ errors.append(_("Line %s: the line number format is incorrect.") % (current_line_num,))
633+ continue
634+
635+ cv_line_dom = [('commit_id', '=', cv.id), ('line_number', '=', line_number), ('id', '=', cv_line_id)]
636+ cv_line_ids = cv_line_obj.search(cr, uid, cv_line_dom, limit=1, context=context)
637+ if not cv_line_ids:
638+ errors.append(_("Line %s: the line number %s doesn't exist in the commitment voucher.") % (current_line_num, line_number))
639+ continue
640+
641+ cv_line_data = cv_line_obj.browse(cr, uid, cv_line_ids[0], context=context)
642+
643+ if not account_code:
644+ errors.append(_("Line %s: empty account code field is not allowed.") % (current_line_num,))
645+ continue
646+
647+ if account_code != cv_line_data.account_id.code:
648+ account_ids = account_obj.search(cr, uid, ['&', ('code', '=', account_code), ('restricted_area', '=', 'commitment_lines')], limit=1, context=context)
649+ if not account_ids:
650+ errors.append(_("Line %s: the account %s does not exist or inactive or mistyped.") % (current_line_num, account_code))
651+ continue
652+ account = account_obj.browse(cr, uid, account_ids[0], context=context)
653+ vals['account_id'] = account.id
654+ else:
655+ account = cv_line_data.account_id
656+
657+ if (cv_line_data.line_product_id and cv_line_data.line_product_id.default_code or False) != cv_line_product:
658+ errors.append(_("Line %s: product %s doesn't match.") % (current_line_num, cv_line_product))
659+ continue
660+
661+ if account.is_analytic_addicted and analytic_distribution_type and analytic_distribution_type.strip() in ('100%', '100', '1'):
662+ if not cost_center_code or not destination_code or not funding_pool_code:
663+ errors.append(_("Line %s: An expense account is set while the analytic distribution values (mandatory) are missing.") % (current_line_num,))
664+ continue
665+
666+ cc_ids = aac_obj.search(cr, uid, [('code', '=', cost_center_code),('category', '=', 'OC'), ('type', '!=', 'view')], limit=1, context=context)
667+ if not cc_ids:
668+ errors.append(_("Line %s: the cost center %s doesn't exist.") % (current_line_num, cost_center_code))
669+ continue
670+
671+ fp_ids = aac_obj.search(cr, uid, [('code', '=', funding_pool_code), ('category', '=', 'FUNDING'), ('type', '!=', 'view')], limit=1, context=context)
672+ if not fp_ids:
673+ errors.append(_("Line %s: the funding pool %s doesn't exist.") % (current_line_num, funding_pool_code))
674+ continue
675+
676+ dest_ids = aac_obj.search(cr, uid, [('code', '=', destination_code), ('category', '=', 'DEST'), ('type', '!=', 'view')], limit=1, context=context)
677+ if not dest_ids:
678+ errors.append(_("Line %s: the destination %s doesn't exist or is inactive.") % (current_line_num, destination_code))
679+ continue
680+
681+ current_ad = cv_line_data.analytic_distribution_id or False
682+
683+ if not current_ad or \
684+ len(current_ad.funding_pool_lines) != 1 or \
685+ current_ad.funding_pool_lines[0].analytic_id.id != fp_ids[0] or \
686+ current_ad.funding_pool_lines[0].cost_center_id.id != cc_ids[0] or \
687+ current_ad.funding_pool_lines[0].destination_id.id != dest_ids[0]:
688+
689+
690+ ad_state, ad_error = ana_obj.analytic_state_from_info(cr, uid, account.id, dest_ids[0], cc_ids[0], fp_ids[0],
691+ posting_date=wiz.commit_id.date, document_date=wiz.commit_id.date, check_analytic_active=True, context=context)
692+ if ad_state != 'valid':
693+ ad_errors.append(_("Line %s: %s/%s/%s %s" ) % (current_line_num, cost_center_code, destination_code, funding_pool_code, ad_error))
694+
695+ distrib_id = ana_obj.create(cr, uid, {'name': 'Line Distribution Import'}, context=context)
696+ ad_vals = {'distribution_id': distrib_id, 'percentage': 100.0, 'currency_id': wiz.commit_id.currency_id.id,
697+ 'destination_id': dest_ids[0]}
698+
699+ ad_vals['analytic_id'] = cc_ids[0]
700+ self.pool.get('cost.center.distribution.line').create(cr, uid, ad_vals, context=context)
701+
702+ ad_vals.update({'analytic_id': fp_ids[0], 'cost_center_id': cc_ids[0]})
703+ self.pool.get('funding.pool.distribution.line').create(cr, uid, ad_vals, context=context)
704+
705+ vals['analytic_distribution_id'] = distrib_id
706+
707+ if current_ad:
708+ ana_obj.unlink(cr, uid, [current_ad.id], context=context)
709+
710+ if vals:
711+ if 'account_id' in vals and 'analytic_distribution_id' in vals:
712+ new_ad_account += 1
713+ elif 'account_id' in vals:
714+ new_account_only += 1
715+ else:
716+ new_ad_only += 1
717+
718+ cv_line_obj.write(cr, uid, cv_line_ids, vals, context=context)
719+
720+ # update the percent
721+ if current_line_num == nb_rows:
722+ self.write(cr, uid, [wiz.id], {'progression': lines_percent}, context)
723+ elif current_line_num % 5 == 0: # refresh every 5 lines
724+ self.write(cr, uid, [wiz.id],
725+ {'progression': header_percent + (current_line_num / float(nb_rows) * (lines_percent - header_percent))},
726+ context)
727+ # cancel the process in case of errors
728+ if errors:
729+ cr.rollback()
730+ message = _('Import FAILED.')
731+ # delete old errors and create new ones
732+ error_ids = errors_obj.search(cr, uid, [], context)
733+ if error_ids:
734+ errors_obj.unlink(cr, uid, error_ids, context)
735+ for e in errors:
736+ errors_obj.create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
737+ wiz_state = 'error'
738+ # if it's AD error, handle it separately to allow import invalid AD combination
739+ elif ad_errors:
740+ message = _('Import successful but with analytic distribution invalid combination.')
741+ # delete old errors and create new ones
742+ error_ids = errors_obj.search(cr, uid, [], context)
743+ if error_ids:
744+ errors_obj.unlink(cr, uid, error_ids, context)
745+ for e in ad_errors:
746+ errors_obj.create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
747+ wiz_state = 'ad_error'
748+ else:
749+ message = _('Import successful.')
750+ wiz_state = 'done'
751+
752+ if wiz_state != 'error':
753+ change_st = _('''%s line(s) updated with a new AD and a new Account
754+%s line(s) updated with a new account only
755+%s line(s) updated with a new AD only.''') % (new_ad_account, new_account_only, new_ad_only)
756+ message = '%s\n%s' % (message, change_st)
757+
758+ # 100% progression
759+ self.write(cr, uid, ids, {'message': message, 'state': wiz_state, 'progression': 100.0}, context)
760+ cr.commit()
761+ cr.close(True)
762+ except osv.except_osv as osv_error:
763+ logging.getLogger('account.cv.import').warn('OSV Exception', exc_info=True)
764+ cr.rollback()
765+ self.write(cr, uid, ids, {'message': _("An error occurred: %s: %s") %
766+ (osv_error.name, osv_error.value), 'state': 'error', 'progression': 100.0})
767+ cr.close(True)
768+ except Exception as e:
769+ logging.getLogger('account.cv.import').warn('Exception', exc_info=True)
770+ cr.rollback()
771+ self.write(cr, uid, ids, {'message': _("An error occurred: %s") %
772+ (e and e.args and e.args[0] or ''), 'state': 'error', 'progression': 100.0})
773+ cr.close(True)
774+ return True
775+
776+ def button_validate(self, cr, uid, ids, context=None):
777+ """
778+ Starts thread and returns the wizard with the state "inprogress"
779+ """
780+ if context is None:
781+ context = {}
782+ thread = threading.Thread(target=self._import, args=(cr.dbname, uid, ids, context))
783+ thread.start()
784+ self.write(cr, uid, ids, {'state': 'inprogress'}, context)
785+ return {
786+ 'type': 'ir.actions.act_window',
787+ 'res_model': 'account.cv.import',
788+ 'view_type': 'form',
789+ 'view_mode': 'form',
790+ 'res_id': ids[0],
791+ 'context': context,
792+ 'target': 'new',
793+ }
794+
795+ def button_update(self, cr, uid, ids, context=None):
796+ """
797+ Updates the view to follow the progression
798+ """
799+ return False
800+
801+ def button_refresh_cv(self, cr, uid, ids, context=None):
802+ """
803+ Closes the wizard and refreshes the CV view
804+ """
805+ return {'type': 'ir.actions.act_window_close'}
806+
807+
808+account_cv_import()
809+
810+
811+class account_cv_import_errors(osv.osv_memory):
812+ _name = 'account.cv.import.errors'
813+
814+ _columns = {
815+ 'name': fields.text("Description", readonly=True, required=True),
816+ 'wizard_id': fields.many2one('account.cv.import', "Wizard", required=True, readonly=True),
817+ }
818+
819+
820+account_cv_import_errors()
821+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
822
823=== added file 'bin/addons/account/wizard/account_cv_import.xml'
824--- bin/addons/account/wizard/account_cv_import.xml 1970-01-01 00:00:00 +0000
825+++ bin/addons/account/wizard/account_cv_import.xml 2022-10-10 10:18:59 +0000
826@@ -0,0 +1,49 @@
827+<?xml version="1.0"?>
828+<openerp>
829+ <data>
830+
831+ <record id="wizard_account_cv_import_errors_tree" model="ir.ui.view">
832+ <field name="name">wizard.account.cv.import.errors.tree</field>
833+ <field name="model">account.cv.import.errors</field>
834+ <field name="type">tree</field>
835+ <field name="arch" type="xml">
836+ <tree string="Information">
837+ <field name="name" />
838+ </tree>
839+ </field>
840+ </record>
841+
842+ <!-- Import CV wizard -->
843+ <record model="ir.ui.view" id="wizard_account_cv_import_form">
844+ <field name='name'>wizard.account.cv.import.form</field>
845+ <field name='model'>account.cv.import</field>
846+ <field name='type'>form</field>
847+ <field name='arch' type='xml'>
848+ <form string="Import CV">
849+ <label string="Select file to import" colspan="4" align="0.0"/>
850+ <newline/>
851+ <group col="4" colspan="4">
852+ <field name="file" filename="filename" colspan="4" attrs="{'invisible': [('state', '!=', 'draft')]}"/>
853+ <field name="filename" invisible="1"/>
854+ </group>
855+ <newline />
856+ <field name="progression" widget="progressbar" nolabel="1" attrs="{'invisible': [('state', '=', 'draft')]}" colspan="4" />
857+ <field name="message" nolabel="1" attrs="{'invisible': [('state', '=', 'draft')]}" widget="text"/>
858+ <newline/>
859+ <button name="button_update" type="object" string="Update" icon="gtk-refresh" attrs="{'invisible': [('state', '!=', 'inprogress')]}"/>
860+ <newline />
861+ <field name="error_ids" nolabel="1" attrs="{'invisible': [('state', 'not in', ['error', 'ad_error'])]}"/>
862+ <group colspan="4" col="2" attrs="{'invisible': [('state', '!=', 'draft')]}">
863+ <button string="Cancel" special="cancel" icon="gtk-cancel" />
864+ <button name="button_validate" type="object" string="Import" icon="terp-camera_test"/>
865+ </group>
866+ <button name="button_refresh_cv" type="object" icon="terp-camera_test" string="Ok"
867+ attrs="{'invisible': [('state', 'not in', ['done', 'ad_error'])]}"/>
868+ <button string="Cancel" special="cancel" icon="gtk-cancel" attrs="{'invisible': [('state', '!=', 'error')]}"/>
869+ <field name="state" invisible="1"/>
870+ </form>
871+ </field>
872+ </record>
873+
874+ </data>
875+</openerp>
876
877=== modified file 'bin/addons/account/wizard/account_invoice_import.py'
878--- bin/addons/account/wizard/account_invoice_import.py 2021-10-19 14:05:56 +0000
879+++ bin/addons/account/wizard/account_invoice_import.py 2022-10-10 10:18:59 +0000
880@@ -43,7 +43,7 @@
881 'filename': fields.char(string="Imported filename", size=256),
882 'progression': fields.float(string="Progression", readonly=True),
883 'message': fields.char(string="Message", size=256, readonly=True),
884- 'state': fields.selection([('draft', 'Created'), ('inprogress', 'In Progress'), ('error', 'Error'), ('done', 'Done')],
885+ 'state': fields.selection([('draft', 'Created'), ('inprogress', 'In Progress'), ('error', 'Error'), ('ad_error', 'AD Error'), ('done', 'Done')],
886 string="State", readonly=True, required=True),
887 'error_ids': fields.one2many('account.invoice.import.errors', 'wizard_id', "Errors", readonly=True),
888 'invoice_id': fields.many2one('account.invoice', 'Invoice', required=True, readonly=True),
889@@ -69,6 +69,7 @@
890 context = {}
891 cr = pooler.get_db(dbname).cursor()
892 errors = []
893+ ad_errors = []
894 invoice_obj = self.pool.get('account.invoice')
895 invoice_line_obj = self.pool.get('account.invoice.line')
896 currency_obj = self.pool.get('res.currency')
897@@ -77,6 +78,8 @@
898 product_obj = self.pool.get('product.product')
899 import_cell_data_obj = self.pool.get('import.cell.data')
900 errors_obj = self.pool.get('account.invoice.import.errors')
901+ ana_obj = self.pool.get('analytic.distribution')
902+ aac_obj = self.pool.get('account.analytic.account')
903
904 try:
905 for wiz in self.browse(cr, uid, ids, context):
906@@ -104,6 +107,10 @@
907 'unit_price': 4,
908 'description': 5,
909 'notes': 6,
910+ 'analytic_distribution': 7,
911+ 'cost_center': 8,
912+ 'destination': 9,
913+ 'funding_pool': 10,
914 }
915 # number of the first line in the file containing data (not header)
916 base_num = 10
917@@ -168,6 +175,11 @@
918 unit_price = line[cols['unit_price']] or 0.0
919 description = line[cols['description']] and tools.ustr(line[cols['description']])
920 notes = line[cols['notes']] and tools.ustr(line[cols['notes']])
921+ analytic_distribution_type = line[cols['analytic_distribution']] and tools.ustr(line[cols['analytic_distribution']])
922+ cost_center_code = line[cols['cost_center']] and tools.ustr(line[cols['cost_center']])
923+ destination_code = line[cols['destination']] and tools.ustr(line[cols['destination']])
924+ funding_pool_code = line[cols['funding_pool']] and tools.ustr(line[cols['funding_pool']])
925+
926 if not line_number:
927 errors.append(_('Line %s: the line number is missing.') % (current_line_num,))
928 continue
929@@ -188,8 +200,7 @@
930 if not account_ids:
931 errors.append(_("Line %s: the account %s doesn't exist.") % (current_line_num, account_code))
932 continue
933- account = account_obj.browse(cr, uid, account_ids[0], fields_to_fetch=['activation_date', 'inactivation_date'],
934- context=context)
935+ account = account_obj.browse(cr, uid, account_ids[0], context=context)
936 checking_date = posting_date or datetime.now().strftime('%Y-%m-%d')
937 if checking_date < account.activation_date or (account.inactivation_date and checking_date >= account.inactivation_date):
938 errors.append(_("Line %s: the account %s is inactive.") % (current_line_num, account_code))
939@@ -235,6 +246,56 @@
940 continue
941 vals['name'] = description
942 vals['note'] = notes
943+ if account.is_analytic_addicted and analytic_distribution_type and analytic_distribution_type.strip() in ('100%', '100', '1'):
944+ if not cost_center_code or not destination_code or not funding_pool_code:
945+ errors.append(_("Line %s: An expense account is set while the analytic distribution values (mandatory) are missing.") % (current_line_num,))
946+ continue
947+ # If AD is filled - write on each line the AD on the import file. Remove from header.
948+
949+ cc_ids = aac_obj.search(cr, uid,[('code', '=', cost_center_code),('category', '=', 'OC'), ('type', '!=', 'view')],
950+ limit=1, context=context)
951+ if not cc_ids:
952+ errors.append(_("Line %s: the cost center %s doesn't exist.") % (current_line_num, cost_center_code))
953+ continue
954+
955+ fp_ids = aac_obj.search(cr, uid, [('code', '=', funding_pool_code), ('category', '=', 'FUNDING'), ('type', '!=', 'view')], limit=1, context=context)
956+ if not fp_ids:
957+ errors.append(_("Line %s: the funding pool %s doesn't exist.") % (current_line_num, funding_pool_code))
958+ continue
959+
960+ dest_ids = aac_obj.search(cr, uid, [('code', '=', destination_code), ('category', '=', 'DEST'), ('type', '!=', 'view')], limit=1, context=context)
961+ if not dest_ids:
962+ errors.append(_("Line %s: the destination %s doesn't exist.") % (current_line_num, destination_code))
963+ continue
964+
965+ current_ad = invoice_line_obj.browse(cr, uid, invoice_line_ids[0],fields_to_fetch=['analytic_distribution_id'], context=context).analytic_distribution_id
966+
967+ # create a new AD if diff from current AD on line
968+ if not current_ad or \
969+ len(current_ad.funding_pool_lines) != 1 or \
970+ current_ad.funding_pool_lines[0].analytic_id.id != fp_ids[0] or \
971+ current_ad.funding_pool_lines[0].cost_center_id.id != cc_ids[0] or \
972+ current_ad.funding_pool_lines[0].destination_id.id != dest_ids[0]:
973+
974+ ad_state, ad_error = ana_obj.analytic_state_from_info(cr, uid, account.id, dest_ids[0], cc_ids[0], fp_ids[0],
975+ posting_date=checking_date, document_date=invoice.document_date, check_analytic_active=True, context=context)
976+ if ad_state != 'valid':
977+ ad_errors.append(_("Line %s: %s/%s/%s %s" ) % (current_line_num, cost_center_code, destination_code, funding_pool_code, ad_error))
978+
979+ distrib_id = ana_obj.create(cr, uid, {'name': 'Line Distribution Import'}, context=context)
980+ ad_vals = {'distribution_id': distrib_id, 'percentage': 100.0, 'currency_id': currency_ids[0],
981+ 'destination_id': dest_ids[0]}
982+
983+ ad_vals['analytic_id'] = cc_ids[0]
984+ self.pool.get('cost.center.distribution.line').create(cr, uid, ad_vals, context=context)
985+
986+ ad_vals.update({'analytic_id': fp_ids[0], 'cost_center_id': cc_ids[0]})
987+ self.pool.get('funding.pool.distribution.line').create(cr, uid, ad_vals, context=context)
988+
989+ vals['analytic_distribution_id'] = distrib_id
990+
991+ if current_ad:
992+ ana_obj.unlink(cr, uid, [current_ad.id], context=context)
993
994 # update the line
995 invoice_line_obj.write(cr, uid, invoice_line_ids[0], vals, context=context)
996@@ -257,6 +318,16 @@
997 for e in errors:
998 errors_obj.create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
999 wiz_state = 'error'
1000+ # if it's AD error, handle it separately to allow import invalid AD combination
1001+ elif ad_errors:
1002+ message = _('Import successful but with analytic distribution invalid combination.')
1003+ # delete old errors and create new ones
1004+ error_ids = errors_obj.search(cr, uid, [], context)
1005+ if error_ids:
1006+ errors_obj.unlink(cr, uid, error_ids, context)
1007+ for e in ad_errors:
1008+ errors_obj.create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
1009+ wiz_state = 'ad_error'
1010 else:
1011 message = _('Import successful.')
1012 # 100% progression
1013
1014=== modified file 'bin/addons/account/wizard/account_invoice_import.xml'
1015--- bin/addons/account/wizard/account_invoice_import.xml 2020-04-21 09:34:06 +0000
1016+++ bin/addons/account/wizard/account_invoice_import.xml 2022-10-10 10:18:59 +0000
1017@@ -32,13 +32,13 @@
1018 <newline/>
1019 <button name="button_update" type="object" string="Update" icon="gtk-refresh" attrs="{'invisible': [('state', '!=', 'inprogress')]}"/>
1020 <newline />
1021- <field name="error_ids" nolabel="1" attrs="{'invisible': [('state', '!=', 'error')]}"/>
1022+ <field name="error_ids" nolabel="1" attrs="{'invisible': [('state', 'not in', ['error', 'ad_error'])]}"/>
1023 <group colspan="4" col="2" attrs="{'invisible': [('state', '!=', 'draft')]}">
1024 <button string="Cancel" special="cancel" icon="gtk-cancel"/>
1025 <button name="button_validate" type="object" string="Import" icon="terp-camera_test"/>
1026 </group>
1027 <button name="button_refresh_invoice" type="object" icon="terp-camera_test" string="Ok"
1028- attrs="{'invisible': [('state', '!=', 'done')]}"/>
1029+ attrs="{'invisible': [('state', 'not in', ['done', 'ad_error'])]}"/>
1030 <field name="state" invisible="1"/>
1031 </form>
1032 </field>
1033
1034=== modified file 'bin/addons/analytic_distribution/account_commitment.py'
1035--- bin/addons/analytic_distribution/account_commitment.py 2022-04-11 16:00:04 +0000
1036+++ bin/addons/analytic_distribution/account_commitment.py 2022-10-10 10:18:59 +0000
1037@@ -37,6 +37,33 @@
1038 _order = "id desc"
1039 _trace = True
1040
1041+ def import_cv(self, cr, uid, ids, data, context=None):
1042+ """
1043+ Opens the Import CV wizard
1044+ """
1045+ if isinstance(ids, (int, long)):
1046+ ids = [ids]
1047+ wiz_id = self.pool.get('account.cv.import').create(cr, uid, {'commit_id': ids[0]}, context=context)
1048+ return {
1049+ 'name': _('Import CV'),
1050+ 'type': 'ir.actions.act_window',
1051+ 'res_model': 'account.cv.import',
1052+ 'target': 'new',
1053+ 'view_mode': 'form,tree',
1054+ 'view_type': 'form',
1055+ 'res_id': [wiz_id],
1056+ }
1057+
1058+ def export_cv(self, cr, uid, ids, data, context=None):
1059+ """
1060+ Opens the Export CV report
1061+ """
1062+ return {
1063+ 'type': 'ir.actions.report.xml',
1064+ 'report_name': 'account.export_cv',
1065+ 'datas': data,
1066+ }
1067+
1068 def _get_total(self, cr, uid, ids, name, args, context=None):
1069 """
1070 Give total of given commitments
1071@@ -83,11 +110,11 @@
1072 """
1073 Returns the list of possible types for the Commitment Vouchers
1074 """
1075- return [('manual', 'Manual'),
1076- ('external', 'Automatic - External supplier'),
1077- ('esc', 'Manual - ESC supplier'),
1078- ('intermission', 'Automatic - Intermission'),
1079- ('intersection', 'Automatic - Intersection'),
1080+ return [('manual', _('Manual')),
1081+ ('external', _('Automatic - External supplier')),
1082+ ('esc', _('Manual - ESC supplier')),
1083+ ('intermission', _('Automatic - Intermission')),
1084+ ('intersection', _('Automatic - Intersection')),
1085 ]
1086
1087 def get_current_cv_version(self, cr, uid, context=None):
1088
1089=== modified file 'bin/addons/analytic_distribution/account_commitment_view.xml'
1090--- bin/addons/analytic_distribution/account_commitment_view.xml 2022-04-11 16:00:04 +0000
1091+++ bin/addons/analytic_distribution/account_commitment_view.xml 2022-10-10 10:18:59 +0000
1092@@ -39,6 +39,13 @@
1093 <field name="analytic_distribution_id" invisible="1"/>
1094 <notebook colspan="4">
1095 <page string="Commitment voucher lines">
1096+ <group name="import" string=" Import Lines " colspan="4" col="4"
1097+ attrs="{'invisible': [('state', '!=', 'draft')]}">
1098+ <button name="import_cv" string="Import CV Lines" icon="gtk-execute" colspan="2" type="object"
1099+ attrs="{'readonly': [('state', '!=', 'draft')]}"/>
1100+ <button name="export_cv" string="Export CV Lines" icon="gtk-execute" colspan="2" type="object"/>
1101+ <newline/>
1102+ </group>
1103 <field name="line_ids" nolabel="1" colspan="4"
1104 attrs="{'readonly': ['|', ('state', '=', 'done'),
1105 '&amp;',
1106
1107=== modified file 'bin/addons/analytic_distribution/analytic_distribution.py'
1108--- bin/addons/analytic_distribution/analytic_distribution.py 2021-12-15 17:17:49 +0000
1109+++ bin/addons/analytic_distribution/analytic_distribution.py 2022-10-10 10:18:59 +0000
1110@@ -214,7 +214,7 @@
1111 return 'invalid'
1112 return 'valid'
1113
1114- def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, posting_date=False, context=None):
1115+ def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, posting_date=False, document_date=False, check_analytic_active=False, context=None):
1116 """
1117 Give analytic state from the given information.
1118 Return result and some info if needed.
1119@@ -227,8 +227,19 @@
1120 info = ''
1121 dest_cc_link_obj = self.pool.get('dest.cc.link')
1122 account = self.pool.get('account.account').browse(cr, uid, account_id, context=context)
1123+ analytic_acc_obj = self.pool.get('account.analytic.account')
1124 # DISTRIBUTION VERIFICATION
1125 # Check that destination is compatible with account
1126+ if check_analytic_active:
1127+ for aa in analytic_acc_obj.browse(cr, uid, [destination_id, cost_center_id, analytic_id], context=context):
1128+ if aa.category == 'FUNDING':
1129+ date_check = document_date or time.strftime('%Y-%m-%d')
1130+ else:
1131+ date_check = posting_date or time.strftime('%Y-%m-%d')
1132+
1133+ if not analytic_acc_obj.is_account_active(aa, date_check):
1134+ return 'invalid', _('Account %s is inactive on %s') % (aa.code, date_check)
1135+
1136 if destination_id not in [x.id for x in account.destination_ids]:
1137 return 'invalid', _('Destination not compatible with account')
1138 # Check that Destination and Cost Center are compatible
1139
1140=== modified file 'bin/addons/base/ir/ir_model.py'
1141--- bin/addons/base/ir/ir_model.py 2021-11-25 15:59:15 +0000
1142+++ bin/addons/base/ir/ir_model.py 2022-10-10 10:18:59 +0000
1143@@ -476,7 +476,10 @@
1144 sel = {}
1145
1146 if field in pool_obj._columns and hasattr(pool_obj._columns[field], 'selection'):
1147- sel = dict(pool_obj._columns[field].selection)
1148+ if callable(pool_obj._columns[field].selection):
1149+ sel = dict(pool_obj._columns[field].selection(pool_obj, cr, uid, context))
1150+ else:
1151+ sel = dict(pool_obj._columns[field].selection)
1152 elif field in pool_obj._inherit_fields and hasattr(pool_obj._inherit_fields[field][2], 'selection'):
1153 sel = dict(pool_obj._inherit_fields[field][2].selection)
1154 if callable(sel):
1155
1156=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
1157--- bin/addons/msf_profile/i18n/fr_MF.po 2022-10-07 08:02:51 +0000
1158+++ bin/addons/msf_profile/i18n/fr_MF.po 2022-10-10 10:18:59 +0000
1159@@ -3428,8 +3428,9 @@
1160 msgid "Update Terms"
1161 msgstr "Mise à jour des termes"
1162
1163-#. module: analytic_distribution
1164+#. module: analytic_distribution, account
1165 #: field:account.commitment,date:0
1166+#: report:addons/account/report/export_cv.mako:109
1167 msgid "Commitment Date"
1168 msgstr "Date d'Engagement"
1169
1170@@ -3935,6 +3936,7 @@
1171 #: selection:account.commitment.line,commit_type:0
1172 #: selection:purchase.order,invoice_method:0
1173 #: model:ir.ui.menu,name:sync_client.sync_wiz_menu
1174+#: code:addons/analytic_distribution/account_commitment.py:114
1175 msgid "Manual"
1176 msgstr "Manuel"
1177
1178@@ -5934,6 +5936,8 @@
1179 #: report:order.type.donation.certificate:0
1180 #: report:addons/product/report/product_mass_update_export_xls.mako:118
1181 #: field:msf.accrual.line.expense,description:0
1182+#: field:account.cv.import.errors,name:0
1183+#: report:addons/account/report/export_cv.mako:121
1184 #, python-format
1185 msgid "Description"
1186 msgstr "Description"
1187@@ -8733,6 +8737,7 @@
1188 #: field:hr.payroll.import,filename:0
1189 #: field:wizard.register.import,filename:0
1190 #: field:account.invoice.import,filename:0
1191+#: field:account.cv.import,filename:0
1192 msgid "Imported filename"
1193 msgstr "Nom du fichier importé"
1194
1195@@ -9702,6 +9707,7 @@
1196 #. module: analytic_distribution
1197 #: selection:account.commitment,type:0
1198 #: selection:account.commitment.line,commit_type:0
1199+#: code:addons/analytic_distribution/account_commitment.py:116
1200 msgid "Manual - ESC supplier"
1201 msgstr "Manuel - Fournisseur ESC"
1202
1203@@ -10865,6 +10871,7 @@
1204 #: field:purchase.order,origin:0
1205 #: field:wizard.account.invoice,origin:0
1206 #: code:addons/msf_supply_doc_export/msf_supply_doc_export.py:914
1207+#: report:addons/account/report/export_cv.mako:129
1208 msgid "Source Document"
1209 msgstr "Document d'origine"
1210
1211@@ -15526,6 +15533,7 @@
1212 #: field:change.dest.location,type:0
1213 #: code:addons/consumption_calculation/history_consumption.py:719
1214 #: field:msf_button_access_rights.button_access_rule,bar_type:0
1215+#: report:addons/account/report/export_cv.mako:137
1216 msgid "Type"
1217 msgstr "Type"
1218
1219@@ -19979,6 +19987,7 @@
1220 #: field:wizard.import.batch,progression:0
1221 #: field:wizard.register.import,progression:0
1222 #: field:account.invoice.import,progression:0
1223+#: field:account.cv.import,progression:0
1224 msgid "Progression"
1225 msgstr "Progression"
1226
1227@@ -20830,11 +20839,12 @@
1228 msgid "Etc/GMT-11"
1229 msgstr "Etc/GMT-11"
1230
1231-#. modules: sales_followup, msf_tools, procurement_cycle, msf_doc_import
1232+#. modules: sales_followup, msf_tools, procurement_cycle, msf_doc_import, account
1233 #: selection:ir.followup.location.wizard,state:0
1234 #: selection:job.in_progress,state:0
1235 #: selection:replenishment.consolidated_oc.import,state:0
1236 #: selection:wizard.import.ad.line,state:0
1237+#: selection:account.cv.import,state:0
1238 msgid "Done"
1239 msgstr "Clôturé"
1240
1241@@ -25086,6 +25096,7 @@
1242 #: report:addons/account/report/free_allocation_report.mako:171
1243 #: field:free.allocation.wizard,period_id:0
1244 #: selection:integrity.finance.wizard,filter:0
1245+#: report:addons/account/report/export_cv.mako:133
1246 #, python-format
1247 msgid "Period"
1248 msgstr "Période"
1249@@ -30255,6 +30266,7 @@
1250 #: field:wizard.import.ad.line,message:0
1251 #: field:wizard.return.from.unit.import,message:0
1252 #: field:product.mass.update,message:0
1253+#: field:account.cv.import,message:0
1254 msgid "Message"
1255 msgstr "Message"
1256
1257@@ -32131,8 +32143,12 @@
1258 #: selection:wizard.register.opening.confirmation,register_type:0
1259 #: selection:account.invoice,journal_type:0
1260 #: selection:wizard.account.invoice,journal_type:0
1261+<<<<<<< TREE
1262 #: selection:account.analytic.line,journal_type:0
1263 #: selection:account.analytic.journal,type:0
1264+=======
1265+#: selection:account.analytic.journal,type:0
1266+>>>>>>> MERGE-SOURCE
1267 msgid "Depreciation"
1268 msgstr "Depreciation"
1269
1270@@ -37956,6 +37972,8 @@
1271 #: report:addons/account/report/free_allocation_report.mako:208
1272 #: view:account.destination.summary:0
1273 #: field:wizard.account.invoice.line,funding_pool_id:0
1274+#: report:addons/account/report/export_cv.mako:152
1275+#: report:addons/account/report/export_invoice.mako:150
1276 #, python-format
1277 msgid "Funding Pool"
1278 msgstr "Funding Pool"
1279@@ -42132,6 +42150,7 @@
1280 #: view:sync.client.update_entity:0
1281 #: view:stock.expired.damaged.report:0
1282 #: view:account.invoice.import:0
1283+#: view:account.cv.import:0
1284 msgid "Update"
1285 msgstr "Mettre à jour"
1286
1287@@ -43461,6 +43480,7 @@
1288 #: view:account.invoice.import.errors:0
1289 #: view:wizard.import.ppl.to.create.ship:0
1290 #: view:wizard.import.product.line:0
1291+#: view:account.cv.import.errors:0
1292 msgid "Information"
1293 msgstr "Informations"
1294
1295@@ -44397,12 +44417,13 @@
1296 msgid "For action: is selection of records needed ?"
1297 msgstr "Action requise : une sélection des livres est-il requise ?"
1298
1299-#. modules: analytic_distribution, finance
1300+#. modules: analytic_distribution, finance, account
1301 #: view:account.commitment:0
1302 #: field:account.commitment.line,commit_id:0
1303 #: field:analytic.distribution.wizard,commitment_id:0
1304 #: model:ir.ui.menu,name:analytic_distribution.menu_commitment_entries
1305 #: model:ir.actions.act_window,name:finance.account_board_commitment_voucher
1306+#: field:account.cv.import,commit_id:0
1307 msgid "Commitment Voucher"
1308 msgstr "Bons d'Engagement"
1309
1310@@ -45179,6 +45200,7 @@
1311 #: field:warning.import.currencies.lines,wizard_id:0
1312 #: field:sale.order.leave.close,wizard_id:0
1313 #: field:account.invoice.import.errors,wizard_id:0
1314+#: field:account.cv.import.errors,wizard_id:0
1315 msgid "Wizard"
1316 msgstr "Assistant"
1317
1318@@ -50568,7 +50590,7 @@
1319 msgid "Indian/Mayotte"
1320 msgstr "Indien/Mayotte"
1321
1322-#. modules: purchase, register_accounting, supplier_catalogue, sale, account_override, msf_doc_import, product
1323+#. modules: purchase, register_accounting, supplier_catalogue, sale, account_override, msf_doc_import, product, analytic_distribution
1324 #: view:account.invoice:0
1325 #: view:composition.kit:0
1326 #: view:initial.stock.inventory:0
1327@@ -50587,6 +50609,7 @@
1328 #: view:sale.order:0
1329 #: view:supplier.catalogue:0
1330 #: view:product.mass.update:0
1331+#: view:account.commitment:0
1332 msgid " Import Lines "
1333 msgstr "Importer les Lignes"
1334
1335@@ -53849,6 +53872,7 @@
1336 #: report:account.employee_ledger_other:0
1337 #: report:addons/account/report/account_employee_ledger.mako:306
1338 #: report:addons/finance/report/account_employee_balance_tree_xls.mako:342
1339+#: report:addons/account/report/export_cv.mako:146
1340 #, python-format
1341 msgid "Account"
1342 msgstr "Compte"
1343@@ -57586,6 +57610,7 @@
1344 #: view:stock.picking:0
1345 #: model:ir.model,name:sync_so.model_account_journal
1346 #: report:addons/account/report/export_invoice.mako:92
1347+#: report:addons/account/report/export_cv.mako:101
1348 #, python-format
1349 msgid "Journal"
1350 msgstr "Journal"
1351@@ -61588,7 +61613,7 @@
1352 msgid "Some of the lines of the Accrual \"%s\" have no analytic distribution!"
1353 msgstr "Certaines lignes de la Régularisation \"%s\" n'ont pas de distribution analytique !"
1354
1355-#. modules: purchase, register_accounting, analytic_distribution_supply, account_corrections, account_subscription, analytic_override, analytic_distribution
1356+#. modules: purchase, register_accounting, analytic_distribution_supply, account_corrections, account_subscription, analytic_override, analytic_distribution, account
1357 #: field:wizard.journal.items.corrections.lines,analytic_distribution_id:0
1358 #: field:account.model,analytic_distribution_id:0
1359 #: field:account.model.line,analytic_distribution_id:0
1360@@ -61605,6 +61630,8 @@
1361 #: field:wizard.account.invoice,analytic_distribution_id:0
1362 #: field:wizard.account.invoice.line,analytic_distribution_id:0
1363 #: field:wizard.advance.line,analytic_distribution_id:0
1364+#: report:addons/account/report/export_cv.mako:149
1365+#: report:addons/account/report/export_invoice.mako:147
1366 msgid "Analytic Distribution"
1367 msgstr "Allocation Analytique"
1368
1369@@ -64874,6 +64901,7 @@
1370 #: report:addons/msf_supply_doc_export/report/supplier_performance_report_xls.mako:232
1371 #: report:addons/account/report/invoice_excel_export.mako:65
1372 #: report:addons/account/report/export_invoice.mako:119
1373+#: report:addons/account/report/export_cv.mako:145
1374 #, python-format
1375 msgid "Line number"
1376 msgstr "Numéro de ligne"
1377@@ -68919,6 +68947,7 @@
1378 #: selection:sync.client.log_sale_purchase,action_type:0
1379 #: code:addons/msf_supply_doc_export/msf_supply_doc_export.py:896
1380 #: selection:account.invoice.import,state:0
1381+#: selection:account.cv.import,state:0
1382 msgid "Created"
1383 msgstr "Créé"
1384
1385@@ -69903,18 +69932,21 @@
1386 #. module: analytic_distribution
1387 #: selection:account.commitment,type:0
1388 #: selection:account.commitment.line,commit_type:0
1389+#: code:addons/analytic_distribution/account_commitment.py:115
1390 msgid "Automatic - External supplier"
1391 msgstr "Automatique - Fournisseur Externe"
1392
1393 #. module: analytic_distribution
1394 #: selection:account.commitment,type:0
1395 #: selection:account.commitment.line,commit_type:0
1396+#: code:addons/analytic_distribution/account_commitment.py:117
1397 msgid "Automatic - Intermission"
1398 msgstr "Automatique - Intermission"
1399
1400 #. module: analytic_distribution
1401 #: selection:account.commitment,type:0
1402 #: selection:account.commitment.line,commit_type:0
1403+#: code:addons/analytic_distribution/account_commitment.py:118
1404 msgid "Automatic - Intersection"
1405 msgstr "Automatique - Intersection"
1406
1407@@ -73815,6 +73847,7 @@
1408 #: selection:wizard.import.ir.line,state:0
1409 #: selection:wizard.import.po.line,state:0
1410 #: selection:wizard.import.tender.line,state:0
1411+#: selection:account.cv.import,state:0
1412 #, python-format, python-format
1413 msgid "Error"
1414 msgstr "Erreur"
1415@@ -74267,6 +74300,7 @@
1416 #: field:msf.import.export,error_message:0
1417 #: code:addons/sourcing/wizard/multiple_sourcing.py:252
1418 #: field:account.invoice.import,error_ids:0
1419+#: field:account.cv.import,error_ids:0
1420 #, python-format
1421 msgid "Errors"
1422 msgstr "Erreurs"
1423@@ -74417,6 +74451,7 @@
1424 #: selection:res.request,ref_doc2:0
1425 #: view:account.direct.invoice.wizard:0
1426 #: field:account.invoice.import,invoice_id:0
1427+#: field:account.cv.import,invoice_id:0
1428 msgid "Invoice"
1429 msgstr "Facture"
1430
1431@@ -76141,6 +76176,7 @@
1432 #. modules: register_accounting, account
1433 #: view:wizard.register.import:0
1434 #: view:account.invoice.import:0
1435+#: view:account.cv.import:0
1436 msgid "Select file to import"
1437 msgstr "Sélectionner le fichier à importer"
1438
1439@@ -81234,6 +81270,8 @@
1440 #: code:addons/msf_doc_import/wizard/wizard_po_simulation_screen.py:606
1441 #: field:wizard.account.invoice.line,cost_center_id:0
1442 #: field:dest.cc.link,cc_id:0
1443+#: report:addons/account/report/export_cv.mako:150
1444+#: report:addons/account/report/export_invoice.mako:148
1445 #, python-format
1446 msgid "Cost Center"
1447 msgstr "Centre de Coût"
1448@@ -81358,6 +81396,7 @@
1449 #: view:product.stock_out:0
1450 #: view:replenishment.consolidated_oc.import:0
1451 #: view:wizard.import.ad.line:0
1452+#: view:account.cv.import:0
1453 msgid "Import"
1454 msgstr "Importer"
1455
1456@@ -82063,6 +82102,7 @@
1457 #: field:wizard.import.ad.line,state:0
1458 #: field:supplier.performance.wizard,state:0
1459 #: field:msf.accrual.line,state:0
1460+#: field:account.cv.import,state:0
1461 #, python-format
1462 msgid "State"
1463 msgstr "Statut"
1464@@ -83270,6 +83310,7 @@
1465 #: field:hr.payroll.import,file:0
1466 #: field:wizard.register.import,file:0
1467 #: field:account.invoice.import,file:0
1468+#: field:account.cv.import,file:0
1469 msgid "File"
1470 msgstr "Fichier"
1471
1472@@ -83952,7 +83993,7 @@
1473 msgid "Sourced-n line"
1474 msgstr "Ligne sourcée-n"
1475
1476-#. modules: analytic_distribution, sales_followup, register_accounting, reason_types_moves, msf_homere_interface, stock_override, consumption_calculation, sale, specific_rules, order_types, msf_tools, mission_stock, msf_doc_import, stock, product, acccount, msf_supply_doc_export
1477+#. modules: analytic_distribution, sales_followup, register_accounting, reason_types_moves, msf_homere_interface, stock_override, consumption_calculation, sale, specific_rules, order_types, msf_tools, mission_stock, msf_doc_import, stock, product, acccount, msf_supply_doc_export, account
1478 #: field:import.commitment.wizard,in_progress:0
1479 #: view:product.history.consumption:0
1480 #: selection:product.history.consumption,fake_status:0
1481@@ -84001,6 +84042,7 @@
1482 #: selection:stock.pipe.per.product.instance,state:0
1483 #: selection:wizard.import.ad.line,state:0
1484 #: selection:supplier.performance.wizard,state:0
1485+#: selection:account.cv.import,state:0
1486 #, python-format
1487 msgid "In Progress"
1488 msgstr "En cours"
1489@@ -86125,6 +86167,7 @@
1490 #: report:addons/msf_supply_doc_export/report/supplier_performance_report_xls.mako:228
1491 #: view:account.commitment:0
1492 #: selection:account.commitment,cv_flow_type:0
1493+#: report:addons/account/report/export_cv.mako:125
1494 #, python-format
1495 msgid "Supplier"
1496 msgstr "Fournisseur"
1497@@ -91372,6 +91415,7 @@
1498 #. modules: account, register_accounting
1499 #: report:cash.inventory:0
1500 #: field:account.cashbox.line,number:0
1501+#: report:addons/account/report/export_cv.mako:105
1502 msgid "Number"
1503 msgstr "Nombre"
1504
1505@@ -91937,7 +91981,7 @@
1506 msgid "Purchase Orders Waiting Confirmation"
1507 msgstr "Bons de Commandes en attente de Confirmation"
1508
1509-#. modules: purchase, analytic_distribution, purchase_override, account_override, register_accounting, sale
1510+#. modules: purchase, analytic_distribution, purchase_override, account_override, register_accounting, sale, account
1511 #: field:account.commitment,line_ids:0
1512 #: view:account.commitment.line:0
1513 #: field:purchase.order.line,cv_line_ids:0
1514@@ -91945,6 +91989,7 @@
1515 #: field:account.invoice.line,cv_line_ids:0
1516 #: field:wizard.account.invoice.line,cv_line_ids:0
1517 #: field:sale.order.line,cv_line_ids:0
1518+#: report:addons/account/report/export_cv.mako:144
1519 msgid "Commitment Voucher Lines"
1520 msgstr "Lignes de Bon d'Engagement"
1521
1522@@ -93277,6 +93322,7 @@
1523 #: report:account.employee_ledger_other:0
1524 #: report:addons/account/report/account_employee_ledger.mako:315
1525 #: report:addons/finance/report/account_employee_balance_tree_xls.mako:345
1526+#: report:addons/account/report/export_cv.mako:117
1527 #, python-format
1528 msgid "Currency"
1529 msgstr "Devise"
1530@@ -95339,6 +95385,8 @@
1531 #: field:sync.trigger.something.target,destination:0
1532 #: field:sync.trigger.something.target.lower,destination:0
1533 #: field:wizard.account.invoice.line,destination_id:0
1534+#: report:addons/account/report/export_cv.mako:151
1535+#: report:addons/account/report/export_invoice.mako:149
1536 #, python-format
1537 msgid "Destination"
1538 msgstr "Destination"
1539@@ -96947,6 +96995,7 @@
1540 #: view:modify.responsible:0
1541 #: view:account.employee.ledger:0
1542 #: view:wizard.account.employee.balance.tree:0
1543+#: view:account.cv.import:0
1544 #, python-format
1545 msgid "Cancel"
1546 msgstr "Annuler"
1547@@ -98148,6 +98197,7 @@
1548 #: code:addons/msf_outgoing/__init__.py:26
1549 #: view:wizard.common.import.line:0
1550 #: selection:stock.move.in.processor,sequence_issue:0
1551+#: view:account.cv.import:0
1552 msgid "Ok"
1553 msgstr "Ok"
1554
1555@@ -109658,6 +109708,7 @@
1556 #. module: account
1557 #: report:addons/account/report/invoice_excel_export.mako:56
1558 #: report:addons/account/report/export_invoice.mako:80
1559+#: report:addons/account/report/export_cv.mako:92
1560 msgid "Sheet"
1561 msgstr "Feuille"
1562
1563@@ -115702,6 +115753,199 @@
1564 msgid "You can not select 'Import Products' on a Project instance"
1565 msgstr "Impossible de sélectionner 'Importer Produits' sur une instance Projet"
1566
1567+#. module: account
1568+#: selection:account.cv.import,state:0
1569+#: selection:account.invoice.import,state:0
1570+msgid "AD Error"
1571+msgstr "Erreur de distribution analytique"
1572+
1573+#. module: account
1574+#: code:addons/account/wizard/account_cv_import.py:161
1575+#, python-format
1576+msgid "CV type '%s' not found or doesn't exist."
1577+msgstr "Type de bon d'engagement '%s' non trouvé ou n'existe pas."
1578+
1579+#. module: account
1580+#: code:addons/account/wizard/account_cv_import.py:114
1581+#, python-format
1582+msgid "CV with number: %s not found."
1583+msgstr "Bon d'engagement avec numéro: %s non trouvé."
1584+
1585+#. module: account
1586+#: report:addons/account/report/export_cv.mako:9
1587+#: model:ir.actions.report.xml,name:account.export_cv
1588+msgid "Export - CV"
1589+msgstr "Export - Bon d'Engagement"
1590+
1591+#. module: analytic_distribution
1592+#: view:account.commitment:0
1593+msgid "Export CV Lines"
1594+msgstr "Exporter les lignes de bon d'engagement"
1595+
1596+#. modules: account, analytic_distribution
1597+#: view:account.cv.import:0
1598+#: code:addons/analytic_distribution/account_commitment.py:48
1599+#, python-format
1600+msgid "Import CV"
1601+msgstr "Import de bon d'engagement"
1602+
1603+#. module: analytic_distribution
1604+#: view:account.commitment:0
1605+msgid "Import CV Lines"
1606+msgstr "Importer les lignes de bon d'engagement"
1607+
1608+#. module: account
1609+#: code:addons/account/wizard/account_cv_import.py:331
1610+#: code:addons/account/wizard/account_invoice_import.py:329
1611+#, python-format
1612+msgid "Import successful but with analytic distribution invalid combination."
1613+msgstr "Succès de l'import mais avec une combinaison invalide de distribution analytique."
1614+
1615+#. module: account
1616+#: report:addons/account/report/export_cv.mako:147
1617+msgid "Initial Amount"
1618+msgstr "Montant Initial"
1619+
1620+#. module: account
1621+#: report:addons/account/report/export_cv.mako:148
1622+msgid "Left Amount"
1623+msgstr "Montant restant."
1624+
1625+#. module: account
1626+#: code:addons/account/wizard/account_cv_import.py:255
1627+#: code:addons/account/wizard/account_invoice_import.py:255
1628+#, python-format
1629+msgid "Line %s: An expense account is set while the analytic distribution values (mandatory) are missing."
1630+msgstr "Ligne %s: Un compte de charge a été renseigné alors que les valeurs de distribution analytique (obligatoires) sont manquantes."
1631+
1632+#. module: account
1633+#: code:addons/account/wizard/account_cv_import.py:208
1634+#, python-format
1635+msgid "Line %s: empty account code field is not allowed."
1636+msgstr "Ligne %s: le code du compte doit être renseigné obligatoirement."
1637+
1638+#. module: account
1639+#: code:addons/account/wizard/account_cv_import.py:215
1640+#, python-format
1641+msgid "Line %s: the account %s does not exist or inactive or mistyped."
1642+msgstr "Ligne %s: le compte %s soit n'existe pas, soit est inactif, soit a été mal tapé."
1643+
1644+#. module: account
1645+#: code:addons/account/wizard/account_cv_import.py:286
1646+#: code:addons/account/wizard/account_cv_import.py:289
1647+#: code:addons/account/wizard/account_cv_import.py:292
1648+#: code:addons/account/wizard/account_invoice_import.py:287
1649+#: code:addons/account/wizard/account_invoice_import.py:290
1650+#: code:addons/account/wizard/account_invoice_import.py:293
1651+#, python-format
1652+msgid "Line %s: the combination %s/%s is not valid."
1653+msgstr "Ligne %s: la combinaison %s/%s n'est pas valide."
1654+
1655+#. module: account
1656+#: code:addons/account/wizard/account_cv_import.py:248
1657+#, python-format
1658+msgid "Line %s: the combination product code: %s, line number: %s, initial amount: %s,left amount: %s doesn't exist in the commitment voucher."
1659+msgstr "Ligne %s: la combinaison code produit: %s, numéro de ligne: %s, montant initial: %s, montant restant: %s n'existe pas dans le bon d'engagement courant."
1660+
1661+#. module: account
1662+#: code:addons/account/wizard/account_cv_import.py:272
1663+#: code:addons/account/wizard/account_invoice_import.py:273
1664+#, python-format
1665+msgid "Line %s: the cost center %s doesn't exist or is inactive."
1666+msgstr "Ligne %s: le centre de coût %s n'existe pas ou est inactif."
1667+
1668+#. module: account
1669+#: code:addons/account/wizard/account_cv_import.py:282
1670+#: code:addons/account/wizard/account_invoice_import.py:283
1671+#, python-format
1672+msgid "Line %s: the destination %s doesn't exist or is inactive."
1673+msgstr "Ligne %s: la destination %s n'existe pas ou est inactive."
1674+
1675+#. module: account
1676+#: code:addons/account/wizard/account_cv_import.py:277
1677+#: code:addons/account/wizard/account_invoice_import.py:278
1678+#, python-format
1679+msgid "Line %s: the funding pool %s doesn't exist or is inactive."
1680+msgstr "Ligne %s: le funding pool %s n'existe pas ou est inactif."
1681+
1682+#. module: account
1683+#: code:addons/account/wizard/account_cv_import.py:227
1684+#, python-format
1685+msgid "Line %s: the initial amount format is incorrect."
1686+msgstr "Ligne %s: le format du montant initial est incorrect."
1687+
1688+#. module: account
1689+#: code:addons/account/wizard/account_cv_import.py:233
1690+#, python-format
1691+msgid "Line %s: the left amount format is incorrect."
1692+msgstr "Ligne %s: le format du montant restant est incorrect."
1693+
1694+#. module: account
1695+#: code:addons/account/wizard/account_cv_import.py:205
1696+#, python-format
1697+msgid "Line %s: the line number %s doesn't exist in the commitment voucher."
1698+msgstr "Ligne %s: le numéro de ligne %s n'existe pas dans le bon d'engagement courant."
1699+
1700+#. module: account
1701+#: code:addons/account/wizard/account_cv_import.py:238
1702+#, python-format
1703+msgid "Line %s: the line product code is missing."
1704+msgstr "Ligne %s: le code produit est manquant"
1705+
1706+#. module: account
1707+#: code:addons/account/wizard/account_cv_import.py:242
1708+#, python-format
1709+msgid "Line %s: the product %s doesn't exist."
1710+msgstr "Ligne %s: le produit %s n'existe pas."
1711+
1712+#. module: account
1713+#: code:addons/account/wizard/account_cv_import.py:111
1714+#, python-format
1715+msgid "No CV number found."
1716+msgstr "Pas de numéro de bon d'engagement trouvé."
1717+
1718+#. module: account
1719+#: code:addons/account/wizard/account_cv_import.py:157
1720+#, python-format
1721+msgid "No CV type found."
1722+msgstr "Pas de type de bon d'engagement trouvé."
1723+
1724+#. module: account
1725+#: code:addons/account/wizard/account_cv_import.py:148
1726+#, python-format
1727+msgid "No source document found."
1728+msgstr "Pas de bon de commande source trouvé."
1729+
1730+#. module: account
1731+#: code:addons/account/wizard/account_cv_import.py:139
1732+#, python-format
1733+msgid "No supplier found."
1734+msgstr "Pas de fournisseur trouvé."
1735+
1736+#. module: account
1737+#: code:addons/account/wizard/account_cv_import.py:151
1738+#, python-format
1739+msgid "Source document %s not found or inactive."
1740+msgstr "Le bon de commande source %s n'a pas été trouvé ou est inactif."
1741+
1742+#. module: account
1743+#: code:addons/account/wizard/account_cv_import.py:143
1744+#, python-format
1745+msgid "Supplier %s not found or inactive."
1746+msgstr "Fournisseur %s n'a pas été trouvé ou est inactif."
1747+
1748+#. module: account
1749+#: code:addons/account/wizard/account_cv_import.py:166
1750+#, python-format
1751+msgid "The combination \"CV Number, Currency, Supplier, Source Document and CV Type\" of the imported file doesn't match with the current commitment voucher."
1752+msgstr "La combinaison \"Numéro, Devise, Fournisseur, Type\" du fichier importé ne correspond pas avec le bon d'engagement courant."
1753+
1754+#. module: account
1755+#: code:addons/account/wizard/account_cv_import.py:124
1756+#, python-format
1757+msgid "The commitment date has a wrong format."
1758+msgstr "La date du bon d'engagement a un format incorrect."
1759+
1760 #. modules: purchase, tender_flow, sale, stock
1761 #: help:purchase.order,product_id:0
1762 #: help:sale.order,product_id:0
1763@@ -115830,6 +116074,7 @@
1764 msgid "Force Date and time of next execution"
1765 msgstr "Date et heure forcée de la prochiane exécution plannifiée"
1766
1767+<<<<<<< TREE
1768 #. module: account
1769 #: code:addons/account/account.py:752
1770 #, python-format
1771@@ -115885,3 +116130,68 @@
1772 #: view:account.invoice:0
1773 msgid "Paid Counterparts"
1774 msgstr "Contreparties Payées"
1775+=======
1776+#. module: analytic_distribution
1777+#: code:addons/analytic_distribution/analytic_distribution.py:241
1778+#, python-format
1779+msgid "Account %s is inactive on %s"
1780+msgstr "Le compte %s est inactif au %s"
1781+
1782+#. module: account
1783+#: code:addons/account/wizard/account_invoice_import.py:283
1784+#, python-format
1785+msgid "Line %s: %s/%s/%s %s"
1786+msgstr "Ligne %s: %s/%s/%s %s"
1787+
1788+#. module: account
1789+#: code:addons/account/wizard/account_invoice_import.py:258
1790+#, python-format
1791+msgid "Line %s: the cost center %s doesn't exist."
1792+msgstr "Ligne %s: le centre de coût %s n'existe pas."
1793+
1794+#. module: account
1795+#: code:addons/account/wizard/account_invoice_import.py:268
1796+#, python-format
1797+msgid "Line %s: the destination %s doesn't exist."
1798+msgstr "Ligne %s: la destination %s n'existe pas."
1799+
1800+#. module: account
1801+#: code:addons/account/wizard/account_invoice_import.py:263
1802+#, python-format
1803+msgid "Line %s: the funding pool %s doesn't exist."
1804+msgstr "Ligne %s: le funding pool %s n'existe pas."
1805+
1806+#. module: account
1807+#: code:addons/account/wizard/account_cv_import.py:326
1808+#, python-format
1809+msgid "%s line(s) updated with a new AD and a new Account\n"
1810+"%s line(s) updated with a new account only\n"
1811+"%s line(s) updated with a new AD only."
1812+msgstr "%s ligne(s) mise(s) à jour avec un nouvelle DA et un nouveau Compte\n"
1813+"%s ligne(s) mise(s) à jour avec uniquement un nouveau Compte\n"
1814+"%s ligne(s) mise(s) à jour avec uniquement une nouvelle DA."
1815+
1816+#. module: account
1817+#: report:addons/account/report/export_cv.mako:145
1818+msgid "Internal ID"
1819+msgstr "ID Interne"
1820+
1821+#. module: account
1822+#: code:addons/account/wizard/account_cv_import.py:231
1823+#, python-format
1824+msgid "Line %s: product %s doesn't match."
1825+msgstr "Ligne %s: le produit %s ne correspond pas."
1826+
1827+#. module: account
1828+#: code:addons/account/wizard/account_cv_import.py:198
1829+#, python-format
1830+msgid "Line %s: the internal id format is incorrect."
1831+msgstr "Ligne %s: format champ ID Interne incorrect."
1832+
1833+#. module: account
1834+#: code:addons/account/wizard/account_cv_import.py:193
1835+#, python-format
1836+msgid "Line %s: the internal id is missing."
1837+msgstr "Ligne %s: champ ID Interne manquant."
1838+
1839+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches