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

Proposed by jftempo
Status: Merged
Merged at revision: 5440
Proposed branch: lp:~julie-w/unifield-server/US-6076-BIS
Merge into: lp:unifield-server
Diff against target: 3653 lines (+1487/-495) (has conflicts)
50 files modified
bin/addons/account/__openerp__.py (+0/-1)
bin/addons/account/account_invoice_view.xml (+88/-25)
bin/addons/account/account_invoice_workflow.xml (+9/-7)
bin/addons/account/account_move_line.py (+17/-0)
bin/addons/account/account_report.xml (+1/-1)
bin/addons/account/invoice.py (+109/-35)
bin/addons/account/report/account_invoice_report.py (+5/-4)
bin/addons/account/report/account_invoice_report_view.xml (+1/-1)
bin/addons/account/report/account_report.py (+11/-10)
bin/addons/account/report/account_report_view.xml (+1/-1)
bin/addons/account/report/account_tax_report.py (+21/-21)
bin/addons/account/wizard/__init__.py (+0/-2)
bin/addons/account/wizard/account_invoice_refund.py (+50/-14)
bin/addons/account/wizard/account_invoice_refund_view.xml (+4/-1)
bin/addons/account/wizard/account_invoice_state.py (+2/-25)
bin/addons/account/wizard/account_invoice_state_view.xml (+0/-24)
bin/addons/account/wizard/account_state_open.py (+0/-44)
bin/addons/account/wizard/account_state_open_view.xml (+0/-35)
bin/addons/account_override/__init__.py (+1/-0)
bin/addons/account_override/account.py (+17/-9)
bin/addons/account_override/account_invoice_sync.py (+346/-0)
bin/addons/account_override/account_invoice_view.xml (+155/-42)
bin/addons/account_override/invoice.py (+114/-13)
bin/addons/account_override/report/report_open_invoices.py (+2/-2)
bin/addons/account_voucher/report/account_voucher_sales_receipt_view.xml (+2/-2)
bin/addons/analytic_distribution/account_invoice_refund.py (+26/-5)
bin/addons/analytic_distribution/account_invoice_view.xml (+8/-2)
bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py (+4/-4)
bin/addons/finance/__openerp__.py (+0/-1)
bin/addons/finance/account_invoice_workflow.xml (+0/-13)
bin/addons/msf_audittrail/audittrail_invoice_data.yml (+2/-1)
bin/addons/msf_outgoing/msf_outgoing.py (+39/-28)
bin/addons/msf_profile/data/patches.xml (+12/-0)
bin/addons/msf_profile/i18n/fr_MF.po (+323/-57)
bin/addons/msf_profile/msf_profile.py (+40/-0)
bin/addons/msf_sync_data_server/data/sync_server.message_rule.csv (+2/-0)
bin/addons/product_attributes/product_attributes.py (+1/-1)
bin/addons/purchase/purchase_workflow.py (+3/-3)
bin/addons/register_accounting/account_invoice_view.xml (+30/-43)
bin/addons/register_accounting/wizard/down_payment.py (+1/-1)
bin/addons/res_currency_tables/res_currency.py (+1/-1)
bin/addons/sale/report/sale_report.py (+2/-2)
bin/addons/sale/sale_order.py (+3/-3)
bin/addons/sale/sale_view.xml (+0/-1)
bin/addons/sale/sale_workflow.py (+3/-3)
bin/addons/stock/stock.py (+8/-0)
bin/addons/stock_override/stock.py (+5/-0)
bin/addons/sync_so/picking.py (+3/-3)
bin/addons/sync_so/specific_xml_id.py (+14/-2)
bin/addons/vertical_integration/report/report_open_invoices.py (+1/-2)
Text conflict in bin/addons/msf_profile/data/patches.xml
Text conflict in bin/addons/msf_profile/i18n/fr_MF.po
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-6076-BIS
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+370751@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/account/__openerp__.py'
2--- bin/addons/account/__openerp__.py 2017-09-28 14:05:02 +0000
3+++ bin/addons/account/__openerp__.py 2019-07-30 10:04:49 +0000
4@@ -73,7 +73,6 @@
5 'wizard/account_report_central_journal_view.xml',
6 'wizard/account_subscription_generate_view.xml',
7 'wizard/account_fiscalyear_close_view.xml',
8- 'wizard/account_state_open_view.xml',
9 'wizard/account_journal_select_view.xml',
10 'wizard/account_change_currency_view.xml',
11 'wizard/account_validate_move_view.xml',
12
13=== modified file 'bin/addons/account/account_invoice_view.xml'
14--- bin/addons/account/account_invoice_view.xml 2018-02-13 15:48:51 +0000
15+++ bin/addons/account/account_invoice_view.xml 2019-07-30 10:04:49 +0000
16@@ -53,11 +53,29 @@
17 <form string="Invoice Line">
18 <notebook>
19 <page string="Line">
20- <field name="product_id" on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})" default_focus="1"/>
21- <field name="uos_id" on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})"/>
22- <field name="quantity"/>
23- <field name="price_unit"/>
24- <field name="discount" groups="base.group_extended"/>
25+ <field name="invoice_type" invisible="1"/>
26+ <field name="from_supply" invisible="1"/>
27+ <field name="partner_type" invisible="1"/>
28+ <field name="product_id"
29+ on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})"
30+ default_focus="1"
31+ attrs="{'readonly': ['|',
32+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True),
33+ '&amp;', '&amp;', ('invoice_type', '=', 'out_invoice'), ('from_supply', '=', True), ('partner_type', 'in', ('intermission', 'section'))]}"
34+ />
35+ <field name="uos_id"
36+ on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})"
37+ attrs="{'readonly': ['|',
38+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True),
39+ '&amp;', '&amp;', ('invoice_type', '=', 'out_invoice'), ('from_supply', '=', True), ('partner_type', 'in', ('intermission', 'section'))]}"
40+ />
41+ <field name="quantity" attrs="{'readonly': ['|',
42+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True),
43+ '&amp;', '&amp;', ('invoice_type', '=', 'out_invoice'), ('from_supply', '=', True), ('partner_type', 'in', ('intermission', 'section'))]}"
44+ />
45+ <field name="price_unit" attrs="{'readonly': [('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
46+ <field name="discount" groups="base.group_extended"
47+ attrs="{'readonly': [('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
48 <field colspan="4" name="name"/>
49 <field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id"/>
50 <field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id), ('parent_id', '!=', False)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
51@@ -152,10 +170,18 @@
52 <field name="journal_id" widget="selection"/>
53 <field name="number" readonly="1"/>
54 <field name="type" invisible="1"/>
55- <field name="currency_id" width="50"/>
56- <button name="%(action_account_change_currency)d" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" groups="account.group_account_user"/>
57+ <field name="currency_id" width="50" attrs="{'readonly': ['|', ('state', '!=', 'draft'),
58+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
59+ <button name="%(action_account_change_currency)d" type="action" icon="terp-stock_effects-object-colorize"
60+ string="Change" groups="account.group_account_user"
61+ attrs="{'invisible':[('state', '!=', 'draft')],
62+ 'readonly': [('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
63 <newline/>
64- <field string="Supplier" name="partner_id" domain="[('supplier', '=', True)]" on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id)" context="{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}"/>
65+ <field string="Supplier" name="partner_id" domain="[('supplier', '=', True)]"
66+ on_change="onchange_partner_id(type, partner_id, date_invoice, payment_term, partner_bank_id, company_id)"
67+ context="{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}"
68+ attrs="{'readonly': ['|', ('state', '!=', 'draft'), '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"
69+ />
70 <field domain="[('partner_id','=',partner_id)]" name="address_invoice_id"/>
71 <field name="fiscal_position" groups="base.group_extended" widget="selection"/>
72 <newline/>
73@@ -187,7 +213,7 @@
74 </tree>
75 </field>
76 <group col="1" colspan="2">
77- <field name="tax_line" nolabel="1">
78+ <field name="tax_line" nolabel="1" attrs="{'invisible': [('vat_ok', '=', False)], 'readonly': ['|', ('state','!=', 'draft'), '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}">
79 <tree editable="bottom" string="Taxes">
80 <field name="invoice_id" invisible="True"/>
81 <field name="account_tax_id" on_change="tax_code_change(account_tax_id,parent.amount_untaxed,context)"/>
82@@ -196,7 +222,7 @@
83 <field name="account_id" groups="account.group_account_invoice"
84 domain="[('type', 'not in', ['view', 'consolidation']),
85 ('user_type_code', '=', 'tax')]"/>
86-
87+
88 <field name="base" on_change="base_change(base,parent.currency_id,parent.company_id,parent.date_invoice)" readonly="1"/>
89 <field name="amount" on_change="amount_change(amount,parent.currency_id,parent.company_id,parent.date_invoice)"/>
90
91@@ -217,10 +243,8 @@
92 <field name="state"/>
93 <field name="residual"/>
94 <group col="6" colspan="4">
95- <button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" icon="gtk-cancel"/>
96 <button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object" icon="terp-stock_effects-object-colorize"/>
97- <button name="%(action_account_invoice_refund)d" type='action' string='Refund' states='open,paid' icon="gtk-execute"/>
98- <button name="%(action_account_state_open)d" type='action' string='Re-Open' states='paid' icon="gtk-convert" groups="base.group_no_one"/>
99+ <button name="%(action_account_invoice_refund)d" type='action' string='Refund' states='open,paid,inv_close' icon="gtk-execute"/>
100 <button name="invoice_open" states="draft,proforma2" string="Approve" icon="terp-camera_test"/>
101 </group>
102 </group>
103@@ -230,11 +254,18 @@
104 <field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)" widget="selection" groups="base.group_multi_company"/>
105 <newline/>
106 <field name="payment_term" widget="selection"/>
107- <field name="name"/>
108+ <field name="name"
109+ attrs="{'readonly': ['|',
110+ ('state', '!=', 'draft'),
111+ '&amp;', '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True), ('from_supply', '=', True)]}"/>
112 <newline/>
113- <field name="origin" groups="base.group_extended"/>
114+ <field name="origin" groups="base.group_extended"
115+ attrs="{'readonly': ['|',
116+ ('state', '!=', 'draft'),
117+ '&amp;', '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True), ('from_supply', '=', True)]}"/>
118 <field domain="[('partner_id','=',partner_id)]" name="address_contact_id" groups="base.group_extended"/>
119- <field name="user_id"/>
120+ <field name="user_id"
121+ attrs="{'readonly': ['|', ('state', '!=', 'draft'), '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
122 <field name="move_id" groups="account.group_account_user"/>
123 <separator colspan="4" string="Additional Information"/>
124 <field colspan="4" name="comment" nolabel="1"/>
125@@ -273,7 +304,16 @@
126 <field name="currency_id" width="50"/>
127 <button name="%(action_account_change_currency)d" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" groups="account.group_account_user"/>
128 <newline/>
129- <field string="Customer" name="partner_id" domain="[('customer', '=', True)]" on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id)" groups="base.group_user" context="{'search_default_customer': 1}"/>
130+ <field string="Customer" name="partner_id"
131+ domain="[('customer', '=', True)]"
132+ on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id)"
133+ groups="base.group_user" context="{'search_default_customer': 1}"
134+ attrs="{'readonly': ['|',
135+ ('state', '!=', 'draft'),
136+ '&amp;', '&amp;',
137+ ('type', '=', 'out_invoice'),
138+ ('from_supply', '=', True),
139+ ('partner_type', 'in', ('intermission', 'section'))]}"/>
140 <field domain="[('partner_id','=',partner_id)]" name="address_invoice_id"/>
141 <field name="fiscal_position" groups="base.group_extended" widget="selection"/>
142 <newline/>
143@@ -286,9 +326,14 @@
144 <notebook colspan="4">
145 <page string="Invoice">
146 <field domain="[('company_id', '=', company_id),('type','=', 'receivable')]" name="account_id" groups="account.group_account_user"/>
147- <field name="name"/>
148+ <field name="name" attrs="{'readonly': ['|',
149+ ('state', '!=', 'draft'),
150+ '&amp;', '&amp;',
151+ ('type', '=', 'out_invoice'),
152+ ('from_supply', '=', True),
153+ ('partner_type', 'in', ('intermission', 'section'))]}"/>
154 <field name="payment_term" widget="selection"/>
155- <field colspan="4" name="invoice_line" nolabel="1" widget="one2many_list" context="{'fake':1}"/>
156+ <field colspan="4" name="invoice_line" nolabel="1" widget="one2many_list" context="{'fake': 1, 'from_inv_form': True}"/>
157 <group col="1" colspan="2">
158 <field name="tax_line" nolabel="1">
159 <tree editable="bottom" string="Taxes">
160@@ -313,14 +358,12 @@
161 <field name="state"/>
162 <field name="residual"/>
163 <group col="8" colspan="4" groups="base.group_user">
164- <button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" icon="gtk-cancel"/>
165 <button name="action_cancel_draft" states="cancel" string="Reset to Draft" type="object" icon="terp-stock_effects-object-colorize"/>
166
167- <button name="%(action_account_invoice_refund)d" type='action' string='Refund' states='open,paid' icon="gtk-execute"/>
168- <button name='%(action_account_state_open)d' type='action' string='Re-Open' states='paid' icon="gtk-convert" groups="base.group_no_one"/>
169+ <button name="%(action_account_invoice_refund)d" type='action' string='Refund' states='open,paid,inv_close' icon="gtk-execute"/>
170 <button name="invoice_proforma2" states="draft" string="PRO-FORMA" icon="terp-gtk-media-pause" groups="account.group_account_user"/>
171 <button name="invoice_open" states="draft,proforma2" string="Validate" icon="gtk-go-forward"/>
172- <button name="%(account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,proforma,sale,proforma2"/>
173+ <button name="%(account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,inv_close,proforma,sale,proforma2"/>
174 </group>
175 </group>
176 </page>
177@@ -328,11 +371,21 @@
178 <field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)" widget="selection" groups="base.group_multi_company"/>
179 <newline/>
180 <field name="date_due"/>
181- <field name="user_id"/>
182+ <field name="user_id" attrs="{'readonly': ['|',
183+ ('state', '!=', 'draft'),
184+ '&amp;', '&amp;',
185+ ('type', '=', 'out_invoice'),
186+ ('from_supply', '=', True),
187+ ('partner_type', 'in', ('intermission', 'section'))]}"/>
188 <newline/>
189 <field domain="[('partner_id.ref_companies', 'in', [company_id])]" name="partner_bank_id"
190 groups="base.group_extended"/>
191- <field name="origin"/>
192+ <field name="origin" attrs="{'readonly': ['|',
193+ ('state', '!=', 'draft'),
194+ '&amp;', '&amp;',
195+ ('type', '=', 'out_invoice'),
196+ ('from_supply', '=', True),
197+ ('partner_type', 'in', ('intermission', 'section'))]}"/>
198 <field colspan="4" domain="[('partner_id','=',partner_id)]" name="address_contact_id"
199 groups="base.group_extended"/>
200 <field name="move_id" groups="account.group_account_user"/>
201@@ -353,6 +406,16 @@
202 </tree>
203 </field>
204 </page>
205+ <!-- display the Counterpart Invoice tab in STV, hide it in Customer Refunds -->
206+ <page string="Counterpart Invoice" attrs="{'invisible': [('type', '!=', 'out_invoice')]}">
207+ <field name="from_supply" invisible="1"/>
208+ <field name="synced"
209+ attrs="{'readonly': ['|', ('from_supply', '=', True), ('state', '!=', 'draft')]}"
210+ on_change="onchange_synced(synced, partner_id)"/>
211+ <newline/>
212+ <field name="counterpart_inv_number"/>
213+ <field name="counterpart_inv_status"/>
214+ </page>
215 </notebook>
216 </form>
217 </field>
218
219=== modified file 'bin/addons/account/account_invoice_workflow.xml'
220--- bin/addons/account/account_invoice_workflow.xml 2018-09-28 15:47:23 +0000
221+++ bin/addons/account/account_invoice_workflow.xml 2019-07-30 10:04:49 +0000
222@@ -24,23 +24,24 @@
223 <record id="act_open" model="workflow.activity">
224 <field name="wkf_id" ref="wkf"/>
225 <field name="name">open</field>
226- <field name="action">action_date_assign()
227-action_move_create()
228-action_number()
229-write({'state':'open'})</field>
230+ <field name="action">action_open_invoice()
231+write({'state':'open'})
232+action_gen_sync_msg()</field>
233 <field name="kind">function</field>
234 </record>
235 <record model="workflow.activity" id="act_open_test">
236 <field name="wkf_id" ref="wkf"/>
237 <field name="name">re-open</field>
238- <field name="action">write({'state':'open'})</field>
239+ <field name="action">write({'state':'open'})
240+action_gen_sync_msg()</field>
241 <field name="kind">function</field>
242 </record>
243 <record id="act_paid" model="workflow.activity">
244 <field name="wkf_id" ref="wkf"/>
245 <field name="name">paid</field>
246 <!--<field name="flow_stop">True</field>-->
247- <field name="action">confirm_paid()</field>
248+ <field name="action">confirm_paid()
249+action_gen_sync_msg()</field>
250 <field name="kind">function</field>
251 <field name="signal_send">subflow.paid</field>
252 </record>
253@@ -49,7 +50,8 @@
254 <field name="name">cancel</field>
255 <field name="flow_stop">True</field>
256 <field name="action">action_cancel()
257-write({'state':'cancel'})</field>
258+write({'state':'cancel'})
259+action_gen_sync_msg()</field>
260 <field name="kind">function</field>
261 </record>
262
263
264=== modified file 'bin/addons/account/account_move_line.py'
265--- bin/addons/account/account_move_line.py 2019-03-14 11:20:01 +0000
266+++ bin/addons/account/account_move_line.py 2019-07-30 10:04:49 +0000
267@@ -27,6 +27,7 @@
268 from tools.translate import _
269 import decimal_precision as dp
270 import tools
271+import netsvc
272
273 class account_move_line(osv.osv):
274 _name = "account.move.line"
275@@ -993,8 +994,24 @@
276 'unreconcile_date': time.strftime('%Y-%m-%d'),
277 'unreconcile_txt': obj_move_line.browse(cr, uid, aml, context=context, fields_to_fetch=['reconcile_txt']).reconcile_txt,
278 }, context=context)
279+
280+ # if full reconcile linked to an invoice, set it as (re-)open
281+ cr.execute('''
282+ select distinct(inv.id)
283+ from account_invoice inv
284+ left join account_move_line move_line on move_line.move_id = inv.move_id
285+ where
286+ move_line.reconcile_id in %s and
287+ move_line.is_counterpart
288+ ''', (tuple(unlink_ids), )
289+ )
290+ inv_ids = [x[0] for x in cr.fetchall()]
291+
292 # then delete the account.move.reconciles
293 obj_move_rec.unlink(cr, uid, unlink_ids)
294+
295+ if inv_ids:
296+ netsvc.LocalService("workflow").trg_validate(uid, 'account.invoice', inv_ids, 'open_test', cr)
297 return True
298
299 def check_unlink(self, cr, uid, ids, context=None):
300
301=== modified file 'bin/addons/account/account_report.xml'
302--- bin/addons/account/account_report.xml 2018-08-03 12:27:21 +0000
303+++ bin/addons/account/account_report.xml 2019-07-30 10:04:49 +0000
304@@ -33,7 +33,7 @@
305 name="account.invoice"
306 rml="account/report/account_print_invoice.rml"
307 string="Invoices"
308- attachment="(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/',''))"
309+ attachment="(object.state in ('open','paid', 'inv_close')) and ('INV'+(object.number or '').replace('/',''))"
310 attachment_use="1"
311 multi="True"/>
312 <report id="account_transfers" model="account.transfer" name="account.transfer" string="Transfers" xml="account/report/transfer.xml" xsl="account/report/transfer.xsl"/>
313
314=== modified file 'bin/addons/account/invoice.py'
315--- bin/addons/account/invoice.py 2019-06-05 09:09:37 +0000
316+++ bin/addons/account/invoice.py 2019-07-30 10:04:49 +0000
317@@ -26,6 +26,7 @@
318 import netsvc
319 from osv import fields, osv, orm
320 from tools.translate import _
321+from msf_partner import PARTNER_TYPE
322
323
324 class account_invoice(osv.osv):
325@@ -93,7 +94,7 @@
326 for invoice in self.browse(cr, uid, ids, context=context):
327 # UNIFIELD REFACTORING: UF-1536 have change this method
328 # Not needed to do process if invoice is draft or paid
329- if invoice.state in ['draft', 'paid']:
330+ if invoice.state in ['draft', 'paid', 'inv_close']:
331 result[invoice.id] = 0.0
332 continue
333 result[invoice.id] = invoice.amount_total
334@@ -167,8 +168,7 @@
335 if invoice.move_id:
336 # US-1882 The payments should only concern the "header line" of the SI on the counterpart account.
337 # For example the import of a tax line shouldn't be considered as a payment (out or in).
338- invoice_amls = [ml for ml in invoice.move_id.line_id if ml.account_id == invoice.account_id
339- and abs(abs(invoice.amount_total) - abs(ml.amount_currency)) <= 10**-3]
340+ invoice_amls = [ml for ml in invoice.move_id.line_id if ml.account_id == invoice.account_id and ml.is_counterpart]
341 for m in invoice_amls:
342 temp_lines = set()
343 if m.reconcile_id:
344@@ -257,7 +257,7 @@
345 _order = "id desc"
346
347 _columns = {
348- 'name': fields.char('Description', size=64, select=True, readonly=True, states={'draft':[('readonly',False)]}),
349+ 'name': fields.char('Description', size=256, select=True, readonly=True, states={'draft': [('readonly', False)]}),
350 'origin': fields.char('Source Document', size=512, help="Reference of the document that produced this invoice.", readonly=True, states={'draft':[('readonly',False)]}),
351 'type': fields.selection([
352 ('out_invoice','Customer Invoice'),
353@@ -279,6 +279,7 @@
354 ('proforma2','Pro-forma'),
355 ('open','Open'),
356 ('paid','Paid'),
357+ ('inv_close','Closed'),
358 ('cancel','Cancelled')
359 ],'State', select=True, readonly=True,
360 help=' * The \'Draft\' state is used when a user is encoding a new and unconfirmed Invoice. \
361@@ -286,8 +287,8 @@
362 \n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \
363 \n* The \'Paid\' state is set automatically when invoice is paid.\
364 \n* The \'Cancelled\' state is used when user cancel invoice.'),
365- 'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, help="Keep empty to use the current date"),
366- 'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True,
367+ 'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'inv_close':[('readonly',True)]}, select=True, help="Keep empty to use the current date"),
368+ 'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'inv_close':[('readonly',True)]}, select=True,
369 help="If you use payment terms, the due date will be computed automatically at the generation "\
370 "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."),
371 'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
372@@ -301,8 +302,7 @@
373
374 'account_id': fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="The partner account used for this invoice."),
375 'invoice_line': fields.one2many('account.invoice.line', 'invoice_id', 'Invoice Lines', readonly=True, states={'draft':[('readonly',False)]}),
376- 'tax_line': fields.one2many('account.invoice.tax', 'invoice_id', 'Tax Lines', readonly=True, states={'draft':[('readonly',False)]}),
377-
378+ 'tax_line': fields.one2many('account.invoice.tax', 'invoice_id', 'Tax Lines'),
379 'move_id': fields.many2one('account.move', 'Journal Entry', readonly=True, select=1, ondelete='restrict', help="Link to the automatically generated Journal Items."),
380 'amount_untaxed': fields.function(_amount_all, method=True, digits_compute=dp.get_precision('Account'), string='Untaxed',
381 store={
382@@ -328,7 +328,7 @@
383 'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
384 'journal_id': fields.many2one('account.journal', 'Journal', required=True, hide_default_menu=True, readonly=True, states={'draft':[('readonly',False)]}),
385 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
386- 'check_total': fields.float('Total', digits_compute=dp.get_precision('Account'), states={'open':[('readonly',True)],'close':[('readonly',True)],'paid':[('readonly',True)]}),
387+ 'check_total': fields.float('Total', digits_compute=dp.get_precision('Account'), states={'open':[('readonly',True)],'inv_close':[('readonly',True)],'paid':[('readonly',True)]}),
388 'reconciled': fields.function(_reconciled, method=True, string='Paid/Reconciled', type='boolean',
389 store={
390 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50), # Check if we can remove ?
391@@ -454,22 +454,47 @@
392 def confirm_paid(self, cr, uid, ids, context=None):
393 if context is None:
394 context = {}
395- self.write(cr, uid, ids, {'state':'paid'}, context=context)
396- for inv_id, name in self.name_get(cr, uid, ids, context=context):
397- message = _("Invoice '%s' is paid.") % name
398- self.log(cr, uid, inv_id, message)
399+ # if reconciled with at least 1 liquidity journal then paid else cancel aka Closed
400+ cr.execute("""
401+ SELECT i.id, min(j.id), i.number
402+ FROM account_invoice i
403+ LEFT JOIN account_move_line l ON i.move_id=l.move_id
404+ LEFT JOIN account_move_line rec_line ON rec_line.reconcile_id = l.reconcile_id
405+ LEFT JOIN account_journal j ON j.id = rec_line.journal_id AND j.type in ('cash', 'bank', 'cheque')
406+ WHERE i.id IN %s
407+ AND l.reconcile_id is not null
408+ AND l.account_id=i.account_id
409+ AND l.is_counterpart
410+ GROUP BY i.id, i.number""", (tuple(ids), )
411+ )
412+
413+ for x in cr.fetchall():
414+ if x[1]:
415+ state = 'paid'
416+ display_state = _('paid')
417+ else:
418+ state = 'inv_close'
419+ display_state = _('closed')
420+
421+ self.write(cr, uid, x[0], {'state': state}, context=context)
422+ self.log(cr, uid, x[0], _("Invoice '%s' is %s.") % (x[2], display_state))
423+
424 return True
425
426 def unlink(self, cr, uid, ids, context=None):
427 if context is None:
428 context = {}
429- invoices = self.read(cr, uid, ids, ['state'], context=context)
430+ invoices = self.read(cr, uid, ids, ['state', 'synced', 'from_supply'], context=context)
431 unlink_ids = []
432 for t in invoices:
433- if t['state'] in ('draft', 'cancel'):
434+ if t['state'] not in ('draft', 'cancel'):
435+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) that are already opened or paid !'))
436+ elif t['from_supply']:
437+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) generated by a Supply workflow!'))
438+ elif t['synced']:
439+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) set as "Synchronized"!'))
440+ else:
441 unlink_ids.append(t['id'])
442- else:
443- raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) that are already opened or paid !'))
444 osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
445 return True
446
447@@ -481,6 +506,7 @@
448 acc_id = False
449 bank_id = False
450 fiscal_position = False
451+ partner_type = False
452
453 opt = [('uid', str(uid))]
454 if partner_id:
455@@ -490,6 +516,8 @@
456 contact_addr_id = res['contact']
457 invoice_addr_id = res['invoice']
458 p = self.pool.get('res.partner').browse(cr, uid, partner_id)
459+ partner_type = p.partner_type # update the partner type immediately as it is used in a domain in attrs
460+
461 if company_id:
462 if p.property_account_receivable.company_id.id != company_id and p.property_account_payable.company_id.id != company_id:
463 property_obj = self.pool.get('ir.property')
464@@ -526,7 +554,8 @@
465 'address_invoice_id': invoice_addr_id,
466 'account_id': acc_id,
467 'payment_term': partner_payment_term,
468- 'fiscal_position': fiscal_position
469+ 'fiscal_position': fiscal_position,
470+ 'partner_type': partner_type,
471 }
472 }
473
474@@ -662,6 +691,22 @@
475 val['currency_id'] = currency.id
476 return {'value': val, 'domain': dom}
477
478+ def onchange_synced(self, cr, uid, ids, synced, partner_id):
479+ """
480+ Resets "synced" field and informs the user in case the box is ticked whereas the partner is neither Intermission nor Intersection
481+ """
482+ res = {}
483+ partner_obj = self.pool.get('res.partner')
484+ if synced and partner_id:
485+ if partner_obj.browse(cr, uid, partner_id, fields_to_fetch=['partner_type']).partner_type not in ('intermission', 'section'):
486+ warning = {
487+ 'title': _('Warning!'),
488+ 'message': _('Synchronization is allowed only with Intermission and Intersection partners.')
489+ }
490+ res['warning'] = warning
491+ res['value'] = {'synced': False, }
492+ return res
493+
494 # go from canceled state to draft state
495 def action_cancel_draft(self, cr, uid, ids, *args):
496 self.write(cr, uid, ids, {'state':'draft'})
497@@ -674,25 +719,31 @@
498 # Workflow stuff
499 #################
500
501- # return the ids of the move lines which has the same account than the invoice
502- # whose id is in ids
503 def move_line_id_payment_get(self, cr, uid, ids, *args):
504- if not ids: return []
505+ '''
506+ return the ids of the SI header move line
507+ '''
508+ if not ids:
509+ return []
510 result = self.move_line_id_payment_gets(cr, uid, ids, *args)
511 return result.get(ids[0], [])
512
513 def move_line_id_payment_gets(self, cr, uid, ids, *args):
514+ if not ids:
515+ return {}
516+
517 res = {}
518- if not ids: return res
519- cr.execute('SELECT i.id, l.id '\
520- 'FROM account_move_line l '\
521- 'LEFT JOIN account_invoice i ON (i.move_id=l.move_id) '\
522- 'WHERE i.id IN %s '\
523- 'AND l.account_id=i.account_id',
524- (tuple(ids),))
525+ cr.execute("""
526+ SELECT i.id, l.id
527+ FROM account_move_line l
528+ LEFT JOIN account_invoice i ON (i.move_id=l.move_id)
529+ WHERE i.id IN %s
530+ AND l.account_id=i.account_id
531+ AND l.is_counterpart""", (tuple(ids), )
532+ )
533 for r in cr.fetchall():
534 res.setdefault(r[0], [])
535- res[r[0]].append( r[1] )
536+ res[r[0]].append(r[1])
537 return res
538
539 def copy(self, cr, uid, id, default={}, context=None):
540@@ -705,6 +756,10 @@
541 'move_name':False,
542 'internal_number': False,
543 'main_purchase_id': False,
544+ 'from_supply': False,
545+ 'synced': False,
546+ 'counterpart_inv_number': False,
547+ 'counterpart_inv_status': False,
548 })
549 if 'date_invoice' not in default:
550 default.update({
551@@ -1324,12 +1379,18 @@
552 for invoice in invoices:
553 del invoice['id']
554
555- type_dict = {
556- 'out_invoice': 'out_refund', # Customer Invoice
557- 'in_invoice': 'in_refund', # Supplier Invoice
558- 'out_refund': 'out_invoice', # Customer Refund
559- 'in_refund': 'in_invoice', # Supplier Refund
560- }
561+ if context.get('is_intermission', False):
562+ type_dict = {
563+ 'out_invoice': 'in_invoice', # IVO
564+ 'in_invoice': 'out_invoice', # IVI
565+ }
566+ else:
567+ type_dict = {
568+ 'out_invoice': 'out_refund', # Customer Invoice
569+ 'in_invoice': 'in_refund', # Supplier Invoice
570+ 'out_refund': 'out_invoice', # Customer Refund
571+ 'in_refund': 'in_invoice', # Supplier Refund
572+ }
573
574 invoice_lines = obj_invoice_line.read(cr, uid, invoice['invoice_line'])
575 invoice_lines = self._refund_cleanup_lines(cr, uid, invoice_lines, is_account_inv_line=True, context=context)
576@@ -1355,6 +1416,10 @@
577 'journal_id': refund_journal_ids,
578 'origin': invoice['number']
579 })
580+ if context.get('is_intermission', False):
581+ invoice.update({
582+ 'is_intermission': True,
583+ })
584 if period_id:
585 invoice.update({
586 'period_id': period_id,
587@@ -1475,6 +1540,13 @@
588 self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
589 return True
590
591+
592+ def action_gen_sync_msg(self, cr, uid, ids, context=None):
593+ for inv_id in ids:
594+ self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'account.invoice', inv_id, {},
595+ 'account.invoice.update_counterpart_inv', self._logger, check_identifier=False, context=context)
596+ return True
597+
598 account_invoice()
599
600 class account_invoice_line(osv.osv):
601@@ -1515,6 +1587,8 @@
602 'name': fields.char('Description', size=256, required=True),
603 'origin': fields.char('Origin', size=512, help="Reference of the document that produced this invoice."),
604 'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True),
605+ 'partner_type': fields.related('invoice_id', 'partner_type', string='Partner Type', type='selection',
606+ selection=PARTNER_TYPE, readonly=True, store=False),
607 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null'),
608 'product_id': fields.many2one('product.product', 'Product', ondelete='set null'),
609 'account_id': fields.many2one('account.account', 'Account', required=True, domain=[('type','<>','view'), ('type', '<>', 'closed')], help="The income or expense account related to the selected product."),
610
611=== modified file 'bin/addons/account/report/account_invoice_report.py'
612--- bin/addons/account/report/account_invoice_report.py 2011-04-07 12:29:55 +0000
613+++ bin/addons/account/report/account_invoice_report.py 2019-07-30 10:04:49 +0000
614@@ -32,8 +32,8 @@
615 'year': fields.char('Year', size=4, readonly=True),
616 'day': fields.char('Day', size=128, readonly=True),
617 'month': fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
618- ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
619- ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
620+ ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
621+ ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
622 'product_id': fields.many2one('product.product', 'Product', readonly=True),
623 'product_qty':fields.float('Qty', readonly=True),
624 'uom_name': fields.char('Reference UoM', size=128, readonly=True),
625@@ -56,15 +56,16 @@
626 ('in_invoice','Supplier Invoice'),
627 ('out_refund','Customer Refund'),
628 ('in_refund','Supplier Refund'),
629- ],'Type', readonly=True),
630+ ],'Type', readonly=True),
631 'state': fields.selection([
632 ('draft','Draft'),
633 ('proforma','Pro-forma'),
634 ('proforma2','Pro-forma'),
635 ('open','Open'),
636 ('paid','Done'),
637+ ('inv_close','Closed'),
638 ('cancel','Cancelled')
639- ], 'Invoice State', readonly=True),
640+ ], 'Invoice State', readonly=True),
641 'date_due': fields.date('Due Date', readonly=True),
642 'address_contact_id': fields.many2one('res.partner.address', 'Contact Address Name', readonly=True),
643 'address_invoice_id': fields.many2one('res.partner.address', 'Invoice Address Name', readonly=True),
644
645=== modified file 'bin/addons/account/report/account_invoice_report_view.xml'
646--- bin/addons/account/report/account_invoice_report_view.xml 2017-10-04 05:23:42 +0000
647+++ bin/addons/account/report/account_invoice_report_view.xml 2019-07-30 10:04:49 +0000
648@@ -6,7 +6,7 @@
649 <field name="model">account.invoice.report</field>
650 <field name="type">tree</field>
651 <field name="arch" type="xml">
652- <tree colors="blue:state in ('draft');gray:state in ('cancel','paid');black:state in ('proforma','proforma2')" string="Invoices Analysis">
653+ <tree colors="blue:state in ('draft');gray:state in ('cancel','paid','inv_close');black:state in ('proforma','proforma2')" string="Invoices Analysis">
654 <field name="date" invisible="1"/>
655 <field name="user_id" invisible="1"/>
656 <field name="year" invisible="1"/>
657
658=== modified file 'bin/addons/account/report/account_report.py'
659--- bin/addons/account/report/account_report.py 2015-02-05 16:24:18 +0000
660+++ bin/addons/account/report/account_report.py 2019-07-30 10:04:49 +0000
661@@ -68,7 +68,7 @@
662 )""")
663 report_account_receivable()
664
665- #a.type in ('receivable','payable')
666+#a.type in ('receivable','payable')
667 class temp_range(osv.osv):
668 _name = 'temp.range'
669 _description = 'A Temporary table used for Dashboard view'
670@@ -101,14 +101,14 @@
671 def _calc_bal(self, cr, uid, ids, name, args, context=None):
672 res = {}
673 for period in self.read(cr, uid, ids, ['name'], context=context):
674- date1,date2 = period['name'].split(' to ')
675- cr.execute("SELECT SUM(credit-debit) FROM account_move_line AS line, account_account as ac \
676+ date1,date2 = period['name'].split(' to ')
677+ cr.execute("SELECT SUM(credit-debit) FROM account_move_line AS line, account_account as ac \
678 WHERE (line.account_id=ac.id) AND ac.type='receivable' \
679 AND (COALESCE(line.date,date) BETWEEN %s AND %s) \
680 AND (reconcile_id IS NULL) AND ac.active",(str(date2),str(date1),))
681- amount = cr.fetchone()
682- amount = amount[0] or 0.00
683- res[period['id']] = amount
684+ amount = cr.fetchone()
685+ amount = amount[0] or 0.00
686+ res[period['id']] = amount
687
688 return res
689
690@@ -159,7 +159,7 @@
691 ('in_invoice','Supplier Invoice'),
692 ('out_refund','Customer Refund'),
693 ('in_refund','Supplier Refund'),
694- ],'Type', readonly=True),
695+ ],'Type', readonly=True),
696 'number': fields.char('Invoice Number', size=32, readonly=True),
697 'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
698 'amount_untaxed': fields.float('Untaxed', readonly=True),
699@@ -174,6 +174,7 @@
700 ('proforma2','Pro-forma'),
701 ('open','Open'),
702 ('paid','Done'),
703+ ('inv_close','Closed'),
704 ('cancel','Cancelled')
705 ],'State', readonly=True),
706 'origin': fields.char('Source Document', size=512, readonly=True, help="Reference of the document that generated this invoice report."),
707@@ -235,7 +236,7 @@
708 inner join account_invoice inv on inv.id = inv_line.invoice_id
709 inner join account_account account on account.id = inv_line.account_id
710 where
711- inv.state in ('open','paid')
712+ inv.state in ('open','paid', 'inv_close')
713 group by
714 to_char(inv.date_invoice, 'YYYY'),to_char(inv.date_invoice,'MM'),inv.currency_id, inv.period_id, inv_line.product_id, account.user_type
715 )""")
716@@ -277,10 +278,10 @@
717 inner join account_invoice inv on inv.id = inv_line.invoice_id
718 inner join account_account account on account.id = inv_line.account_id
719 where
720- inv.state in ('open','paid')
721+ inv.state in ('open','paid', 'inv_close')
722 group by
723 to_char(inv.date_invoice, 'YYYY'),to_char(inv.date_invoice,'MM'),inv.currency_id, inv.period_id, inv_line.product_id, account.id
724 )""")
725 report_account_sales()
726
727-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
728\ No newline at end of file
729+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
730
731=== modified file 'bin/addons/account/report/account_report_view.xml'
732--- bin/addons/account/report/account_report_view.xml 2011-01-14 00:11:01 +0000
733+++ bin/addons/account/report/account_report_view.xml 2019-07-30 10:04:49 +0000
734@@ -88,7 +88,7 @@
735 <field name="model">report.invoice.created</field>
736 <field name="type">tree</field>
737 <field name="arch" type="xml">
738- <tree colors="blue:state in ('draft');black:state in ('proforma','proforma2','open');gray:state in('paid','cancel') " string="Invoices">
739+ <tree colors="blue:state in ('draft');black:state in ('proforma','proforma2','open');gray:state in('paid', 'inv_close', 'cancel') " string="Invoices">
740 <field name="create_date" select="1"/>
741 <field name="name" select="1"/>
742 <field name="type"/>
743
744=== modified file 'bin/addons/account/report/account_tax_report.py'
745--- bin/addons/account/report/account_tax_report.py 2014-09-24 09:16:10 +0000
746+++ bin/addons/account/report/account_tax_report.py 2019-07-30 10:04:49 +0000
747@@ -84,14 +84,14 @@
748 while i < len(res):
749
750 res_dict = { 'code': res[i][1].code,
751- 'name': res[i][1].name,
752- 'debit': 0,
753- 'credit': 0,
754- 'tax_amount': res[i][1].sum_period,
755- 'type': 1,
756- 'level': res[i][0],
757- 'pos': 0
758- }
759+ 'name': res[i][1].name,
760+ 'debit': 0,
761+ 'credit': 0,
762+ 'tax_amount': res[i][1].sum_period,
763+ 'type': 1,
764+ 'level': res[i][0],
765+ 'pos': 0
766+ }
767
768 top_result.append(res_dict)
769 res_general = self._get_general(res[i][1].id, period_list, company_id, based_on, context=context)
770@@ -128,10 +128,10 @@
771 AND account.company_id = %s \
772 AND move.id = line.move_id \
773 AND line.period_id IN %s \
774- AND ((invoice.state = %s) \
775+ AND ((invoice.state in (\'paid\', \'inv_close\')) \
776 OR (invoice.id IS NULL)) \
777 GROUP BY account.id,account.name,account.code', ('draft', tax_code_id,
778- company_id, periods_ids, 'paid',))
779+ company_id, periods_ids))
780
781 else:
782 self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \
783@@ -150,7 +150,7 @@
784 AND line.period_id IN %s\
785 AND account.active \
786 GROUP BY account.id,account.name,account.code', ('draft', tax_code_id,
787- company_id, periods_ids,))
788+ company_id, periods_ids,))
789 res = self.cr.dictfetchall()
790
791 i = 0
792@@ -206,14 +206,14 @@
793
794 while (bcl_current_level >= int(accounts[bcl_rup_ind]['level']) and bcl_rup_ind >= 0 ):
795 res_tot = { 'code': accounts[bcl_rup_ind]['code'],
796- 'name': '',
797- 'debit': 0,
798- 'credit': 0,
799- 'tax_amount': accounts[bcl_rup_ind]['tax_amount'],
800- 'type': accounts[bcl_rup_ind]['type'],
801- 'level': 0,
802- 'pos': 0
803- }
804+ 'name': '',
805+ 'debit': 0,
806+ 'credit': 0,
807+ 'tax_amount': accounts[bcl_rup_ind]['tax_amount'],
808+ 'type': accounts[bcl_rup_ind]['type'],
809+ 'level': 0,
810+ 'pos': 0
811+ }
812
813 if res_tot['type'] == 1:
814 # on change le type pour afficher le total
815@@ -229,6 +229,6 @@
816 return result_accounts
817
818 report_sxw.report_sxw('report.account.vat.declaration', 'account.tax.code',
819- 'addons/account/report/account_tax_report.rml', parser=tax_report, header="internal")
820+ 'addons/account/report/account_tax_report.rml', parser=tax_report, header="internal")
821
822-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
823\ No newline at end of file
824+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
825
826=== modified file 'bin/addons/account/wizard/__init__.py'
827--- bin/addons/account/wizard/__init__.py 2018-08-02 15:01:48 +0000
828+++ bin/addons/account/wizard/__init__.py 2019-07-30 10:04:49 +0000
829@@ -53,8 +53,6 @@
830 import account_validate_account_move
831 import account_use_model
832
833-import account_state_open
834-
835 import account_report_print_journal
836 import account_report_central_journal
837 import account_report_general_journal
838
839=== modified file 'bin/addons/account/wizard/account_invoice_refund.py'
840--- bin/addons/account/wizard/account_invoice_refund.py 2018-05-14 12:41:04 +0000
841+++ bin/addons/account/wizard/account_invoice_refund.py 2019-07-30 10:04:49 +0000
842@@ -29,13 +29,24 @@
843
844 _name = "account.invoice.refund"
845 _description = "Invoice Refund"
846+
847+ def _get_filter_refund(self, cr, uid, context=None):
848+ """
849+ Returns the selectable Refund Types (no simple "Refund" in case of an IVO/IVI)
850+ """
851+ if context is None:
852+ context = {}
853+ if context.get('is_intermission', False):
854+ return [('modify', 'Modify'), ('cancel', 'Cancel')]
855+ return [('modify', 'Modify'), ('refund', 'Refund'), ('cancel', 'Cancel')]
856+
857 _columns = {
858 'date': fields.date('Operation date', help='This date will be used as the invoice date for Refund Invoice and Period will be chosen accordingly!'),
859 'period': fields.many2one('account.period', 'Force period'),
860 'journal_id': fields.many2one('account.journal', 'Refund Journal', hide_default_menu=True,
861 help='You can select here the journal to use for the refund invoice that will be created. If you leave that field empty, it will use the same journal as the current invoice.'),
862 'description': fields.char('Description', size=128, required=True),
863- 'filter_refund': fields.selection([('modify', 'Modify'), ('refund', 'Refund'), ('cancel', 'Cancel')], "Refund Type", required=True, help='Refund invoice base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
864+ 'filter_refund': fields.selection(_get_filter_refund, "Refund Type", required=True, help='Refund invoice based on this type. You can not Modify and Cancel if the invoice is already reconciled'),
865 }
866
867 def _get_journal(self, cr, uid, context=None):
868@@ -109,9 +120,8 @@
869 """
870 for ml in aml_list:
871 if ml.account_id.reconcile:
872- if ml.account_id.id not in to_reconcile_dict:
873- to_reconcile_dict[ml.account_id.id] = []
874- to_reconcile_dict[ml.account_id.id].append(ml.id)
875+ key = (ml.account_id.id, ml.is_counterpart)
876+ to_reconcile_dict.setdefault(key, []).append(ml.id)
877
878 def compute_refund(self, cr, uid, ids, mode='refund', context=None):
879 """
880@@ -144,8 +154,20 @@
881 for inv in inv_obj.browse(cr, uid, invoice_ids, context=context):
882 if inv.state in ['draft', 'proforma2', 'cancel']:
883 raise osv.except_osv(_('Error !'), _('Can not %s draft/proforma/cancel invoice.') % (mode))
884+ if mode in ('cancel', 'modify') and not inv.account_id.reconcile:
885+ raise osv.except_osv(_('Error !'), _("Cannot Cancel / Modify if the account can't be reconciled."))
886 if mode in ('cancel', 'modify') and inv_obj.has_one_line_reconciled(cr, uid, [inv.id], context=context):
887- raise osv.except_osv(_('Error !'), _('Can not %s invoice which is already reconciled, invoice should be unreconciled first. You can only Refund this invoice') % (mode))
888+ if inv.is_intermission:
889+ # error specific to IVO/IVI for which there is no simple refund option
890+ raise osv.except_osv(_('Error !'), _('Cannot %s an Intermission Voucher which is already reconciled, it should be unreconciled first.') % _(mode))
891+ if inv.state == 'inv_close':
892+ raise osv.except_osv(_('Error !'), _('Can not %s invoice which is already reconciled, invoice should be unreconciled first.') % (mode))
893+ else:
894+ raise osv.except_osv(_('Error !'), _('Can not %s invoice which is already reconciled, invoice should be unreconciled first. You can only Refund this invoice') % (mode))
895+
896+ if mode == 'refund' and inv.state == 'inv_close':
897+ raise osv.except_osv(_('Error !'), _('It is not possible to refund a Closed invoice'))
898+
899 if form['period']:
900 period = form['period']
901 else:
902@@ -188,8 +210,14 @@
903 refund_id = self._hook_create_refund(cr, uid, [inv.id], date, period, description, journal_id, form, context=context)
904 del context['refund_mode'] # ignore it for the remaining process (in particular for the SI created in a refund modify...)
905 refund = inv_obj.browse(cr, uid, refund_id[0], context=context)
906+ # for Intermission Vouchers OUT: at standard creation time there is no "check_total" entered manually,
907+ # its value is always 0.0 => use the "amount_total" value for the IVI generated so it won't block at validation step
908+ if inv.is_intermission and inv.type == 'out_invoice':
909+ check_total = inv.amount_total or 0.0
910+ else:
911+ check_total = inv.check_total
912 inv_obj.write(cr, uid, [refund.id], {'date_due': date,
913- 'check_total': inv.check_total})
914+ 'check_total': check_total})
915
916 created_inv.append(refund_id[0])
917 if mode in ('cancel', 'modify'):
918@@ -206,8 +234,8 @@
919 self._get_reconcilable_amls(movelines, to_reconcile)
920 self._get_reconcilable_amls(refund.move_id.line_id, to_reconcile)
921 # reconcile the lines grouped by account
922- for account_id in to_reconcile:
923- account_m_line_obj.reconcile(cr, uid, to_reconcile[account_id],
924+ for account_id, is_counterpart in to_reconcile:
925+ account_m_line_obj.reconcile(cr, uid, to_reconcile[(account_id, is_counterpart)],
926 writeoff_period_id=period,
927 writeoff_journal_id = inv.journal_id.id,
928 writeoff_acc_id=account_id
929@@ -230,6 +258,7 @@
930 'period_id': False,
931 'name': description,
932 'origin': source_doc,
933+ 'is_intermission': inv.is_intermission,
934 })
935 for field in self._hook_fields_m2o_for_modify_refund(cr, uid):
936 invoice[field] = invoice[field] and invoice[field][0]
937@@ -243,8 +272,7 @@
938 # Refund cancel/modify: set the invoice JI/AJIs as Corrected by the system so that they can't be
939 # corrected manually. This must be done at the end of the refund process to handle the right AJI ids
940 # get the list of move lines excluding invoice header
941- ml_list = [ml.id for ml in movelines if not (ml.account_id.id == inv.account_id.id and
942- abs(abs(inv.amount_total) - abs(ml.amount_currency)) <= 10**-3)]
943+ ml_list = [ml.id for ml in movelines if not ml.is_counterpart]
944 account_m_line_obj.set_as_corrected(cr, uid, ml_list, manual=False, context=None)
945 # all JI lines of the SI and SR (including header) should be not corrigible, no matter if they
946 # are marked as corrected, reversed...
947@@ -254,11 +282,19 @@
948 # write on JIs without recreating AJIs
949 account_m_line_obj.write(cr, uid, ji_ids, {'is_si_refund': True}, context=context, check=False, update_check=False)
950
951- if inv.type in ('out_invoice', 'out_refund'):
952- xml_id = 'action_invoice_tree3'
953+ if context.get('is_intermission', False):
954+ module = 'account_override'
955+ if inv.type == 'in_invoice':
956+ xml_id = 'action_intermission_out'
957+ else:
958+ xml_id = 'action_intermission_in'
959 else:
960- xml_id = 'action_invoice_tree4'
961- result = mod_obj.get_object_reference(cr, uid, 'account', xml_id)
962+ module = 'account'
963+ if inv.type in ('out_invoice', 'out_refund'):
964+ xml_id = 'action_invoice_tree3'
965+ else:
966+ xml_id = 'action_invoice_tree4'
967+ result = mod_obj.get_object_reference(cr, uid, module, xml_id)
968 id = result and result[1] or False
969 result = act_obj.read(cr, uid, id, context=context)
970 invoice_domain = eval(result['domain'])
971
972=== modified file 'bin/addons/account/wizard/account_invoice_refund_view.xml'
973--- bin/addons/account/wizard/account_invoice_refund_view.xml 2018-05-15 08:55:26 +0000
974+++ bin/addons/account/wizard/account_invoice_refund_view.xml 2019-07-30 10:04:49 +0000
975@@ -15,11 +15,14 @@
976 <field name="date" required="1"/>
977 <field name="period"/>
978 <field name="filter_refund"/>
979+ <field name="is_intermission" invisible="1"/>
980 </group>
981 <separator colspan="4"/>
982 <group col="4" colspan="4" fill="1">
983 <label align="0.0" width="550" colspan="4" string="Modify Invoice: Cancels the current invoice and creates a new copy of it ready for editing."/>
984- <label align="0.0" width="300" string="Refund Invoice: Creates the refund invoice, ready for editing."/>
985+ <group attrs="{'invisible': [('is_intermission', '=', True)] }">
986+ <label align="0.0" width="300" string="Refund Invoice: Creates the refund invoice, ready for editing."/>
987+ </group>
988 <label align="0.0" width="500" colspan="4" string="Cancel Invoice: Creates the refund invoice, validate and reconcile it to cancel the current invoice."/>
989 </group>
990 <separator colspan="4"/>
991
992=== modified file 'bin/addons/account/wizard/account_invoice_state.py'
993--- bin/addons/account/wizard/account_invoice_state.py 2011-01-14 00:11:01 +0000
994+++ bin/addons/account/wizard/account_invoice_state.py 2019-07-30 10:04:49 +0000
995@@ -47,28 +47,5 @@
996
997 account_invoice_confirm()
998
999-class account_invoice_cancel(osv.osv_memory):
1000- """
1001- This wizard will cancel the all the selected invoices.
1002- If in the journal, the option allow cancelling entry is not selected then it will give warning message.
1003- """
1004-
1005- _name = "account.invoice.cancel"
1006- _description = "Cancel the Selected Invoices"
1007-
1008- def invoice_cancel(self, cr, uid, ids, context=None):
1009- if context is None:
1010- context = {}
1011- wf_service = netsvc.LocalService('workflow')
1012- pool_obj = pooler.get_pool(cr.dbname)
1013- data_inv = pool_obj.get('account.invoice').read(cr, uid, context['active_ids'], ['state'], context=context)
1014-
1015- for record in data_inv:
1016- if record['state'] in ('cancel','paid'):
1017- raise osv.except_osv(_('Warning'), _("Selected Invoice(s) cannot be cancelled as they are already in 'Cancelled' or 'Done' state!"))
1018- wf_service.trg_validate(uid, 'account.invoice', record['id'], 'invoice_cancel', cr)
1019- return {'type': 'ir.actions.act_window_close'}
1020-
1021-account_invoice_cancel()
1022-
1023-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1024\ No newline at end of file
1025+
1026+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1027
1028=== modified file 'bin/addons/account/wizard/account_invoice_state_view.xml'
1029--- bin/addons/account/wizard/account_invoice_state_view.xml 2017-10-04 05:23:42 +0000
1030+++ bin/addons/account/wizard/account_invoice_state_view.xml 2019-07-30 10:04:49 +0000
1031@@ -16,29 +16,5 @@
1032 </field>
1033 </record>
1034
1035- <record id="account_invoice_cancel_view" model="ir.ui.view">
1036- <field name="name">account.invoice.cancel.form</field>
1037- <field name="model">account.invoice.cancel</field>
1038- <field name="type">form</field>
1039- <field name="arch" type="xml">
1040- <form string="Cancel Selected Invoices">
1041- <separator string="Cancel Selected Invoices" colspan="4"/>
1042- <group colspan="4" col="6">
1043- <button icon="gtk-cancel" string="Cancel Invoices" name="invoice_cancel" type="object" default_focus="1"/>
1044- <button icon="terp-dialog-close" special="cancel" string="Close"/>
1045- </group>
1046- </form>
1047- </field>
1048- </record>
1049-
1050- <record id="action_account_invoice_cancel" model="ir.actions.act_window">
1051- <field name="name">Cancel Selected Invoices</field>
1052- <field name="res_model">account.invoice.cancel</field>
1053- <field name="view_type">form</field>
1054- <field name="view_mode">form</field>
1055- <field name="view_id" ref="account_invoice_cancel_view"/>
1056- <field name="target">new</field>
1057- </record>
1058-
1059 </data>
1060 </openerp>
1061
1062=== removed file 'bin/addons/account/wizard/account_state_open.py'
1063--- bin/addons/account/wizard/account_state_open.py 2011-01-14 00:11:01 +0000
1064+++ bin/addons/account/wizard/account_state_open.py 1970-01-01 00:00:00 +0000
1065@@ -1,44 +0,0 @@
1066-# -*- coding: utf-8 -*-
1067-##############################################################################
1068-#
1069-# OpenERP, Open Source Management Solution
1070-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
1071-#
1072-# This program is free software: you can redistribute it and/or modify
1073-# it under the terms of the GNU Affero General Public License as
1074-# published by the Free Software Foundation, either version 3 of the
1075-# License, or (at your option) any later version.
1076-#
1077-# This program is distributed in the hope that it will be useful,
1078-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1079-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1080-# GNU Affero General Public License for more details.
1081-#
1082-# You should have received a copy of the GNU Affero General Public License
1083-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1084-#
1085-##############################################################################
1086-from osv import osv
1087-
1088-import netsvc
1089-from tools.translate import _
1090-
1091-class account_state_open(osv.osv_memory):
1092- _name = 'account.state.open'
1093- _description = 'Account State Open'
1094-
1095- def change_inv_state(self, cr, uid, ids, context=None):
1096- obj_invoice = self.pool.get('account.invoice')
1097- if context is None:
1098- context = {}
1099- if 'active_ids' in context:
1100- data_inv = obj_invoice.browse(cr, uid, context['active_ids'][0], context=context)
1101- if data_inv.reconciled:
1102- raise osv.except_osv(_('Warning'), _('Invoice is already reconciled'))
1103- wf_service = netsvc.LocalService("workflow")
1104- res = wf_service.trg_validate(uid, 'account.invoice', context['active_ids'][0], 'open_test', cr)
1105- return {'type': 'ir.actions.act_window_close'}
1106-
1107-account_state_open()
1108-
1109-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1110\ No newline at end of file
1111
1112=== removed file 'bin/addons/account/wizard/account_state_open_view.xml'
1113--- bin/addons/account/wizard/account_state_open_view.xml 2011-01-14 00:11:01 +0000
1114+++ bin/addons/account/wizard/account_state_open_view.xml 1970-01-01 00:00:00 +0000
1115@@ -1,35 +0,0 @@
1116-<?xml version="1.0" encoding="utf-8"?>
1117-<openerp>
1118- <data>
1119-
1120- <record id="view_account_state_open" model="ir.ui.view">
1121- <field name="name">Account State Open</field>
1122- <field name="model">account.state.open</field>
1123- <field name="type">form</field>
1124- <field name="arch" type="xml">
1125- <form string="Open Invoice">
1126- <label string="Are you sure you want to open this invoice ?"/>
1127- <newline/>
1128- <label string="(Invoice should be unreconciled if you want to open it)"/>
1129- <separator colspan="4"/>
1130- <group colspan="2" col="4">
1131- <button special="cancel" string="No" icon="terp-gtk-stop"/>
1132- <button name="change_inv_state" string="Yes" type="object" icon="terp-camera_test"/>
1133- </group>
1134- </form>
1135- </field>
1136- </record>
1137-
1138- <record id="action_account_state_open" model="ir.actions.act_window">
1139- <field name="name">Account State Open</field>
1140- <field name="type">ir.actions.act_window</field>
1141- <field name="res_model">account.state.open</field>
1142- <field name="view_type">form</field>
1143- <field name="view_mode">form</field>
1144- <field name="view_id" ref="view_account_state_open"/>
1145- <field name="context">{'record_id' : active_id}</field>
1146- <field name="target">new</field>
1147- </record>
1148-
1149- </data>
1150-</openerp>
1151
1152=== modified file 'bin/addons/account_override/__init__.py'
1153--- bin/addons/account_override/__init__.py 2019-01-08 11:20:04 +0000
1154+++ bin/addons/account_override/__init__.py 2019-07-30 10:04:49 +0000
1155@@ -230,4 +230,5 @@
1156 import report
1157 import wizard
1158 import finance_export
1159+import account_invoice_sync
1160 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1161
1162=== modified file 'bin/addons/account_override/account.py'
1163--- bin/addons/account_override/account.py 2019-05-24 15:09:28 +0000
1164+++ bin/addons/account_override/account.py 2019-07-30 10:04:49 +0000
1165@@ -246,20 +246,28 @@
1166 elif args == [('restricted_area', '=', 'intermission_header')]:
1167 if context_ivo or context.get('check_header_ivo'):
1168 # HEADER of Intermission Voucher OUT:
1169- # restrict to 'is_intermission_counterpart', or Regular/Cash or Income, or Receivable/Receivables or Cash
1170+ # restrict to 'is_intermission_counterpart', or Regular/Cash or Income, or Receivable/Receivables or Cash,
1171+ # or Payable/Payables (for refund UC)
1172 # + prevent from using donation accounts
1173- arg = [('type_for_register', 'not in', ['donation', 'advance', 'transfer', 'transfer_same']),
1174- '|', '|', ('is_intermission_counterpart', '=', True),
1175- '&', ('type', '=', 'other'), ('user_type_code', 'in', ['cash', 'income']),
1176- '&', ('type', '=', 'receivable'), ('user_type_code', 'in', ['receivables', 'cash'])]
1177+ arg = [
1178+ ('type_for_register', 'not in', ['donation', 'advance', 'transfer', 'transfer_same']),
1179+ '|', '|', '|', ('is_intermission_counterpart', '=', True),
1180+ '&', ('type', '=', 'other'), ('user_type_code', 'in', ['cash', 'income']),
1181+ '&', ('type', '=', 'receivable'), ('user_type_code', 'in', ['receivables', 'cash']),
1182+ '&', ('user_type_code', '=', 'payables'), ('type', '=', 'payable')
1183+ ]
1184 elif context_ivi or context.get('check_header_ivi'):
1185 # HEADER of Intermission Voucher IN:
1186 # restrict to 'is_intermission_counterpart' or Regular/Cash or Regular/Income or Payable/Payables
1187+ # or Receivable/Receivables or Cash (for refund UC)
1188 # + prevent from using donation accounts
1189- arg = [('type_for_register', 'not in', ['donation', 'advance', 'transfer', 'transfer_same']),
1190- '|', '|', ('is_intermission_counterpart', '=', True),
1191- '&', ('type', '=', 'other'), ('user_type_code', 'in', ['cash', 'income']),
1192- '&', ('user_type_code', '=', 'payables'), ('type', '=', 'payable')]
1193+ arg = [
1194+ ('type_for_register', 'not in', ['donation', 'advance', 'transfer', 'transfer_same']),
1195+ '|', '|', '|', ('is_intermission_counterpart', '=', True),
1196+ '&', ('type', '=', 'other'), ('user_type_code', 'in', ['cash', 'income']),
1197+ '&', ('user_type_code', '=', 'payables'), ('type', '=', 'payable'),
1198+ '&', ('type', '=', 'receivable'), ('user_type_code', 'in', ['receivables', 'cash']),
1199+ ]
1200 return arg
1201
1202 def _get_fake_cash_domain(self, cr, uid, ids, field_name, arg, context=None):
1203
1204=== added file 'bin/addons/account_override/account_invoice_sync.py'
1205--- bin/addons/account_override/account_invoice_sync.py 1970-01-01 00:00:00 +0000
1206+++ bin/addons/account_override/account_invoice_sync.py 2019-07-30 10:04:49 +0000
1207@@ -0,0 +1,346 @@
1208+#!/usr/bin/env python
1209+#-*- encoding:utf-8 -*-
1210+##############################################################################
1211+#
1212+# OpenERP, Open Source Management Solution
1213+# Copyright (C) 2019 TeMPO Consulting, MSF. All Rights Reserved
1214+#
1215+# This program is free software: you can redistribute it and/or modify
1216+# it under the terms of the GNU Affero General Public License as
1217+# published by the Free Software Foundation, either version 3 of the
1218+# License, or (at your option) any later version.
1219+#
1220+# This program is distributed in the hope that it will be useful,
1221+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1222+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1223+# GNU Affero General Public License for more details.
1224+#
1225+# You should have received a copy of the GNU Affero General Public License
1226+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1227+#
1228+##############################################################################
1229+
1230+
1231+from osv import osv
1232+from osv import fields
1233+from tools.translate import _
1234+import logging
1235+import time
1236+
1237+
1238+class account_invoice_sync(osv.osv):
1239+ _inherit = 'account.invoice'
1240+ _logger = logging.getLogger('------sync.account.invoice')
1241+
1242+ _columns = {
1243+ 'synced': fields.boolean("Synchronized"),
1244+ 'from_supply': fields.boolean('From Supply', help="Internal field indicating whether the document is related to a Supply workflow"),
1245+ 'counterpart_inv_number': fields.char('Counterpart Invoice Number', size=64, readonly=True),
1246+ 'counterpart_inv_status': fields.selection([
1247+ ('draft', 'Draft'),
1248+ ('open', 'Open'),
1249+ ('paid', 'Paid'),
1250+ ('inv_close', 'Closed'),
1251+ ('cancel', 'Cancelled'),
1252+ ], string='Counterpart Invoice Status', readonly=True),
1253+ }
1254+
1255+ _defaults = {
1256+ 'synced': lambda *a: False,
1257+ 'from_supply': lambda *a: False,
1258+ }
1259+
1260+ def _create_analytic_distrib(self, cr, uid, vals, distrib, context=None):
1261+ """
1262+ Updates vals with the new analytic_distribution_id created based on the distrib in parameter if it exists
1263+ """
1264+ if context is None:
1265+ context = {}
1266+ analytic_distrib_obj = self.pool.get('analytic.distribution')
1267+ cc_distrib_line_obj = self.pool.get('cost.center.distribution.line')
1268+ fp_distrib_line_obj = self.pool.get('funding.pool.distribution.line')
1269+ data_obj = self.pool.get('ir.model.data')
1270+ # get the Funding Pool "PF"
1271+ try:
1272+ fp_id = data_obj.get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
1273+ except ValueError:
1274+ fp_id = 0
1275+ if distrib: # original distrib from PO or PO line
1276+ # create the Analytic Distribution
1277+ distrib_id = analytic_distrib_obj.create(cr, uid, {}, context=context)
1278+ for cc_line in distrib.cost_center_lines:
1279+ distrib_vals = {
1280+ 'analytic_id': cc_line.analytic_id and cc_line.analytic_id.id, # analytic_id = Cost Center for the CC distrib line
1281+ 'percentage': cc_line.percentage or 0.0,
1282+ 'distribution_id': distrib_id,
1283+ 'currency_id': cc_line.currency_id.id,
1284+ 'destination_id': cc_line.destination_id.id,
1285+ }
1286+ cc_distrib_line_obj.create(cr, uid, distrib_vals, context=context)
1287+ distrib_vals.update({
1288+ 'analytic_id': fp_id, # analytic_id = Funding Pool for the FP distrib line
1289+ 'cost_center_id': cc_line.analytic_id and cc_line.analytic_id.id,
1290+ })
1291+ fp_distrib_line_obj.create(cr, uid, distrib_vals, context=context)
1292+ vals.update({'analytic_distribution_id': distrib_id,})
1293+
1294+ def _create_invoice_lines(self, cr, uid, inv_lines_data, inv_id, inv_posting_date, inv_linked_po, from_supply, context=None):
1295+ """
1296+ Creates the lines of the automatic counterpart invoice (inv_id) generated at synchro time.
1297+ """
1298+ if context is None:
1299+ context = {}
1300+ so_po_common_obj = self.pool.get('so.po.common')
1301+ product_obj = self.pool.get('product.product')
1302+ account_obj = self.pool.get('account.account')
1303+ product_uom_obj = self.pool.get('product.uom')
1304+ inv_line_obj = self.pool.get('account.invoice.line')
1305+ for inv_line in inv_lines_data:
1306+ line_name = inv_line.get('name', '')
1307+ if not line_name: # required field
1308+ raise osv.except_osv(_('Error'), _("Impossible to retrieve the line description."))
1309+ product_id = False
1310+ product_data = inv_line.get('product_id', {})
1311+ line_account_id = False
1312+ # for the lines related to a product: use the account of the product / else use the one of the source invoice line
1313+ if product_data:
1314+ default_code = product_data.get('default_code', '')
1315+ product_id = so_po_common_obj.get_product_id(cr, uid, product_data, default_code=default_code, context=context) or False
1316+ if not product_id:
1317+ raise osv.except_osv(_('Error'), _("Product %s not found.") % default_code)
1318+ product = product_obj.browse(cr, uid, product_id, fields_to_fetch=['active', 'default_code', 'product_tmpl_id', 'categ_id'],
1319+ context=context)
1320+ if not product.active:
1321+ raise osv.except_osv(_('Error'), _("The product %s is inactive.") % product.default_code or '')
1322+ line_account_id = product.product_tmpl_id.property_account_expense and product.product_tmpl_id.property_account_expense.id
1323+ if not line_account_id:
1324+ line_account_id = product.categ_id and product.categ_id.property_account_expense_categ and product.categ_id.property_account_expense_categ.id
1325+ else:
1326+ account_code = inv_line.get('account_id', {}).get('code', '')
1327+ if not account_code:
1328+ raise osv.except_osv(_('Error'), _("Impossible to retrieve the account code at line level."))
1329+ account_ids = account_obj.search(cr, uid, [('code', '=', account_code)], limit=1, context=context)
1330+ if not account_ids:
1331+ raise osv.except_osv(_('Error'), _("Account code %s not found.") % account_code)
1332+ line_account_id = account_ids[0]
1333+ if not line_account_id:
1334+ raise osv.except_osv(_('Error'), _("Error when retrieving the account at line level."))
1335+ line_account = account_obj.browse(cr, uid, line_account_id,
1336+ fields_to_fetch=['activation_date', 'inactivation_date'], context=context)
1337+ if inv_posting_date < line_account.activation_date or \
1338+ (line_account.inactivation_date and inv_posting_date >= line_account.inactivation_date):
1339+ raise osv.except_osv(_('Error'), _('The account "%s - %s" is inactive.') % (line_account.code, line_account.name))
1340+ uom_id = False
1341+ uom_data = inv_line.get('uos_id', {})
1342+ if uom_data:
1343+ uom_name = uom_data.get('name', '')
1344+ uom_ids = product_uom_obj.search(cr, uid, [('name', '=', uom_name)], limit=1, context=context)
1345+ if not uom_ids:
1346+ raise osv.except_osv(_('Error'), _("Unit of Measure %s not found.") % uom_name)
1347+ uom_id = uom_ids[0]
1348+ quantity = inv_line.get('quantity', 0.0)
1349+ inv_line_vals = {
1350+ 'invoice_id': inv_id,
1351+ 'account_id': line_account_id,
1352+ 'name': line_name,
1353+ 'quantity': quantity,
1354+ 'price_unit': inv_line.get('price_unit', 0.0),
1355+ 'discount': inv_line.get('discount', 0.0),
1356+ 'product_id': product_id,
1357+ 'uos_id': uom_id,
1358+ }
1359+ if from_supply and inv_linked_po:
1360+ # fill in the AD at line level if applicable
1361+ # search the matching between PO line and invoice line based on description/product/quantity
1362+ matching_po_line = False
1363+ for po_line in inv_linked_po.order_line:
1364+ if po_line.name == line_name and po_line.product_id and po_line.product_id.id == product_id and \
1365+ po_line.product_qty == quantity and po_line.state not in ('draft', 'cancel', 'cancel_r'):
1366+ matching_po_line = po_line
1367+ break
1368+ if matching_po_line:
1369+ po_line_distrib = matching_po_line.analytic_distribution_id
1370+ self._create_analytic_distrib(cr, uid, inv_line_vals, po_line_distrib, context=context) # update inv_line_vals
1371+ inv_line_obj.create(cr, uid, inv_line_vals, context=context)
1372+
1373+ def create_invoice_from_sync(self, cr, uid, source, invoice_data, context=None):
1374+ """
1375+ Creates automatic counterpart invoice at synchro time.
1376+ Intermission workflow: an IVO sent generates an IVI
1377+ Intersection workflow: an STV sent generates an SI
1378+ """
1379+ self._logger.info("+++ Create an account.invoice in %s matching the one sent by %s" % (cr.dbname, source))
1380+ if context is None:
1381+ context = {}
1382+ journal_obj = self.pool.get('account.journal')
1383+ currency_obj = self.pool.get('res.currency')
1384+ partner_obj = self.pool.get('res.partner')
1385+ user_obj = self.pool.get('res.users')
1386+ po_obj = self.pool.get('purchase.order')
1387+ stock_picking_obj = self.pool.get('stock.picking')
1388+ invoice_dict = invoice_data.to_dict()
1389+ # the counterpart instance must exist and be active
1390+ partner_ids = partner_obj.search(cr, uid, [('name', '=', source), ('active', '=', True)], limit=1, context=context)
1391+ if not partner_ids:
1392+ raise osv.except_osv(_('Error'), _("The partner %s doesn't exist or is inactive.") % source)
1393+ partner_id = partner_ids[0]
1394+ partner = partner_obj.browse(cr, uid, partner_id, fields_to_fetch=['property_account_payable', 'name'], context=context)
1395+ journal_type = invoice_dict.get('journal_id', {}).get('type', '')
1396+ if not journal_type or journal_type not in ('sale', 'intermission'):
1397+ raise osv.except_osv(_('Error'), _("Impossible to retrieve the journal type, or the journal type is incorrect."))
1398+ currency_name = invoice_dict.get('currency_id', {}).get('name', '')
1399+ if not currency_name:
1400+ raise osv.except_osv(_('Error'), _("Impossible to retrieve the currency."))
1401+ currency_ids = currency_obj.search(cr, uid, [('name', '=', currency_name), ('currency_table_id', '=', False),
1402+ ('active', '=', True)], limit=1, context=context)
1403+ if not currency_ids:
1404+ raise osv.except_osv(_('Error'), _("Currency %s not found or inactive.") % currency_name)
1405+ currency_id = currency_ids[0]
1406+ number = invoice_dict.get('number', '')
1407+ state = invoice_dict.get('state', '') # note that we get the real state as the doc can be beyond the "open" state at sync. time
1408+ doc_date = invoice_dict.get('document_date', time.strftime('%Y-%m-%d'))
1409+ posting_date = invoice_dict.get('date_invoice', time.strftime('%Y-%m-%d'))
1410+ description = invoice_dict.get('name', '')
1411+ source_doc = invoice_dict.get('origin', '')
1412+ from_supply = invoice_dict.get('from_supply', False)
1413+ inv_lines = invoice_dict.get('invoice_line', [])
1414+ po = False
1415+ vals = {}
1416+ # STV in sending instance: generates an SI in the receiving instance
1417+ if journal_type == 'sale':
1418+ pur_journal_ids = journal_obj.search(cr, uid, [('type', '=', 'purchase'), ('is_current_instance', '=', True)], limit=1, context=context)
1419+ if not pur_journal_ids:
1420+ raise osv.except_osv(_('Error'), _("No Purchase journal found for the current instance."))
1421+ # for the SI use the Account Payable of the partner
1422+ si_account = partner.property_account_payable
1423+ if not si_account or posting_date < si_account.activation_date or \
1424+ (si_account.inactivation_date and posting_date >= si_account.inactivation_date):
1425+ raise osv.except_osv(_('Error'), _("Account Payable not found or inactive for the partner %s.") % partner.name)
1426+ vals.update(
1427+ {
1428+ 'journal_id': pur_journal_ids[0],
1429+ 'account_id': si_account.id,
1430+ 'type': 'in_invoice',
1431+ 'is_direct_invoice': False,
1432+ 'is_inkind_donation': False,
1433+ 'is_debit_note': False,
1434+ 'is_intermission': False,
1435+ }
1436+ )
1437+ # IVO in sending instance: generates an IVI in the receiving instance
1438+ elif journal_type == 'intermission':
1439+ int_journal_ids = journal_obj.search(cr, uid, [('type', '=', 'intermission'), ('is_current_instance', '=', True)], limit=1, context=context)
1440+ if not int_journal_ids:
1441+ raise osv.except_osv(_('Error'), _("No Intermission journal found for the current instance."))
1442+ # for the IVI use the Intermission counterpart account from the Company form
1443+ ivi_account = user_obj.browse(cr, uid, uid, fields_to_fetch=['company_id'], context=context).company_id.intermission_default_counterpart
1444+ if not ivi_account or posting_date < ivi_account.activation_date or \
1445+ (ivi_account.inactivation_date and posting_date >= ivi_account.inactivation_date):
1446+ raise osv.except_osv(_('Error'), _("The Intermission counterpart account is missing in the Company form or is inactive."))
1447+ vals.update(
1448+ {
1449+ 'journal_id': int_journal_ids[0],
1450+ 'account_id': ivi_account.id,
1451+ 'type': 'in_invoice',
1452+ 'is_inkind_donation': False,
1453+ 'is_debit_note': False,
1454+ 'is_intermission': True,
1455+ }
1456+ )
1457+ # common fields whatever the invoice type
1458+ if from_supply:
1459+ po_id = False
1460+ po_number = ''
1461+ fo_number = ''
1462+ ship_or_out_ref = ''
1463+ main_in = False
1464+ # extract PO number, and Shipment or Simple Out ref, from refs looking like:
1465+ # "se_HQ2C1.19/se_HQ2/HT101/PO00001 : SHIP/00002-01" or "se_HQ1C2.19/se_HQ1/HT201/PO00003 : OUT/00001"
1466+ inv_name_split = description.split()
1467+ if inv_name_split:
1468+ po_number = inv_name_split[0].split('.')[-1]
1469+ po_ids = po_obj.search(cr, uid, [('name', '=', po_number)], limit=1, context=context)
1470+ if po_ids:
1471+ po_id = po_ids[0]
1472+ ship_or_out_ref = inv_name_split[-1]
1473+ # extract FO number from source docs looking like:
1474+ # "SHIP/00001-04:19/se_HQ1/HT101/FO00007" or "OUT/00003:19/se_HQ1/HT101/FO00008"
1475+ inv_source_doc_split = source_doc.split(':')
1476+ if inv_source_doc_split:
1477+ fo_number = inv_source_doc_split[-1]
1478+ if po_id:
1479+ po = po_obj.browse(cr, uid, po_id, fields_to_fetch=['picking_ids', 'analytic_distribution_id', 'order_line'], context=context)
1480+ shipment_ref = "%s.%s" % (source or '', ship_or_out_ref or '')
1481+ # get the "main" IN
1482+ main_in_ids = stock_picking_obj.search(cr, uid,
1483+ [('id', 'in', [picking.id for picking in po.picking_ids]),
1484+ ('shipment_ref', '=', shipment_ref)],
1485+ limit=1, context=context)
1486+ if main_in_ids:
1487+ main_in = stock_picking_obj.browse(cr, uid, main_in_ids[0], fields_to_fetch=['name'], context=context)
1488+ # fill in the Analytic Distribution
1489+ # at header level if applicable
1490+ po_distrib = po.analytic_distribution_id
1491+ self._create_analytic_distrib(cr, uid, vals, po_distrib, context=context) # update vals
1492+ # note: in case a FO would have been manually created the PO and IN would be missing in the ref/source doc,
1493+ # but the same codification is used so it's visible that sthg is missing
1494+ description = "%s.%s : %s" % (source, fo_number, main_in and main_in.name or '') # e.g. se_HQ1C1.19/se_HQ1/HT101/FO00008 : IN/00009
1495+ source_doc = "%s:%s" % (main_in and main_in.name or '', po_id and po_number or '') # e.g. IN/00009:19/se_HQ1/HT201/PO00009
1496+ vals.update(
1497+ {
1498+ 'partner_id': partner_id,
1499+ 'currency_id': currency_id,
1500+ 'document_date': doc_date,
1501+ 'date_invoice': posting_date,
1502+ 'name': description,
1503+ 'origin': source_doc,
1504+ 'counterpart_inv_number': number,
1505+ 'counterpart_inv_status': state,
1506+ 'from_supply': from_supply,
1507+ 'synced': True,
1508+ }
1509+ )
1510+ inv_id = self.create(cr, uid, vals, context=context)
1511+ if inv_id:
1512+ self._create_invoice_lines(cr, uid, inv_lines, inv_id, posting_date, po, from_supply, context=context)
1513+ if journal_type == 'sale':
1514+ self._logger.info("SI No. %s created successfully." % inv_id)
1515+ elif journal_type == 'intermission':
1516+ self._logger.info("IVI No. %s created successfully." % inv_id)
1517+
1518+ def update_counterpart_inv(self, cr, uid, source, invoice_data, context=None):
1519+ """
1520+ Updates the Counterpart Invoice Number and Status (to be triggered at synchro time)
1521+ """
1522+ self._logger.info("+++ Update Counterpart Invoice data from %s" % source)
1523+ if context is None:
1524+ context = {}
1525+ invoice_dict = invoice_data.to_dict()
1526+ number = invoice_dict.get('number', '')
1527+ state = invoice_dict.get('state')
1528+ counterpart_inv_number = invoice_dict.get('counterpart_inv_number', '')
1529+ if state:
1530+ vals = {
1531+ 'counterpart_inv_status': state,
1532+ }
1533+ if number:
1534+ vals.update(
1535+ {
1536+ 'counterpart_inv_number': number,
1537+ }
1538+ )
1539+ inv_ids = []
1540+ if counterpart_inv_number:
1541+ inv_ids = self.search(cr, uid, [('number', '=', counterpart_inv_number)], limit=1, context=context)
1542+ elif not counterpart_inv_number and number:
1543+ # use case where the state of the IVO/STV is updated before the related IVI/SI has been opened
1544+ inv_ids = self.search(cr, uid, [('counterpart_inv_number', '=', number)], limit=1, context=context)
1545+ if inv_ids:
1546+ self.write(cr, uid, inv_ids[0], vals, context=context)
1547+ # note that the "Counterpart Inv. Number" received is the "Number" of the invoice updated!
1548+ self._logger.info("account.invoice %s: Counterpart Invoice %s set to %s" % (counterpart_inv_number, number, state))
1549+
1550+account_invoice_sync()
1551+
1552+
1553+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1554
1555=== modified file 'bin/addons/account_override/account_invoice_view.xml'
1556--- bin/addons/account_override/account_invoice_view.xml 2018-02-01 13:22:25 +0000
1557+++ bin/addons/account_override/account_invoice_view.xml 2019-07-30 10:04:49 +0000
1558@@ -43,17 +43,12 @@
1559 <field name="line_number"/>
1560 </xpath>
1561 <xpath expr="//field[@name='date_invoice']" position="before">
1562- <field name="document_date"/>
1563+ <field name="document_date" />
1564 </xpath>
1565 <xpath expr="//field[@name='period_id']" position="replace">
1566 </xpath>
1567 <xpath expr="//label[@string='(keep empty to use the current period)']" position="replace">
1568 </xpath>
1569- <button name='invoice_cancel' position="replace">
1570- <!-- The widget boolean permit to the attrs to work efficiently -->
1571- <field name="purchase_ids" invisible="1" widget="boolean" readonly="1" />
1572- <button name="invoice_cancel" string="Cancel" icon="gtk-cancel" attrs="{'invisible': ['|', ('state', 'in', ['open', 'paid']), ('purchase_ids', '!=', False)]}" confirm="You are about to cancel this invoice. Do you want to proceed?"/>
1573- </button>
1574 <xpath expr="//button[@name='invoice_open']" position="after" >
1575 <button name="button_split_invoice" states="draft,proforma2" type="object" string="Split Invoice" icon="gtk-cut"/>
1576 <newline/>
1577@@ -155,6 +150,12 @@
1578 </xpath>
1579 <xpath expr="/search/group[1]/filter[@name='unpaid']" position="after">
1580 <filter name="paid" icon="terp-dolar" string="Paid" domain="[('state', '=', 'paid')]"/>
1581+ <filter name="closed" icon="terp-dialog-close" string="Closed" domain="[('state', '=', 'inv_close')]" />
1582+ <separator orientation="vertical"/>
1583+ <filter name="not_imported" icon="gtk-cancel" string="Not imported" domain="[('imported_state', '=', 'not')]"/>
1584+ <filter name="partial" icon="terp-dolar_ok!" string="Partially imported" domain="[('imported_state', '=', 'partial')]"/>
1585+ <filter name="imported" icon="gtk-apply" string="Imported" domain="[('imported_state', '=', 'imported')]"/>
1586+ <separator orientation="vertical"/>
1587 </xpath>
1588 </data>
1589 </field>
1590@@ -278,11 +279,9 @@
1591 <field name="residual"/>
1592 </group>
1593 <group col="8" colspan="4">
1594- <button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" icon="gtk-cancel"/>
1595- <button name="%(account.action_account_invoice_refund)d" type='action' string='Refund' states='open,paid' icon="gtk-execute"/>
1596- <button name='%(account.action_account_state_open)d' type='action' string='Re-Open' states='paid' icon="gtk-convert" groups="base.group_no_one"/>
1597+ <button name="%(account.action_account_invoice_refund)d" type='action' string='Refund' states='open,paid,inv_close' icon="gtk-execute"/>
1598 <button name="invoice_open" type="object" states="draft,proforma2" string="Validate" icon="gtk-go-forward"/>
1599- <button name="%(account.account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,proforma,sale,proforma2"/>
1600+ <button name="%(account.account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,inv_close,proforma,sale,proforma2"/>
1601 </group>
1602 </page>
1603 <page string="Other Info">
1604@@ -429,13 +428,10 @@
1605 <field name="state"/>
1606 <field name="amount_total"/>
1607 </group>
1608- <group col="2" colspan="4" states="draft">
1609+ <group col="4" colspan="4">
1610 <label string=""/>
1611 <button name="invoice_open" type="object" states="draft" string="Validate" icon="gtk-go-forward"/>
1612- </group>
1613- <group col="2" colspan="4" states="open,paid">
1614- <button name="invoice_cancel" states="open" string="Cancel" icon="gtk-cancel" confirm="Do you confirm Donation received cancellation?"/>
1615- <button name="%(account.account_invoices)d" string="Print Donation" type="action" icon="gtk-print" states="open,paid"/>
1616+ <button name="%(account.account_invoices)d" string="Print Donation" type="action" icon="gtk-print" states="open,paid,inv_close"/>
1617 </group>
1618 </page>
1619 </notebook>
1620@@ -482,13 +478,30 @@
1621 <field name="type" invisible="1"/>
1622 <field name="is_intermission" invisible="1"/>
1623 <!-- US-370: use the change currency button -->
1624- <field name="currency_id" width="50"/>
1625- <button name="%(account.action_account_change_currency)d" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" />
1626+ <field name="currency_id" width="50"
1627+ attrs="{'readonly': ['|', '|',
1628+ ('state', '!=', 'draft'),
1629+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True),
1630+ '&amp;', ('type', '=', 'out_invoice'), ('from_supply', '=', True)]}"/>
1631+ <button name="%(account.action_account_change_currency)d" type="action"
1632+ icon="terp-stock_effects-object-colorize" string="Change"
1633+ attrs="{'invisible': [('state', '!=', 'draft')],
1634+ 'readonly': ['|', '|',
1635+ ('state', '!=', 'draft'),
1636+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True),
1637+ '&amp;', ('type', '=', 'out_invoice'), ('from_supply', '=', True)]}" />
1638 <newline/>
1639- <field string="Partner" name="partner_id" on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id, False, is_intermission, False, False, account_id)" domain="[('by_invoice_type', '=', True), ('partner_type', '=', 'intermission')]" context="{'type': context.get('type')}"/>
1640+ <field string="Partner" name="partner_id"
1641+ on_change="onchange_partner_id(type,partner_id, date_invoice,payment_term, partner_bank_id, company_id, False, is_intermission, False, False, account_id)"
1642+ domain="[('by_invoice_type', '=', True), ('partner_type', '=', 'intermission')]"
1643+ context="{'type': context.get('type')}"
1644+ attrs="{'readonly': ['|', '|',
1645+ ('state', '!=', 'draft'),
1646+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True),
1647+ '&amp;', ('type', '=', 'out_invoice'), ('from_supply', '=', True)]}"/>
1648 <field domain="[('partner_id','=',partner_id)]" name="address_invoice_id" string="Partner address"/>
1649 <newline/>
1650- <field name="document_date" string="I/MI voucher date"/>
1651+ <field name="document_date" string="I/MI voucher date" />
1652 <field name="date_invoice"/>
1653 <newline/>
1654 <group colspan="8" col="8" attrs="{'invisible': [('analytic_distribution_id', '=', False)]}">
1655@@ -505,13 +518,20 @@
1656 <notebook colspan="4">
1657 <page string="Invoice">
1658 <field name="account_id" domain="[('company_id', '=', company_id), ('restricted_area', '=', 'intermission_header')]"/>
1659- <field name="name" string="Reference"/>
1660+ <field name="name" string="Reference"
1661+ attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('from_supply', '=', True)]}"/>
1662 <newline/>
1663 <group name="import" string=" Import Lines " colspan="4" col="4" attrs="{'invisible':[('state', '!=', 'draft')]}">
1664- <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object" attrs="{'invisible':[('state', '!=', 'draft')]}"/>
1665+ <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object"
1666+ attrs="{'invisible': [('state', '!=', 'draft')],
1667+ 'readonly': ['|',
1668+ ('from_supply', '=', True),
1669+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
1670 </group>
1671- <field colspan="4" name="invoice_line" nolabel="1" widget="one2many_list" context="{'is_intermission': True}">
1672- <tree string="Intermission Voucher Lines">
1673+ <field colspan="4" name="invoice_line" nolabel="1" widget="one2many_list" context="{'is_intermission': True, 'from_inv_form': True}">
1674+ <tree string="Intermission Voucher Lines"
1675+ colors="red:analytic_distribution_state == 'invalid' or inactive_product == True;black:inactive_product == False and analytic_distribution_state in ('none', 'valid')">
1676+ <field name="line_number"/>
1677 <field name="is_corrected" invisible="1"/>
1678 <button name="button_open_analytic_lines" string="Have been corrected" type="object" icon="terp-mail-" attrs="{'invisible': [('is_corrected', '=', False)]}"/>
1679 <field name="name"/>
1680@@ -523,7 +543,7 @@
1681 <field name="analytic_distribution_state" invisible="1"/>
1682 <field name="have_analytic_distribution_from_header" invisible="1"/>
1683 <field name="quantity"/>
1684- <field name="uos_id" string="UOM" invisible="1" />
1685+ <field name="uos_id" string="UOM"/>
1686 <field name="price_unit"/>
1687 <field name="price_subtotal"/>
1688 <field name="inactive_product" invisible="1" />
1689@@ -532,12 +552,42 @@
1690 <form string="Intermission Voucher Lines">
1691 <notebook>
1692 <page string="Line">
1693- <field name="name" default_focus="1"/>
1694+ <field name="from_supply" invisible="1"/>
1695+ <field name="synced" invisible="1"/>
1696+ <field name="invoice_type" invisible="1"/>
1697+ <field name="product_id"
1698+ on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})"
1699+ default_focus="1"
1700+ attrs="{'readonly': ['|',
1701+ ('from_supply', '=', True),
1702+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}" />
1703+ <field name="uos_id"
1704+ on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.address_invoice_id, parent.currency_id, {'company_id': parent.company_id})"
1705+ attrs="{'readonly': ['|',
1706+ ('from_supply', '=', True),
1707+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"
1708+ />
1709+ <field name="quantity" attrs="{'readonly': ['|',
1710+ ('from_supply', '=', True),
1711+ '&amp;', ('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
1712+ <field name="price_unit" attrs="{'readonly': [('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
1713+ <field name="discount" groups="base.group_extended" attrs="{'readonly': [('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
1714+ <field name="name" colspan="4"/>
1715 <field name="account_id" domain="[('restricted_area', '=', 'intermission_lines')]"/>
1716- <field name="quantity"/>
1717- <field name="uos_id" string="UOM" invisible="1"/>
1718- <field name="price_unit"/>
1719- <field name="price_subtotal"/>
1720+ <group colspan="6">
1721+ <field name="analytic_distribution_state" invisible="1"/>
1722+ <field name="newline" invisible="1" />
1723+ <field name="is_allocatable" invisible="1"/>
1724+ <group colspan="2" col="4">
1725+ <button name="button_analytic_distribution" string="Change analytic distribution"
1726+ type="object" icon="terp-check" context="context" colspan="1"
1727+ attrs="{'invisible': ['|','|', ('newline', '=', True), ('analytic_distribution_state', '!=', 'valid'), ('is_allocatable', '=', False)]}" />
1728+ <button name="button_analytic_distribution" string="Change analytic distribution"
1729+ type="object" icon="terp-emblem-important" context="context" colspan="1"
1730+ attrs="{'invisible': ['|','|', ('newline', '=', True), ('analytic_distribution_state', '=', 'valid'), ('is_allocatable', '=', False)]}" />
1731+ <field name="analytic_distribution_state_recap" attrs="{'invisible': [('is_allocatable', '=', False)]}"/>
1732+ </group>
1733+ </group>
1734 </page>
1735 <page string="Notes">
1736 <field name="note" nolabel="1" colspan="4"/>
1737@@ -550,28 +600,64 @@
1738 <field name="state"/>
1739 <field name="amount_total"/>
1740 </group>
1741- <group col="2" colspan="4" states="draft">
1742+ <group col="6" colspan="4" states="draft">
1743 <label string=""/>
1744- <button name="invoice_open" type="object" states="draft" string="Validate" icon="gtk-go-forward"/>
1745+ <!-- add a confirmation step only for IVOs when "synced" isn't selected -->
1746+ <button name="invoice_open" type="object" string="Validate"
1747+ icon="gtk-go-forward"
1748+ attrs="{'invisible': ['|',
1749+ ('state', '!=', 'draft'),
1750+ ('type', '=', 'out_invoice')]}"/>
1751+ <button name="invoice_open_with_confirmation" type="object" string="Validate"
1752+ icon="gtk-go-forward"
1753+ confirm="Are you sure you want to validate this invoice without synchronization?"
1754+ attrs="{'invisible': ['|', '|',
1755+ ('state', '!=', 'draft'),
1756+ ('type', '!=', 'out_invoice'),
1757+ ('synced', '=', True)]}"/>
1758+ <button name="invoice_open_with_sync_confirmation" type="object" string="Validate"
1759+ icon="gtk-go-forward"
1760+ confirm="This invoice will sync to its counterpart instance."
1761+ attrs="{'invisible': ['|', '|',
1762+ ('state', '!=', 'draft'),
1763+ ('type', '!=', 'out_invoice'),
1764+ ('synced', '=', False)]}"/>
1765 </group>
1766- <group col="2" colspan="4" states="open,paid">
1767+ <group col="6" colspan="4" states="open,paid,inv_close">
1768 <label string=""/>
1769- <button name="%(account.account_invoices)d" string="Print Intermission Voucher" type="action" icon="gtk-print" states="open,paid"/>
1770+ <button name="%(account.action_account_invoice_refund)d" type="action" string="Refund" icon="gtk-execute"
1771+ attrs="{'invisible': [('state', '!=', 'open')]}"/>
1772+ <button name="%(account.account_invoices)d" string="Print Intermission Voucher" type="action" icon="gtk-print" states="open,paid,inv_close"/>
1773 </group>
1774 </page>
1775 <page string="Other Info">
1776 <field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)" widget="selection" groups="base.group_multi_company"/>
1777 <newline/>
1778 <field name="date_due"/>
1779- <field name="user_id"/>
1780+ <field name="user_id"
1781+ attrs="{'readonly': ['|', '|',
1782+ ('state', '!=', 'draft'),
1783+ '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True),
1784+ '&amp;', ('type', '=', 'out_invoice'), ('from_supply', '=', True)]}"/>
1785 <newline/>
1786 <field domain="[('partner_id.ref_companies', 'in', [company_id])]" name="partner_bank_id" />
1787- <field name="origin"/>
1788+ <field name="origin" attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('from_supply', '=', True)]}"/>
1789 <field colspan="4" domain="[('partner_id','=',partner_id)]" name="address_contact_id" />
1790 <field name="move_id" />
1791 <separator colspan="4" string="Additional Information"/>
1792 <field colspan="4" name="comment" nolabel="1"/>
1793 </page>
1794+ <page string="Counterpart Invoice">
1795+ <field name="from_supply" invisible="1"/>
1796+ <field name="synced"
1797+ attrs="{'readonly': ['|', '|',
1798+ ('from_supply', '=', True),
1799+ ('state', '!=', 'draft'),
1800+ ('type', '=', 'in_invoice')]}"/> <!-- IVI can never be ticked as "Synced" manually -->
1801+ <newline/>
1802+ <field name="counterpart_inv_number"/>
1803+ <field name="counterpart_inv_status"/>
1804+ </page>
1805 </notebook>
1806 </form>
1807 </field>
1808@@ -610,7 +696,11 @@
1809 <button name="invoice_proforma2" position="replace"/>
1810 <xpath expr="/form/notebook/page[@string='Invoice']/field[@name='invoice_line']" position="before" >
1811 <group name="import" string=" Import Lines " colspan="4" col="4" attrs="{'invisible':[('state', '!=', 'draft')]}">
1812- <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object" attrs="{'invisible':[('state', '!=', 'draft')]}"/>
1813+ <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object"
1814+ attrs="{'invisible': [('state', '!=', 'draft')],
1815+ 'readonly': [('type', '=', 'out_invoice'),
1816+ ('from_supply', '=', True),
1817+ ('partner_type', 'in', ('intermission', 'section'))]}"/>
1818 </group>
1819 </xpath>
1820 <xpath expr="/form/notebook/page[@string='Invoice']/group[3]" position="replace">
1821@@ -623,12 +713,35 @@
1822 <field name="residual"/>
1823 <field name="is_debit_note" invisible="1"/>
1824 </group>
1825+ <field name="partner_type" invisible="1"/>
1826 <group col="8" colspan="4">
1827- <button name="invoice_cancel" states="proforma2,open" string="Cancel" icon="gtk-cancel"/>
1828 <button name="%(account.action_account_invoice_refund)d" type='action' string='Refund' icon="gtk-execute" attrs="{'invisible': ['|', ('state', 'in', ['draft']), ('type', 'in', ['in_refund', 'out_refund'])]}"/>
1829- <button name='%(account.action_account_state_open)d' type='action' string='Re-Open' states='paid' icon="gtk-convert" groups="base.group_no_one"/>
1830- <button name="invoice_open" states="draft,proforma2" string="Validate" icon="gtk-go-forward" type="object"/>
1831- <button name="%(account.account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,proforma,sale,proforma2"/>
1832+ <!-- add a confirmation step only for STV (not for Customer Refunds)
1833+ when the partner type is compatible with a synchro but "synced" isn't ticked -->
1834+ <button name="invoice_open" type="object" string="Validate"
1835+ icon="gtk-go-forward"
1836+ attrs="{'invisible': ['|',
1837+ ('state', '!=', 'draft'),
1838+ '&amp;',
1839+ ('type', '=', 'out_invoice'), ('partner_type', 'in', ('intermission', 'section')) ]}"/>
1840+ <button name="invoice_open_with_confirmation" type="object" string="Validate"
1841+ icon="gtk-go-forward"
1842+ confirm="Are you sure you want to validate this invoice without synchronization?"
1843+ attrs="{'invisible': ['|', '|', '|',
1844+ ('state', '!=', 'draft'),
1845+ ('type', '!=', 'out_invoice'),
1846+ ('synced', '=', True),
1847+ ('partner_type', 'not in', ('intermission', 'section'))]}"/>
1848+
1849+ <button name="invoice_open_with_sync_confirmation" type="object" string="Validate"
1850+ icon="gtk-go-forward"
1851+ confirm="This invoice will sync to its counterpart instance."
1852+ attrs="{'invisible': ['|', '|', '|',
1853+ ('state', '!=', 'draft'),
1854+ ('type', '!=', 'out_invoice'),
1855+ ('synced', '=', False),
1856+ ('partner_type', 'not in', ('intermission', 'section'))]}"/>
1857+ <button name="%(account.account_invoices)d" string="Print Invoice" type="action" icon="gtk-print" states="open,paid,inv_close,proforma,sale,proforma2"/>
1858 </group>
1859 </xpath>
1860 <xpath expr="//page[@string='Payments']" position="replace">
1861@@ -813,7 +926,7 @@
1862 <field eval="False" name="view_id"/>
1863 <!-- US-2704 if the domain change, do not forget to update the domain of account_board_supplier_invoice_draft in finance/board_account_view.xml -->
1864 <field name="domain">[('type','=','in_invoice'), ('is_direct_invoice', '=', False), ('is_inkind_donation', '=', False), ('is_debit_note', "=", False), ('is_intermission', '=', False)]</field>
1865- <field name="context">{'type':'in_invoice', 'journal_type': 'purchase'}</field>
1866+ <field name="context">{'type': 'in_invoice', 'journal_type': 'purchase', 'from_inv_form': True}</field>
1867 <field name="search_view_id" ref="account.view_account_invoice_filter"/>
1868 <field name="help">With Supplier Invoices you can enter and manage invoices issued by your suppliers.
1869 OpenERP can also generate draft invoices automatically from purchase orders or receipts. This way, you can control the invoice
1870@@ -848,7 +961,7 @@
1871 rml="account_override/report/account_print_invoice.rml"
1872 string="Print report"
1873 target_filename="${eval(_get_invoice_report_name)}"
1874- attachment="(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/',''))"
1875+ attachment="(object.state in ('open','paid', 'inv_close')) and ('INV'+(object.number or '').replace('/',''))"
1876 attachment_use="1"
1877 multi="True"/>
1878
1879
1880=== modified file 'bin/addons/account_override/invoice.py'
1881--- bin/addons/account_override/invoice.py 2019-05-21 08:19:49 +0000
1882+++ bin/addons/account_override/invoice.py 2019-07-30 10:04:49 +0000
1883@@ -28,12 +28,14 @@
1884 from tools.translate import _
1885 from lxml import etree
1886 from datetime import datetime
1887+from msf_partner import PARTNER_TYPE
1888 import re
1889 import netsvc
1890
1891
1892 import decimal_precision as dp
1893
1894+
1895 class account_invoice(osv.osv):
1896 _name = 'account.invoice'
1897 _inherit = 'account.invoice'
1898@@ -223,9 +225,9 @@
1899 'sequence_id': fields.many2one('ir.sequence', string='Lines Sequence', ondelete='cascade',
1900 help="This field contains the information related to the numbering of the lines of this order."),
1901 'date_invoice': fields.date('Posting Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
1902- 'close':[('readonly',True)]}, select=True),
1903+ 'inv_close':[('readonly',True)]}, select=True),
1904 'document_date': fields.date('Document Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
1905- 'close':[('readonly',True)]}, select=True),
1906+ 'inv_close':[('readonly',True)]}, select=True),
1907 'is_debit_note': fields.boolean(string="Is a Debit Note?"),
1908 'is_inkind_donation': fields.boolean(string="Is an In-kind Donation?"),
1909 'is_intermission': fields.boolean(string="Is an Intermission Voucher?"),
1910@@ -251,6 +253,8 @@
1911 'st_lines': fields.one2many('account.bank.statement.line', 'invoice_id', string="Register lines", readonly=True, help="Register lines that have a link to this invoice."),
1912 'can_merge_lines': fields.function(_get_can_merge_lines, method=True, type='boolean', string='Can merge lines ?'),
1913 'is_merged_by_account': fields.boolean("Is merged by account"),
1914+ 'partner_type': fields.related('partner_id', 'partner_type', string='Partner Type', type='selection',
1915+ selection=PARTNER_TYPE, readonly=True, store=False),
1916 }
1917
1918 _defaults = {
1919@@ -814,6 +818,35 @@
1920 'view_id': supplier_view_id}
1921 return super(account_invoice, self).log(cr, uid, inv_id, message, secondary, action_xmlid, local_ctx)
1922
1923+ def _check_tax_allowed(self, cr, uid, ids, context=None):
1924+ """
1925+ Raises an error if a tax is used with an Intermission or Intersection partner
1926+ """
1927+ if context is None:
1928+ context = {}
1929+ if isinstance(ids, (int, long)):
1930+ ids = [ids]
1931+ warning_msg = _('Taxes are forbidden with Intermission and Intersection partners.')
1932+ for inv in self.browse(cr, uid, ids, fields_to_fetch=['partner_id', 'tax_line', 'invoice_line'], context=context):
1933+ if inv.partner_id.partner_type in ('intermission', 'section'):
1934+ if inv.tax_line:
1935+ raise osv.except_osv(_('Warning'), warning_msg)
1936+ for inv_line in inv.invoice_line:
1937+ if inv_line.invoice_line_tax_id:
1938+ raise osv.except_osv(_('Warning'), warning_msg)
1939+
1940+ def _check_sync_allowed(self, cr, uid, ids, context=None):
1941+ """
1942+ Raises an error if the doc is marked as Synced whereas the Partner is neither Intermission nor Intersection
1943+ """
1944+ if context is None:
1945+ context = {}
1946+ if isinstance(ids, (int, long)):
1947+ ids = [ids]
1948+ for inv in self.browse(cr, uid, ids, fields_to_fetch=['partner_id', 'synced'], context=context):
1949+ if inv.partner_id.partner_type not in ('intermission', 'section') and inv.synced:
1950+ raise osv.except_osv(_('Warning'), _('Synchronized invoices are allowed only with Intermission and Intersection partners.'))
1951+
1952 def invoice_open(self, cr, uid, ids, context=None):
1953 """
1954 No longer fills the date automatically, but requires it to be set
1955@@ -823,6 +856,8 @@
1956 context = {}
1957 self._check_invoice_merged_lines(cr, uid, ids, context=context)
1958 self.check_accounts_for_partner(cr, uid, ids, context=context)
1959+ self._check_tax_allowed(cr, uid, ids, context=context)
1960+ self._check_sync_allowed(cr, uid, ids, context=context)
1961
1962 # Prepare workflow object
1963 wf_service = netsvc.LocalService("workflow")
1964@@ -871,6 +906,18 @@
1965
1966 return True
1967
1968+ def invoice_open_with_confirmation(self, cr, uid, ids, context=None):
1969+ """
1970+ Simply calls "invoice_open" (asking for confirmation is done at form level)
1971+ """
1972+ return self.invoice_open(cr, uid, ids, context=context)
1973+
1974+ def invoice_open_with_sync_confirmation(self, cr, uid, ids, context=None):
1975+ """
1976+ Simply calls "invoice_open" (asking for confirmation is done at form level)
1977+ """
1978+ return self.invoice_open(cr, uid, ids, context=context)
1979+
1980 def action_reconcile_imported_invoice(self, cr, uid, ids, context=None):
1981 """
1982 Reconcile each imported invoice with its attached invoice line
1983@@ -1107,6 +1154,21 @@
1984 self._check_header_account(cr, uid, inv_id, inv_type=inv_type, context=context)
1985 self._check_line_accounts(cr, uid, inv_id, inv_type=inv_type, context=context)
1986
1987+ def update_counterpart_inv_status(self, cr, uid, ids, context=None):
1988+ """
1989+ In case an IVO or STV, with an Intermission or Intersection partner and set as Synchronized, is being opened:
1990+ set the Counterpart Invoice Status to Draft automatically
1991+ """
1992+ if context is None:
1993+ context = {}
1994+ if isinstance(ids, (int, long)):
1995+ ids = [ids]
1996+ inv_fields = ['type', 'is_debit_note', 'synced', 'partner_type', 'counterpart_inv_status']
1997+ for inv in self.browse(cr, uid, ids, fields_to_fetch=inv_fields, context=context):
1998+ is_ivo_or_stv = inv.type == 'out_invoice' and not inv.is_debit_note
1999+ if is_ivo_or_stv and inv.synced and inv.partner_type in ('intermission', 'section') and not inv.counterpart_inv_status:
2000+ self.write(cr, uid, inv.id, {'counterpart_inv_status': 'draft'}, context=context)
2001+
2002 def action_open_invoice(self, cr, uid, ids, context=None, *args):
2003 """
2004 Give function to use when changing invoice to open state
2005@@ -1124,6 +1186,7 @@
2006 if not self.action_reconcile_imported_invoice(cr, uid, ids, context):
2007 return False
2008 self.check_domain_restrictions(cr, uid, ids, context) # raises an error if one unauthorized element is used
2009+ self.update_counterpart_inv_status(cr, uid, ids, context=context)
2010 return True
2011
2012
2013@@ -1629,6 +1692,13 @@
2014 relation="account.analytic.account", string='Funding Pool',
2015 states={'draft': [('readonly', False)]},
2016 help="Field used for import only"),
2017+ 'from_supply': fields.related('invoice_id', 'from_supply', type='boolean', string='From Supply', readonly=True, store=False),
2018+ 'synced': fields.related('invoice_id', 'synced', type='boolean', string='Synchronized', readonly=True, store=False),
2019+ 'invoice_type': fields.related('invoice_id', 'type', string='Invoice Type', type='selection', readonly=True, store=False,
2020+ selection=[('out_invoice', 'Customer Invoice'),
2021+ ('in_invoice', 'Supplier Invoice'),
2022+ ('out_refund', 'Customer Refund'),
2023+ ('in_refund', 'Supplier Refund')]),
2024 }
2025
2026 _defaults = {
2027@@ -1661,6 +1731,26 @@
2028 if abs(qty) >= too_big_amount or abs(pu) >= too_big_amount or abs(discount) >= too_big_amount or abs(subtotal) >= too_big_amount:
2029 raise osv.except_osv(_('Error'), _('Line "%s": one of the numbers entered is more than 10 digits.') % inv_line.name)
2030
2031+ def _check_automated_invoice(self, cr, uid, invoice_id, context=None):
2032+ """
2033+ Prevents the creation of manual inv. lines if the related invoice has been generated via Sync. or
2034+ by a Supply workflow (for Intermission/Intersection partners)
2035+ """
2036+ if context is None:
2037+ context = {}
2038+ if self._name == 'wizard.account.invoice.line':
2039+ # no check on Direct Invoice
2040+ return True
2041+ inv_obj = self.pool.get('account.invoice')
2042+ if invoice_id:
2043+ inv_fields = ['from_supply', 'synced', 'type', 'is_inkind_donation', 'partner_type']
2044+ inv = inv_obj.browse(cr, uid, invoice_id, fields_to_fetch=inv_fields, context=context)
2045+ ivi_or_si_synced = inv.type == 'in_invoice' and not inv.is_inkind_donation and inv.synced
2046+ intermission_or_section_from_supply = inv.partner_type in ('intermission', 'section') and inv.from_supply
2047+ if context.get('from_inv_form') and (ivi_or_si_synced or intermission_or_section_from_supply):
2048+ raise osv.except_osv(_('Error'), _('This document has been generated via a Supply workflow or via synchronization. '
2049+ 'You can\'t add lines manually.'))
2050+
2051 def create(self, cr, uid, vals, context=None):
2052 """
2053 Give a line_number to invoice line.
2054@@ -1671,6 +1761,7 @@
2055 """
2056 if not context:
2057 context = {}
2058+ self._check_automated_invoice(cr, uid, vals.get('invoice_id'), context=context)
2059 # Create new number with invoice sequence
2060 if vals.get('invoice_id') and self._name in ['account.invoice.line']:
2061 invoice = self.pool.get('account.invoice').browse(cr, uid, vals['invoice_id'])
2062@@ -1766,9 +1857,10 @@
2063
2064 def unlink(self, cr, uid, ids, context=None):
2065 """
2066- If invoice is a Direct Invoice and is in draft state:
2067- - compute total amount (check_total field)
2068- - write total to the register line
2069+ - If invoice is a Direct Invoice and is in draft state:
2070+ - compute total amount (check_total field)
2071+ - write total to the register line
2072+ - Raise error msg if the related inv. has been generated via Sync. or by a Supply workflow (for Intermission/Intersection partners)
2073 """
2074 if not context:
2075 context = {}
2076@@ -1776,16 +1868,25 @@
2077 ids = [ids]
2078 # Fetch all invoice_id to check
2079 direct_invoice_ids = []
2080+ invoice_ids = []
2081 abst_obj = self.pool.get('account.bank.statement.line')
2082 for invl in self.browse(cr, uid, ids):
2083- if invl.invoice_id and invl.invoice_id.is_direct_invoice and invl.invoice_id.state == 'draft':
2084- direct_invoice_ids.append(invl.invoice_id.id)
2085- # find account_bank_statement_lines and used this to delete the account_moves and associated records
2086- absl_ids = abst_obj.search(cr, uid,
2087- [('invoice_id','=',invl.invoice_id.id)],
2088- order='NO_ORDER')
2089- if absl_ids:
2090- abst_obj.unlink_moves(cr, uid, absl_ids, context)
2091+ if invl.invoice_id and invl.invoice_id.id not in invoice_ids:
2092+ invoice = invl.invoice_id
2093+ invoice_ids.append(invoice.id) # check each invoice only once
2094+ is_ivi_or_si = invoice.type == 'in_invoice' and not invoice.is_inkind_donation
2095+ if (is_ivi_or_si and invoice.synced) or (invoice.from_supply and invoice.partner_type in ('intermission', 'section')):
2096+ # will be displayed when trying to delete lines manually / merge lines / or split invoices
2097+ raise osv.except_osv(_('Error'), _("This document has been generated via a Supply workflow or via synchronization. "
2098+ "Existing lines can't be deleted."))
2099+ if invoice.is_direct_invoice and invoice.state == 'draft':
2100+ direct_invoice_ids.append(invoice.id)
2101+ # find account_bank_statement_lines and use this to delete the account_moves and associated records
2102+ absl_ids = abst_obj.search(cr, uid,
2103+ [('invoice_id', '=', invoice.id)],
2104+ order='NO_ORDER')
2105+ if absl_ids:
2106+ abst_obj.unlink_moves(cr, uid, absl_ids, context)
2107 # Normal behaviour
2108 res = super(account_invoice_line, self).unlink(cr, uid, ids, context)
2109 # See all direct invoice
2110
2111=== modified file 'bin/addons/account_override/report/report_open_invoices.py'
2112--- bin/addons/account_override/report/report_open_invoices.py 2017-08-04 15:15:29 +0000
2113+++ bin/addons/account_override/report/report_open_invoices.py 2019-07-30 10:04:49 +0000
2114@@ -71,10 +71,10 @@
2115 bg_id = context['background_id']
2116 self.percent = 0.05 # 5% of the process
2117 bg_obj.update_percent(self.cr, self.uid, [bg_id], self.percent)
2118- state = context.get('paid_invoice') and 'paid' or 'open'
2119+ states = context.get('paid_invoice') and ['paid', 'inv_close'] or ['open']
2120 for type in ['si_di', 'sr', 'donation', 'ivi', 'stv', 'cr', 'dn', 'ivo']:
2121 # determine the domain to use according to the report type and the doc type
2122- domain = [('state', '=', state)]
2123+ domain = [('state', 'in', states)]
2124 if context.get('paid_invoice') and beginning_date and ending_date:
2125 domain += [('date_invoice', '>=', beginning_date), ('date_invoice', '<=', ending_date)]
2126 if type == 'si_di':
2127
2128=== modified file 'bin/addons/account_voucher/report/account_voucher_sales_receipt_view.xml'
2129--- bin/addons/account_voucher/report/account_voucher_sales_receipt_view.xml 2011-01-14 00:11:01 +0000
2130+++ bin/addons/account_voucher/report/account_voucher_sales_receipt_view.xml 2019-07-30 10:04:49 +0000
2131@@ -7,7 +7,7 @@
2132 <field name="model">sale.receipt.report</field>
2133 <field name="type">tree</field>
2134 <field name="arch" type="xml">
2135- <tree colors="blue:state in ('draft');gray:state in ('cancel','paid');black:state in ('proforma','proforma2')" string="Sales Receipt Analysis">
2136+ <tree colors="blue:state in ('draft');gray:state in ('cancel','paid','inv_close');black:state in ('proforma','proforma2')" string="Sales Receipt Analysis">
2137 <field name="date" invisible="1"/>
2138 <field name="user_id" invisible="1"/>
2139 <field name="year" invisible="1"/>
2140@@ -112,4 +112,4 @@
2141 <menuitem action="action_sale_receipt_report_all" id="menu_action_sale_receipt_report_all" parent="account.menu_finance_statistic_report_statement" sequence="3"/>
2142
2143 </data>
2144-</openerp>
2145\ No newline at end of file
2146+</openerp>
2147
2148=== modified file 'bin/addons/analytic_distribution/account_invoice_refund.py'
2149--- bin/addons/analytic_distribution/account_invoice_refund.py 2018-05-14 12:41:04 +0000
2150+++ bin/addons/analytic_distribution/account_invoice_refund.py 2019-07-30 10:04:49 +0000
2151@@ -43,8 +43,10 @@
2152 # in case of a DI refund from a register line use the dir_invoice_id in context
2153 doc_to_refund_id = context.get('dir_invoice_id', False) or (context.get('active_ids') and context['active_ids'][0])
2154 if doc_to_refund_id:
2155- source_type = obj_inv.read(cr, uid, doc_to_refund_id, ['type'], context=context)['type']
2156- if source_type in ('in_invoice', 'in_refund'):
2157+ source = obj_inv.read(cr, uid, doc_to_refund_id, ['type', 'is_intermission'], context=context)
2158+ if source['is_intermission']:
2159+ args = [('type', '=', 'intermission')]
2160+ elif source['type'] in ('in_invoice', 'in_refund'):
2161 args = [('type', '=', 'purchase_refund')]
2162 if user.company_id.instance_id:
2163 args.append(('is_current_instance','=',True))
2164@@ -72,7 +74,7 @@
2165 jtype = isinstance(context['journal_type'], list) and context['journal_type'][0] or context['journal_type']
2166 if jtype in ('sale', 'sale_refund'):
2167 jtype = 'sale_refund'
2168- else:
2169+ elif jtype != 'intermission': # for IVO/IVI keep using the Interm. journal
2170 jtype = 'purchase_refund'
2171 user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
2172 for field in res['fields']:
2173@@ -86,13 +88,32 @@
2174 _columns = {
2175 'date': fields.date('Posting date'),
2176 'document_date': fields.date('Document Date', required=True),
2177+ 'is_intermission': fields.boolean("Wizard opened from an Intermission Voucher", readonly=True)
2178 }
2179
2180+ def _get_refund(self, cr, uid, context=None):
2181+ """
2182+ Returns the default value for the 'filter_refund' field depending on the context
2183+ """
2184+ if context is None:
2185+ context = {}
2186+ if context.get('is_intermission', False):
2187+ return 'modify'
2188+ return 'refund' # note that only the "Refund" option is available in DI
2189+
2190+ def _get_is_intermission(self, cr, uid, context=None):
2191+ """
2192+ Returns True if the wizard has been opened from an Intermission Voucher
2193+ """
2194+ if context is None:
2195+ context = {}
2196+ return context.get('is_intermission', False)
2197+
2198 _defaults = {
2199 'document_date': _get_document_date,
2200- #UTP-961: refund DI: only refund option is available
2201- 'filter_refund': 'refund',
2202+ 'filter_refund': _get_refund,
2203 'journal_id': _get_journal, # US-193
2204+ 'is_intermission': _get_is_intermission,
2205 }
2206
2207 def _hook_fields_for_modify_refund(self, cr, uid, *args):
2208
2209=== modified file 'bin/addons/analytic_distribution/account_invoice_view.xml'
2210--- bin/addons/analytic_distribution/account_invoice_view.xml 2018-02-23 14:35:29 +0000
2211+++ bin/addons/analytic_distribution/account_invoice_view.xml 2019-07-30 10:04:49 +0000
2212@@ -120,10 +120,16 @@
2213 <xpath expr="//separator[@string='Taxes']" position="replace" />
2214 <xpath expr="//field[@name='invoice_line_tax_id']" position="replace">
2215 <field name="vat_ok" invisible="1" />
2216+ <field name="synced" invisible="1" />
2217 <group colspan="4" col="4" attrs="{'invisible': [('vat_ok', '=', False)]}">
2218 <separator colspan="4" string="Taxes"/>
2219- <field colspan="4" name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]"
2220- nolabel="1"/>
2221+ <field colspan="4"
2222+ name="invoice_line_tax_id"
2223+ context="{'type': parent.type}"
2224+ domain="[('parent_id', '=', False), ('company_id', '=', parent.company_id)]"
2225+ nolabel="1"
2226+ attrs="{'readonly': [('invoice_type', '=', 'in_invoice'), ('synced', '=', True)]}"
2227+ />
2228 </group>
2229 </xpath>
2230 </data>
2231
2232=== modified file 'bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py'
2233--- bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2019-04-08 13:21:57 +0000
2234+++ bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2019-07-30 10:04:49 +0000
2235@@ -511,10 +511,10 @@
2236 if el.purchase_line_id and el.purchase_line_id.state not in ['draft', 'validated_n', 'validated']:
2237 res[el.id] = False
2238 # verify invoice state
2239- if el.invoice_id and el.invoice_id.state in ['open', 'paid']:
2240+ if el.invoice_id and el.invoice_id.state in ['open', 'paid', 'inv_close']:
2241 res[el.id] = False
2242 # verify invoice line state
2243- if el.invoice_line_id and el.invoice_line_id.invoice_id and el.invoice_line_id.invoice_id.state in ['open', 'paid']:
2244+ if el.invoice_line_id and el.invoice_line_id.invoice_id and el.invoice_line_id.invoice_id.state in ['open', 'paid', 'inv_close']:
2245 res[el.id] = False
2246 # verify commitment state
2247 if el.commitment_id and el.commitment_id.state in ['done']:
2248@@ -764,10 +764,10 @@
2249 if wiz.purchase_line_id and wiz.purchase_line_id.state not in ['draft', 'validated_n', 'validated']:
2250 raise osv.except_osv(_('Error'), _('You cannot change the distribution.'))
2251 # Verify that invoice is in good state if necessary
2252- if wiz.invoice_id and wiz.invoice_id.state in ['open', 'paid']:
2253+ if wiz.invoice_id and wiz.invoice_id.state in ['open', 'paid', 'inv_close']:
2254 raise osv.except_osv(_('Error'), _('You cannot change the distribution.'))
2255 # Verify that invoice from invoice line is in good state if necessary
2256- if wiz.invoice_line_id and wiz.invoice_line_id.invoice_id and wiz.invoice_line_id.invoice_id.state in ['open', 'paid']:
2257+ if wiz.invoice_line_id and wiz.invoice_line_id.invoice_id and wiz.invoice_line_id.invoice_id.state in ['open', 'paid', 'inv_close']:
2258 raise osv.except_osv(_('Error'), _('You cannot change the distribution.'))
2259 # Verify that commitment is in good state if necessary
2260 if wiz.commitment_id and wiz.commitment_id.state in ['done']:
2261
2262=== modified file 'bin/addons/finance/__openerp__.py'
2263--- bin/addons/finance/__openerp__.py 2017-11-07 09:20:43 +0000
2264+++ bin/addons/finance/__openerp__.py 2019-07-30 10:04:49 +0000
2265@@ -35,7 +35,6 @@
2266 "demo_xml" : [],
2267 "update_xml" : [
2268 'board_account_view.xml',
2269- 'account_invoice_workflow.xml',
2270 'account_view.xml',
2271 'account_invoice_view.xml',
2272 'account_analytic_line_view.xml',
2273
2274=== removed file 'bin/addons/finance/account_invoice_workflow.xml'
2275--- bin/addons/finance/account_invoice_workflow.xml 2014-03-14 15:47:48 +0000
2276+++ bin/addons/finance/account_invoice_workflow.xml 1970-01-01 00:00:00 +0000
2277@@ -1,13 +0,0 @@
2278-<?xml version="1.0" encoding="utf-8"?>
2279-<openerp>
2280- <data>
2281-
2282- <!-- Invoice workflow -->
2283- <record id="account.act_open" model="workflow.activity">
2284- <field name="wkf_id" ref="account.wkf"/>
2285- <field name="action">action_open_invoice()
2286- write({'state':'open'})</field>
2287- </record>
2288-
2289- </data>
2290-</openerp>
2291
2292=== modified file 'bin/addons/msf_audittrail/audittrail_invoice_data.yml'
2293--- bin/addons/msf_audittrail/audittrail_invoice_data.yml 2019-05-13 09:18:37 +0000
2294+++ bin/addons/msf_audittrail/audittrail_invoice_data.yml 2019-07-30 10:04:49 +0000
2295@@ -9,7 +9,8 @@
2296 # Create the rule
2297 fields = ['date_invoice', 'state', 'account_id', 'address_invoice_id', 'amount_to_pay', 'analytic_distribution_id',
2298 'check_total', 'comment', 'currency_id', 'fiscal_position', 'name', 'origin', 'partner_id',
2299- 'payment_ids', 'period_id', 'reference', 'reference_type', 'tax_line']
2300+ 'payment_ids', 'period_id', 'reference', 'reference_type', 'tax_line', 'synced', 'counterpart_inv_number',
2301+ 'counterpart_inv_status']
2302
2303 fields_ids = self.pool.get('ir.model.fields').search(cr, uid, [('model', '=' ,'account.invoice'), ('name', 'in', fields)], context=context)
2304
2305
2306=== modified file 'bin/addons/msf_outgoing/msf_outgoing.py'
2307--- bin/addons/msf_outgoing/msf_outgoing.py 2019-07-25 13:39:42 +0000
2308+++ bin/addons/msf_outgoing/msf_outgoing.py 2019-07-30 10:04:49 +0000
2309@@ -369,7 +369,8 @@
2310 'backshipment_id': fields.function(_vals_get, method=True, type='many2one', relation='shipment', string='Draft Shipment', multi='get_vals',),
2311 # added by Quentin https://bazaar.launchpad.net/~unifield-team/unifield-wm/trunk/revision/426.20.14
2312 'parent_id': fields.many2one('shipment', string='Parent shipment'),
2313- 'invoice_id': fields.many2one('account.invoice', string='Related invoice'),
2314+ # TODO check if really deprecated ?
2315+ 'invoice_id': fields.many2one('account.invoice', string='Related invoice (deprecated)'),
2316 'additional_items_ids': fields.one2many('shipment.additionalitems', 'shipment_id', string='Additional Items'),
2317 'picking_ids': fields.one2many(
2318 'stock.picking',
2319@@ -1579,6 +1580,7 @@
2320 'fiscal_position': partner.property_account_position.id,
2321 'date_invoice': context.get('date_inv', False) or today,
2322 'user_id': uid,
2323+ 'from_supply': True,
2324 }
2325
2326 cur_id = shipment.pack_family_memory_ids[0].currency_id.id
2327@@ -1613,32 +1615,7 @@
2328 if is_stv and partner.partner_type == 'internal':
2329 continue
2330
2331- if is_ivo or is_stv:
2332- origin_inv = 'origin' in invoice_vals and invoice_vals['origin'] or False
2333- fo = move and move.sale_line_id and move.sale_line_id.order_id or False
2334- new_origin = origin_inv and fo and "%s:%s" % (origin_inv, fo.name)
2335- new_origin = new_origin and new_origin[:64] # keep only 64 characters (because of the JE ref size)
2336- if new_origin:
2337- invoice_vals.update({'origin': new_origin})
2338- name_inv = 'name' in invoice_vals and invoice_vals['name'] or False
2339- new_name_inv = name_inv and fo and fo.client_order_ref and "%s : %s" % (fo.client_order_ref, name_inv)
2340- if new_name_inv:
2341- invoice_vals.update({'name': new_name_inv})
2342-
2343- invoice_id = invoice_obj.create(cr, uid, invoice_vals,
2344- context=context)
2345-
2346- # Change currency for the intermission invoice
2347- if shipment.partner_id2.partner_type == 'intermission':
2348- company_currency = company.currency_id and company.currency_id.id or False
2349- if not company_currency:
2350- raise osv.except_osv(_('Warning'), _('No company currency found!'))
2351- wiz_account_change = self.pool.get('account.change.currency').create(cr, uid, {'currency_id': company_currency}, context=context)
2352- self.pool.get('account.change.currency').change_currency(cr, uid, [wiz_account_change], context={'active_id': invoice_id})
2353-
2354- # Link the invoice to the shipment
2355- self.write(cr, uid, [shipment.id], {'invoice_id': invoice_id}, context=context)
2356-
2357+ invoice_id_by_fo = {}
2358 # For each stock moves, create an invoice line
2359 for pack in shipment.pack_family_memory_ids:
2360 for move in pack.move_lines:
2361@@ -1648,6 +1625,41 @@
2362 if move.sale_line_id and move.sale_line_id.order_id.order_policy != 'picking':
2363 continue
2364
2365+ # create 1 FO = 1 Invoice
2366+ order_id = move.sale_line_id and move.sale_line_id.order_id or False
2367+ if order_id not in invoice_id_by_fo:
2368+ new_invoice_vals = invoice_vals.copy()
2369+ if is_ivo or is_stv:
2370+ new_invoice_vals.update({'synced': True, }) # add "synced" tag for STV and IVO created from Supply flow
2371+ origin_inv = 'origin' in new_invoice_vals and new_invoice_vals['origin'] or False
2372+ fo = move and move.sale_line_id and move.sale_line_id.order_id or False
2373+ new_origin = origin_inv and fo and "%s:%s" % (origin_inv, fo.name)
2374+ new_origin = new_origin and new_origin[:64] # keep only 64 characters (because of the JE ref size)
2375+ if new_origin:
2376+ new_invoice_vals.update({'origin': new_origin})
2377+ name_inv = 'name' in new_invoice_vals and new_invoice_vals['name'] or False
2378+ new_name_inv = name_inv and fo and fo.client_order_ref and "%s : %s" % (fo.client_order_ref, name_inv)
2379+ if new_name_inv:
2380+ new_invoice_vals.update({'name': new_name_inv})
2381+ # this one does not work (check with new pps process US-5859)
2382+ #new_invoice_vals['picking_id'] = pack.draft_packing_id and pack.draft_packing_id.id or False
2383+
2384+ invoice_id = invoice_obj.create(cr, uid, new_invoice_vals,
2385+ context=context)
2386+
2387+ # Change currency for the intermission invoice
2388+ if shipment.partner_id2.partner_type == 'intermission':
2389+ company_currency = company.currency_id and company.currency_id.id or False
2390+ if not company_currency:
2391+ raise osv.except_osv(_('Warning'), _('No company currency found!'))
2392+ wiz_account_change = self.pool.get('account.change.currency').create(cr, uid, {'currency_id': company_currency}, context=context)
2393+ self.pool.get('account.change.currency').change_currency(cr, uid, [wiz_account_change], context={'active_id': invoice_id})
2394+
2395+ invoice_id_by_fo[order_id] = invoice_id
2396+
2397+ invoice_id = invoice_id_by_fo[order_id]
2398+
2399+
2400 origin = move.picking_id.name or ''
2401 if move.picking_id.origin:
2402 origin += ':' + move.picking_id.origin
2403@@ -1714,7 +1726,6 @@
2404 'analytic_distribution_id': distrib_id,
2405 }, context=context)
2406
2407- self.pool.get('shipment').write(cr, uid, [shipment.id], {'invoice_id': invoice_id}, context=context)
2408 if move.sale_line_id:
2409 sale_obj.write(cr, uid, [move.sale_line_id.order_id.id], {'invoice_ids': [(4, invoice_id)], })
2410 sale_line_obj.write(cr, uid, [move.sale_line_id.id], {'invoiced': True,
2411
2412=== modified file 'bin/addons/msf_profile/data/patches.xml'
2413--- bin/addons/msf_profile/data/patches.xml 2019-07-24 09:13:25 +0000
2414+++ bin/addons/msf_profile/data/patches.xml 2019-07-30 10:04:49 +0000
2415@@ -429,6 +429,7 @@
2416 <field name="method">us_6111_nr_field_closed_mar_2018</field>
2417 </record>
2418
2419+<<<<<<< TREE
2420 <!-- UF14.0 -->
2421 <record id="us_5952_delivered_closed_outs_to_delivered_state" model="patch.scripts">
2422 <field name="method">us_5952_delivered_closed_outs_to_delivered_state</field>
2423@@ -439,5 +440,16 @@
2424 </record>
2425
2426
2427+=======
2428+ <!-- UF14.0 -->
2429+ <record id="us_6075_set_paid_invoices_as_closed" model="patch.scripts">
2430+ <field name="method">us_6075_set_paid_invoices_as_closed</field>
2431+ </record>
2432+
2433+ <record id="us_6076_set_inv_as_from_supply" model="patch.scripts">
2434+ <field name="method">us_6076_set_inv_as_from_supply</field>
2435+ </record>
2436+
2437+>>>>>>> MERGE-SOURCE
2438 </data>
2439 </openerp>
2440
2441=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
2442--- bin/addons/msf_profile/i18n/fr_MF.po 2019-07-26 15:23:04 +0000
2443+++ bin/addons/msf_profile/i18n/fr_MF.po 2019-07-30 10:04:49 +0000
2444@@ -4239,12 +4239,6 @@
2445 msgid "Account tax charts"
2446 msgstr "Compte - Plans de taxes"
2447
2448-#. module: account
2449-#: model:ir.actions.act_window,name:account.action_account_state_open
2450-#: model:ir.model,name:account.model_account_state_open
2451-msgid "Account State Open"
2452-msgstr "Compte - Statut Ouvert"
2453-
2454 #. module: base
2455 #: selection:res.config.users,context_tz:0
2456 #: selection:res.users,context_tz:0
2457@@ -7017,11 +7011,6 @@
2458 "Vous pouvez en créer un à partir du menu :\n"
2459 "Configuration/Comptabilité Financière/Comptes/Journaux."
2460
2461-#. module: account
2462-#: view:account.state.open:0
2463-msgid "Are you sure you want to open this invoice ?"
2464-msgstr "Etes-vous sûr de vouloir ouvrir cette facture ?"
2465-
2466 #. modules: stock_move_tracking, stock, stock_override
2467 #: selection:report.stock.move,type:0
2468 #: selection:stock.location,chained_picking_type:0
2469@@ -8768,6 +8757,8 @@
2470 #: selection:wizard.import.product.line,state:0
2471 #: selection:product.mass.update,state:0
2472 #: selection:stock.expired.damaged.report,state:0
2473+#: selection:account.invoice,counterpart_inv_status:0
2474+#: selection:wizard.account.invoice,counterpart_inv_status:0
2475 #, python-format
2476 msgid "Draft"
2477 msgstr "Brouillon"
2478@@ -10378,6 +10369,7 @@
2479 #: selection:sale.donation.stock.moves,partner_type:0
2480 #: selection:sale.loan.stock.moves,partner_type:0
2481 #: selection:stock.picking,partner_type:0
2482+<<<<<<< TREE
2483 #: selection:sale.order,partner_type:0
2484 #: view:res.partner:0
2485 #: selection:res.partner,partner_type:0
2486@@ -10386,6 +10378,10 @@
2487 #: selection:purchase.order.change.currency,partner_type:0
2488 #: selection:sale.order.change.currency,partner_type:0
2489 #: selection:stock.picking,partner_type_stock_picking:0
2490+=======
2491+#: selection:account.invoice,partner_type:0
2492+#: selection:account.invoice.line,partner_type:0
2493+>>>>>>> MERGE-SOURCE
2494 #: code:addons/msf_supply_doc_export/wizard/supplier_performance_wizard.py:32
2495 #: field:supplier.performance.wizard,partner_type_intermission:0
2496 msgid "Intermission"
2497@@ -11219,7 +11215,7 @@
2498
2499 #. module: account
2500 #: help:account.invoice.refund,filter_refund:0
2501-msgid "Refund invoice base on this type. You can not Modify and Cancel if the invoice is already reconciled"
2502+msgid "Refund invoice based on this type. You can not Modify and Cancel if the invoice is already reconciled"
2503 msgstr "Facture d'Avoirs basée sur ce type. Vous ne pouvez pas Modifier ni Annuler si la facture est déjà lettrée."
2504
2505 #. module: base
2506@@ -12182,7 +12178,7 @@
2507 msgid "No envoi.ini file found in given ZIP file!"
2508 msgstr "Pas de fichier envoi.ini trouvé dans le fichier ZP donné!"
2509
2510-#. modules: msf_processes, account, register_accounting
2511+#. modules: msf_processes, account, register_accounting, account_override
2512 #: view:account.invoice:0
2513 #: selection:account.invoice,type:0
2514 #: selection:account.invoice.report,type:0
2515@@ -12196,6 +12192,7 @@
2516 #: code:addons/register_accounting/account_bank_statement.py:2735
2517 #: view:wizard.account.invoice:0
2518 #: selection:wizard.account.invoice,type:0
2519+#: selection:account.invoice.line,invoice_type:0
2520 #, python-format
2521 msgid "Supplier Invoice"
2522 msgstr "Facture Fournisseur"
2523@@ -13288,7 +13285,7 @@
2524 msgid "Automatic entry"
2525 msgstr "Ecriture Automatique"
2526
2527-#. modules: msf_order_date, purchase, msf_partner, stock_override, purchase_override, msf_config_locations, sale, account_override, analytic_distribution, msf_outgoing, msf_supply_doc_export
2528+#. modules: msf_order_date, purchase, msf_partner, stock_override, purchase_override, msf_config_locations, sale, account_override, analytic_distribution, msf_outgoing, msf_supply_doc_export, account
2529 #: selection:shipment,partner_type:0
2530 #: selection:purchase.order.merged.line,po_partner_type_stored:0
2531 #: selection:sale.loan.stock.moves,partner_type:0
2532@@ -13306,6 +13303,8 @@
2533 #: selection:sale.donation.stock.moves,partner_type:0
2534 #: selection:sale.order.change.currency,partner_type:0
2535 #: selection:stock.picking,partner_type_stock_picking:0
2536+#: selection:account.invoice,partner_type:0
2537+#: selection:account.invoice.line,partner_type:0
2538 #: code:addons/msf_supply_doc_export/wizard/supplier_performance_wizard.py:30
2539 #: field:supplier.performance.wizard,partner_type_external:0
2540 msgid "External"
2541@@ -14897,8 +14896,9 @@
2542 msgid "BARBADOS DOLLAR"
2543 msgstr "BARBADOS DOLLAR"
2544
2545-#. modules: account, register_accounting
2546+#. modules: account, register_accounting, account_override
2547 #: selection:account.invoice,type:0
2548+#: selection:account.invoice.line,invoice_type:0
2549 #: selection:account.invoice.report,type:0
2550 #: report:account.invoice2:0
2551 #: selection:report.invoice.created,type:0
2552@@ -15362,11 +15362,6 @@
2553 msgid "Destination not compatible with account"
2554 msgstr "Destination not compatible with account"
2555
2556-#. module: account
2557-#: model:ir.model,name:account.model_account_invoice_cancel
2558-msgid "Cancel the Selected Invoices"
2559-msgstr "Annuler les Factures Sélectionnées"
2560-
2561 #. modules: account, register_accounting
2562 #: view:account.bank.statement:0
2563 #: view:account.bank.statement:0
2564@@ -16841,8 +16836,12 @@
2565 msgid "%s update%s"
2566 msgstr "%s update%s"
2567
2568+<<<<<<< TREE
2569 #. modules: msf_budget, sales_followup, account, product_attributes, register_accounting, unifield_setup, object_query, order_types, mission_stock, msf_accrual, procurement_report, msf_partner, res_currency_tables, salr, sourcing, tender_flow, msf_doc_import, finance, msf_order_date, stock, product, stock_override
2570 #: view:account.state.open:0
2571+=======
2572+#. modules: msf_budget, sales_followup, account, product_attributes, register_accounting, unifield_setup, object_query, order_types, mission_stock, msf_accrual, procurement_report, msf_partner, res_currency_tables, salr, sourcing, tender_flow, msf_doc_import, finance, stock, product, stock_override
2573+>>>>>>> MERGE-SOURCE
2574 #: selection:mission.stock.wizard,split_stock:0
2575 #: selection:mission.stock.wizard,with_valuation:0
2576 #: view:wizard.accrual.reversal:0
2577@@ -17414,12 +17413,13 @@
2578 msgid "Warning!"
2579 msgstr "Avertissement!"
2580
2581-#. modules: purchase, sale
2582+#. modules: purchase, sale, account_override
2583 #: code:addons/purchase/purchase_workflow.py:549
2584 #: code:addons/sale/sale_workflow.py:529
2585+#: code:addons/account_override/invoice.py:829
2586 #, python-format
2587-msgid "You can't use taxes with an intermission partner."
2588-msgstr "Vous ne pouvez pas utiliser de taxes avec un partenaire intermission."
2589+msgid "Taxes are forbidden with Intermission and Intersection partners."
2590+msgstr "Les taxes sont interdites avec les partenaires Intermission et Intersection."
2591
2592 #. module: account
2593 #: model:ir.actions.act_window,name:account.action_account_fiscal_position_form
2594@@ -18873,8 +18873,9 @@
2595 msgid "Number of Packs"
2596 msgstr "Nombre de Colis"
2597
2598-#. module: account
2599+#. module: account, account_override
2600 #: code:addons/account/invoice.py:652
2601+#: code:addons/account_override/invoice.py:421
2602 #, python-format
2603 msgid "Can't find any account journal of %s type for this company.\n"
2604 "\n"
2605@@ -20404,8 +20405,9 @@
2606 msgid "Red color"
2607 msgstr "Red color"
2608
2609-#. module: base
2610+#. module: base, account
2611 #: selection:res.request,state:0
2612+#: code:addons/account/invoice.py:477
2613 msgid "closed"
2614 msgstr "fermé/fermée"
2615
2616@@ -21129,7 +21131,7 @@
2617 msgid "Free 1 Lines"
2618 msgstr "Option 1 Lignes"
2619
2620-#. modules: account_override, msf_outgoing, purchase_override, stock_override, sale, msf_order_date, purchase, msf_partner, msf_supply_doc_export
2621+#. modules: account_override, msf_outgoing, purchase_override, stock_override, sale, msf_order_date, purchase, msf_partner, msf_supply_doc_export, account
2622 #: field:account.account,has_partner_type_section:0
2623 #: selection:shipment,partner_type:0
2624 #: selection:purchase.order.merged.line,po_partner_type_stored:0
2625@@ -21137,6 +21139,8 @@
2626 #: selection:sale.loan.stock.moves,partner_type:0
2627 #: selection:stock.picking,partner_type:0
2628 #: selection:sale.order,partner_type:0
2629+#: selection:account.invoice,partner_type:0
2630+#: selection:account.invoice.line,partner_type:0
2631 #: view:res.partner:0
2632 #: selection:res.partner,partner_type:0
2633 #: selection:purchase.order,partner_type:0
2634@@ -25234,8 +25238,12 @@
2635 msgid "Europe/Bucharest"
2636 msgstr "Europe/Bucharest"
2637
2638+<<<<<<< TREE
2639 #. modules: msf_budget, account, account_payment, product_attributes, register_accounting, unifield_setup, object_query, order_types, mission_stock, msf_accrual, procurement_report, stock, msf_partner, salr, sourcing, tender_flow, msf_doc_import, finance, msf_supply_doc_export, product, stock_override, msf_order_date
2640 #: view:account.state.open:0
2641+=======
2642+#. modules: msf_budget, account, account_payment, product_attributes, register_accounting, unifield_setup, object_query, order_types, mission_stock, msf_accrual, procurement_report, stock, msf_partner, salr, sourcing, tender_flow, msf_doc_import, finance, msf_supply_doc_export, product, stock_override
2643+>>>>>>> MERGE-SOURCE
2644 #: view:account.payment.make.payment:0
2645 #: selection:mission.stock.wizard,split_stock:0
2646 #: selection:mission.stock.wizard,with_valuation:0
2647@@ -27110,6 +27118,8 @@
2648 #: field:purchase.report,invoiced:0
2649 #: view:account.invoice:0
2650 #: selection:account.direct.invoice.wizard,state:0
2651+#: selection:account.invoice,counterpart_inv_status:0
2652+#: selection:wizard.account.invoice,counterpart_inv_status:0
2653 msgid "Paid"
2654 msgstr "Payé"
2655
2656@@ -27898,12 +27908,6 @@
2657 msgid "Ratio"
2658 msgstr "Ratio"
2659
2660-#. module: account
2661-#: code:addons/account/wizard/account_state_open.py:37
2662-#, python-format
2663-msgid "Invoice is already reconciled"
2664-msgstr "La Facture est déjà lettrée"
2665-
2666 #. module: account_mcdb
2667 #: view:account.analytic.line:0
2668 msgid "Have been reallocated?"
2669@@ -30251,15 +30255,28 @@
2670 msgid "Certificate attached ?"
2671 msgstr "Certificat attaché ?"
2672
2673+<<<<<<< TREE
2674 #. modules: msf_supply_doc_export, sourcing, consumption_calculation, sale, sales_followup, msf_supply_doc_export, purchase
2675+=======
2676+#. modules: msf_supply_doc_export, sourcing, consumption_calculation, sale, sales_followup, msf_supply_doc_export, account_override,account,register_accounting
2677+>>>>>>> MERGE-SOURCE
2678 #: field:po.follow.up,closed_ok:0
2679 #: selection:real.average.consumption,state:0
2680 #: selection:po.follow.up,state:0
2681 #: selection:sale.order.leave.close,order_state:0
2682 #: field:ir.followup.location.wizard,closed_ok:0
2683 #: selection:sale.order.line,sale_order_state:0
2684+<<<<<<< TREE
2685 #: selection:sale.order.line,state_to_display:0
2686 #: selection:purchase.order.line,state_to_display:0
2687+=======
2688+#: selection:account.invoice,state:0
2689+#: selection:account.invoice.report,state:0
2690+#: selection:report.invoice.created,state:0
2691+#: view:account.invoice:0
2692+#: selection:wizard.account.invoice,state:0
2693+#: selection:account.invoice,counterpart_inv_status:0
2694+>>>>>>> MERGE-SOURCE
2695 msgid "Closed"
2696 msgstr "Fermé"
2697
2698@@ -33691,7 +33708,6 @@
2699 msgstr "Importer PCM à partir de feuilles Excel"
2700
2701 #. modules: account, sale
2702-#: view:account.state.open:0
2703 #: model:ir.actions.act_window,name:sale.action_view_sale_open_invoice
2704 #: view:sale.open.invoice:0
2705 msgid "Open Invoice"
2706@@ -33780,11 +33796,6 @@
2707 "* a basic mechanism to easily plug various automated payment.\n"
2708 " "
2709
2710-#. module: account
2711-#: view:account.invoice.cancel:0
2712-msgid "Cancel Invoices"
2713-msgstr "Annuler les Factures"
2714-
2715 #. module: base
2716 #: field:partner.sms.send,text:0
2717 msgid "SMS Message"
2718@@ -41110,12 +41121,6 @@
2719 msgid "Sync Flag"
2720 msgstr "Sync Flag"
2721
2722-#. module: account
2723-#: view:account.invoice.cancel:0
2724-#: model:ir.actions.act_window,name:account.action_account_invoice_cancel
2725-msgid "Cancel Selected Invoices"
2726-msgstr "Annuler les Factures Sélectionnées"
2727-
2728 #. module: account_override
2729 #: code:addons/account_override/account.py:624
2730 #, python-format
2731@@ -47194,7 +47199,11 @@
2732 msgid "Metadata"
2733 msgstr "Métadonnées"
2734
2735+<<<<<<< TREE
2736 #. modules: msf_order_date, purchase, msf_outgoing, msf_partner, stock_override, purchase_override, sale, account_override, analytic_distribution, product_attributes, msf_supply_doc_export
2737+=======
2738+#. modules: msf_order_date, purchase, msf_outgoing, msf_partner, stock_override, purchase_override, sale, account_override, analytic_distribution, msf_supply_doc_export, account
2739+>>>>>>> MERGE-SOURCE
2740 #: field:account.account,has_partner_type_esc:0
2741 #: view:account.commitment:0
2742 #: selection:sale.order,partner_type:0
2743@@ -47210,7 +47219,12 @@
2744 #: selection:sale.order.change.currency,partner_type:0
2745 #: selection:stock.picking,partner_type:0
2746 #: selection:stock.picking,partner_type_stock_picking:0
2747+<<<<<<< TREE
2748 #: model:product.international.status,name:product_attributes.int_2
2749+=======
2750+#: selection:account.invoice,partner_type:0
2751+#: selection:account.invoice.line,partner_type:0
2752+>>>>>>> MERGE-SOURCE
2753 #: code:addons/msf_supply_doc_export/wizard/supplier_performance_wizard.py:31
2754 #: field:supplier.performance.wizard,partner_type_esc:0
2755 msgid "ESC"
2756@@ -51967,9 +51981,11 @@
2757 msgid "Search Donation"
2758 msgstr "Rechercher Donation"
2759
2760-#. module: sale
2761+#. modules: sale, account_override, account
2762 #: report:addons/sale/report/sale_donation_stock_moves_report_xls.mako:127
2763 #: field:sale.donation.stock.moves,partner_type:0
2764+#: field:account.invoice,partner_type:0
2765+#: field:account.invoice.line,partner_type:0
2766 msgid "Partner Type"
2767 msgstr "Type de Partenaire"
2768
2769@@ -56903,8 +56919,9 @@
2770 msgid "Kit Composition List"
2771 msgstr "Liste de composition du Kit"
2772
2773-#. modules: account, register_accounting
2774+#. modules: account, register_accounting, account_override
2775 #: selection:account.invoice,type:0
2776+#: selection:account.invoice.line,invoice_type:0
2777 #: selection:account.invoice.report,type:0
2778 #: selection:report.invoice.created,type:0
2779 #: selection:wizard.account.invoice,type:0
2780@@ -58894,7 +58911,6 @@
2781 #: code:addons/account/wizard/account_invoice_state.py:44
2782 #: code:addons/account/wizard/account_invoice_state.py:68
2783 #: code:addons/account/wizard/account_report_balance_sheet.py:55
2784-#: code:addons/account/wizard/account_state_open.py:37
2785 #: code:addons/account/wizard/account_subscription_generate.py:50
2786 #: code:addons/account/wizard/account_subscription_generate.py:52
2787 #: code:addons/account/wizard/account_subscription_generate.py:60
2788@@ -63350,6 +63366,18 @@
2789 msgid "Cannot delete invoice(s) that are already opened or paid !"
2790 msgstr "Impossible de supprimer des factures qui sont déjà ouvertes ou payées !"
2791
2792+#. module: account
2793+#: code:addons/account/invoice.py:472
2794+#, python-format
2795+msgid "Cannot delete invoice(s) generated by a Supply workflow!"
2796+msgstr "Impossible de supprimer des factures générées par un flux \"Supply\" !"
2797+
2798+#. module: account
2799+#: code:addons/account/invoice.py:474
2800+#, python-format
2801+msgid "Cannot delete invoice(s) set as \"Synchronized\"!"
2802+msgstr "Impossible de supprimer des factures marquées comme \"Synchronisées\" !"
2803+
2804 #. module: stock
2805 #: view:physical.inventory:0
2806 msgid "Counting sheet"
2807@@ -63994,11 +64022,6 @@
2808 msgid "Select your report"
2809 msgstr "Sélectionner votre rapport"
2810
2811-#. module: account
2812-#: view:account.state.open:0
2813-msgid "(Invoice should be unreconciled if you want to open it)"
2814-msgstr "(Une facture doit être déléttrée pour pouvoir l'ouvrir"
2815-
2816 #. modules: procurement_auto, procurement_cycle
2817 #: help:stock.warehouse.automatic.supply,frequence_id:0
2818 #: help:stock.warehouse.order.cycle,frequence_id:0
2819@@ -66333,8 +66356,9 @@
2820 msgid "Remove all Instances"
2821 msgstr "Supprimer toutes les instances"
2822
2823-#. module: analytic_distribution
2824+#. modules: analytic_distribution, account_override
2825 #: view:account.invoice.line:0
2826+#: view:account.invoice:0
2827 msgid "Change analytic distribution"
2828 msgstr "Changer la distribution analytique"
2829
2830@@ -68392,7 +68416,7 @@
2831 #. module: account_override
2832 #: view:account.invoice:0
2833 msgid "You are about to cancel this invoice. Do you want to proceed?"
2834-msgstr "You are about to cancel this invoice. Do you want to proceed?"
2835+msgstr "Vous êtes sur le point d'annuler cette facture. Voulez-vous continuer ?"
2836
2837 #. module: procurement
2838 #: help:procurement.order,name:0
2839@@ -72046,7 +72070,6 @@
2840 msgstr "Seuls les Produits de Kit peuvent être utilisés pour les Kits."
2841
2842 #. modules: sales_followup, account, purchase_override, procurement_request, res_currency_tables, sync_client, documents_done, product, kit, base, purchase_followup, sale, stock, msf_profile
2843-#: view:account.invoice.cancel:0
2844 #: view:account.invoice.confirm:0
2845 #: view:base.language.install:0
2846 #: view:base.module.import:0
2847@@ -73705,6 +73728,7 @@
2848 #: code:addons/account_override/invoice.py:1484
2849 #: code:addons/account_override/invoice.py:1772
2850 #: code:addons/account_override/invoice.py:1775
2851+#: code:addons/account_override/account_invoice_sync.py:0
2852 #: code:addons/account_reconciliation/account_move_line.py:236
2853 #: code:addons/account_reconciliation/account_move_line.py:256
2854 #: code:addons/account_reconciliation/account_move_line.py:258
2855@@ -74686,6 +74710,13 @@
2856 #: code:addons/stock/wizard/stock_reception_wizard.py:110
2857 #: field:export.report.stock.move,error:0
2858 #: selection:export.report.stock.move,state:0
2859+#: code:addons/account/invoice.py:1342
2860+#: code:addons/account/invoice.py:1344
2861+#: code:addons/account/report/account_liquidity_balance.py:71
2862+#: code:addons/account/wizard/account_report_liquidity_balance.py:71
2863+#: code:addons/account/wizard/account_report_liquidity_balance.py:73
2864+#: code:addons/account/wizard/account_report_liquidity_balance.py:75
2865+#: code:addons/account_override/period.py:148
2866 #, python-format, python-format
2867 msgid "Error"
2868 msgstr "Erreur"
2869@@ -78305,8 +78336,13 @@
2870 #: selection:purchase.order,rfq_state:0
2871 #: view:tender:0
2872 #: selection:tender,state:0
2873+<<<<<<< TREE
2874 #: selection:sale.order.line,state_to_display:0
2875 #: selection:purchase.order.line,state_to_display:0
2876+=======
2877+#: selection:account.invoice,counterpart_inv_status:0
2878+#: selection:wizard.account.invoice,counterpart_inv_status:0
2879+>>>>>>> MERGE-SOURCE
2880 #: field:po.follow.up,cancel_ok:0
2881 #, python-format
2882 msgid "Cancelled"
2883@@ -88425,7 +88461,12 @@
2884 #: selection:wizard.import.cheque,state:0
2885 #: selection:wizard.import.invoice,state:0
2886 #: selection:wizard.register.creation,state:0
2887+<<<<<<< TREE
2888 #: code:addons/sale/report/sale_loan_stock_moves_report.py:92
2889+=======
2890+#: selection:account.invoice,counterpart_inv_status:0
2891+#: selection:wizard.account.invoice,counterpart_inv_status:0
2892+>>>>>>> MERGE-SOURCE
2893 #, python-format
2894 msgid "Open"
2895 msgstr "Ouvert"
2896@@ -88796,10 +88837,17 @@
2897
2898 #. module: account_override
2899 #: code:addons/account_override/invoice.py:747
2900+#: code:addons/account_override/account_invoice_sync.py:230
2901 #, python-format
2902 msgid "No Intermission journal found for the current instance."
2903 msgstr "Pas de journal Intermission trouvé pour l'instance actuelle."
2904
2905+#. module: account_override
2906+#: code:addons/account_override/account_invoice_sync.py:209
2907+#, python-format
2908+msgid "No Purchase journal found for the current instance."
2909+msgstr "Pas de journal des Achats trouvé pour l'instance actuelle."
2910+
2911 #. module: msf_profile
2912 #: field:email.configuration,smtp_server:0
2913 msgid "SMTP Server"
2914@@ -94758,6 +94806,24 @@
2915 msgid "Can not %s invoice which is already reconciled, invoice should be unreconciled first. You can only Refund this invoice"
2916 msgstr "Ne peut %s une facture qui est déjà lettrée, le lettrage de la facture devrait d'abord être annulé. Vous ne pouvez que Rembourser cette facture"
2917
2918+#. module: account
2919+#: code:addons/account/wizard/account_invoice_refund.py:161
2920+#, python-format
2921+msgid "Cannot %s an Intermission Voucher which is already reconciled, it should be unreconciled first."
2922+msgstr "Ne peut %s un Bon Intermission qui est déjà lettré, le lettrage du bon devrait d'abord être annulé."
2923+
2924+#. module: account
2925+#: code:addons/account/wizard/account_invoice_refund.py:0
2926+#, python-format
2927+msgid "modify"
2928+msgstr "modifier"
2929+
2930+#. module: account
2931+#: code:addons/account/wizard/account_invoice_refund.py:0
2932+#, python-format
2933+msgid "cancel"
2934+msgstr "annuler"
2935+
2936 #. modules: return_claim, msf_outgoing, stock_override, kit, msf_doc_import
2937 #: selection:assign.to.kit.line,integrity_status:0
2938 #: selection:kit.selection.line,integrity_status:0
2939@@ -97423,7 +97489,7 @@
2940 msgid "Document Date"
2941 msgstr "Date du Document"
2942
2943-#. modules: msf_order_date, purchase, msf_outgoing, stock_move_tracking, msf_partner, stock_override, purchase_override, msf_config_locations, sale, account_override, stock_batch_recall, specific_rules, msf_doc_import, stock, msf_supply_doc_export
2944+#. modules: msf_order_date, purchase, msf_outgoing, stock_move_tracking, msf_partner, stock_override, purchase_override, msf_config_locations, sale, account_override, stock_batch_recall, specific_rules, msf_doc_import, stock, msf_supply_doc_export, account
2945 #: field:account.account,has_partner_type_internal:0
2946 #: selection:stock.location.configuration.wizard,location_type:0
2947 #: selection:stock.remove.location.wizard,location_usage:0
2948@@ -97452,6 +97518,8 @@
2949 #: selection:stock.picking,fake_type:0
2950 #: selection:stock.picking,partner_type:0
2951 #: selection:stock.picking,partner_type_stock_picking:0
2952+#: selection:account.invoice,partner_type:0
2953+#: selection:account.invoice.line,partner_type:0
2954 #: code:addons/msf_supply_doc_export/wizard/supplier_performance_wizard.py:28
2955 #: field:supplier.performance.wizard,partner_type_internal:0
2956 #, python-format
2957@@ -101145,12 +101213,13 @@
2958 msgid "On "
2959 msgstr "Allumé "
2960
2961-#. modules: account, register_accounting
2962+#. modules: account, register_accounting, account_override
2963 #: selection:account.invoice,type:0
2964 #: selection:account.invoice.report,type:0
2965 #: model:process.process,name:account.process_process_invoiceprocess0
2966 #: selection:report.invoice.created,type:0
2967 #: selection:wizard.account.invoice,type:0
2968+#: selection:account.invoice.line,invoice_type:0
2969 msgid "Customer Invoice"
2970 msgstr "Bon client"
2971
2972@@ -107371,6 +107440,7 @@
2973 msgid "Stop report"
2974 msgstr "Arrêter le rapport"
2975
2976+<<<<<<< TREE
2977 #. module: stock
2978 #: code:addons/stock/stock.py:1780
2979 #, python-format
2980@@ -107481,3 +107551,199 @@
2981 #: report:addons/sale/report/sale_loan_stock_moves_report_xls.mako:175
2982 msgid "Line State"
2983 msgstr "État de la Ligne"
2984+=======
2985+#. module: account
2986+#: code:addons/account/wizard/account_invoice_refund.py:148
2987+#, python-format
2988+msgid "Can not %s invoice which is already reconciled, invoice should be unreconciled first."
2989+msgstr "Ne peut %s une facture qui est déjà lettrée, le lettrage de la facture devrait d'abord être annulé."
2990+
2991+#. module: account
2992+#: code:addons/account/invoice.py:480
2993+#, python-format
2994+msgid "Invoice '%s' is %s."
2995+msgstr "La facture '%s' est %s."
2996+
2997+#. module: account
2998+#: code:addons/account/wizard/account_invoice_refund.py:153
2999+#, python-format
3000+msgid "It is not possible to refund a Closed invoice"
3001+msgstr "Il n'est pas possible de rembourser une facture fermée"
3002+
3003+#. module: account
3004+#: code:addons/account/invoice.py:474
3005+#, python-format
3006+msgid "paid"
3007+msgstr "réglée"
3008+
3009+#. module: account
3010+#: field:account.invoice.refund,is_intermission:0
3011+msgid "Wizard opened from an Intermission Voucher"
3012+msgstr "Assistant ouvert depuis un Bon Intermission"
3013+
3014+#. module: account_override
3015+#: code:addons/account_override/invoice.py:1739
3016+#, python-format
3017+msgid "This document has been generated via a Supply workflow or via synchronization. You can't add lines manually."
3018+msgstr "Ce document a été généré via un flux \"Supply\" ou via la synchronisation. Vous ne pouvez pas ajouter de lignes manuellement."
3019+
3020+#. module: account_override
3021+#: code:addons/account_override/invoice.py:1868
3022+#, python-format
3023+msgid "This document has been generated via a Supply workflow or via synchronization. Existing lines can't be deleted."
3024+msgstr "Ce document a été généré via un flux \"Supply\" ou via la synchronisation. Les lignes existantes ne peuvent pas être supprimées."
3025+
3026+#. module: account_override
3027+#: code:addons/account_override/invoice.py:848
3028+#, python-format
3029+msgid "Synchronized invoices are allowed only with Intermission and Intersection partners."
3030+msgstr "Les factures synchronisées ne sont autorisées qu'avec les partenaires Intermission et Intersection."
3031+
3032+#. module: account
3033+#: code:addons/account/invoice.py:683
3034+#, python-format
3035+msgid "Synchronization is allowed only with Intermission and Intersection partners."
3036+msgstr "La synchronisation n'est autorisée qu'avec les partenaires Intermission et Intersection."
3037+
3038+#. module: account_override
3039+#: view:account.invoice:0
3040+msgid "Are you sure you want to validate this invoice without synchronization?"
3041+msgstr "Etes-vous sûr de vouloir valider cette facture sans synchronisation ?"
3042+
3043+#. modules: account_override, account, register_accounting
3044+#: view:account.invoice:0
3045+msgid "Counterpart Invoice"
3046+msgstr "Facture de Contrepartie"
3047+
3048+#. modules: account_override, register_accounting
3049+#: field:account.invoice,counterpart_inv_number:0
3050+#: field:wizard.account.invoice,counterpart_inv_number:0
3051+msgid "Counterpart Invoice Number"
3052+msgstr "Numéro de la Facture de Contrepartie"
3053+
3054+#. modules: account_override, register_accounting
3055+#: field:account.invoice,counterpart_inv_status:0
3056+#: field:wizard.account.invoice,counterpart_inv_status:0
3057+msgid "Counterpart Invoice Status"
3058+msgstr "Etat de la Facture de Contrepartie"
3059+
3060+#. modules: account_override, register_accounting
3061+#: field:account.invoice,synced:0
3062+#: field:wizard.account.invoice,synced:0
3063+#: field:account.invoice.line,synced:0
3064+msgid "Synchronized"
3065+msgstr "Synchronisé"
3066+
3067+#. modules: account_override, register_accounting
3068+#: field:account.invoice,from_supply:0
3069+#: field:wizard.account.invoice,from_supply:0
3070+#: field:account.invoice.line,from_supply:0
3071+msgid "From Supply"
3072+msgstr "De la \"Supply\""
3073+
3074+#. module: account_override
3075+#: field:account.invoice.line,invoice_type:0
3076+msgid "Invoice Type"
3077+msgstr "Type de Facture"
3078+
3079+#. modules: account_override, register_accounting
3080+#: help:account.invoice,from_supply:0
3081+#: help:wizard.account.invoice,from_supply:0
3082+msgid "Internal field indicating whether the document is related to a Supply workflow"
3083+msgstr "Champ interne indiquant si le document est lié à un flux \"Supply\""
3084+
3085+#. module: account_override
3086+#: code:addons/account_override/account_invoice_sync.py:120
3087+#, python-format
3088+msgid "Account code %s not found."
3089+msgstr "Code comptable %s non trouvé."
3090+
3091+#. module: account_override
3092+#: code:addons/account_override/account_invoice_sync.py:189
3093+#, python-format
3094+msgid "Impossible to retrieve the currency."
3095+msgstr "Impossible de récupérer la devise."
3096+
3097+#. module: account_override
3098+#: code:addons/account_override/account_invoice_sync.py:117
3099+#, python-format
3100+msgid "Impossible to retrieve the account code at line level."
3101+msgstr "Impossible de récupérer le code comptable au niveau d'une ligne."
3102+
3103+#. module: account_override
3104+#: code:addons/account_override/account_invoice_sync.py:193
3105+#, python-format
3106+msgid "Currency %s not found or inactive."
3107+msgstr "Devise %s non trouvée ou inactive."
3108+
3109+#. module: account_override
3110+#: code:addons/account_override/account_invoice_sync.py:123
3111+#, python-format
3112+msgid "Error when retrieving the account at line level."
3113+msgstr "Erreur lors de la récupération du compte au niveau d'une ligne."
3114+
3115+#. module: account_override
3116+#: code:addons/account_override/account_invoice_sync.py:235
3117+#, python-format
3118+msgid "The Intermission counterpart account is missing in the Company form or is inactive."
3119+msgstr "Il manque le compte de Contrepartie Intermission dans le formulaire de la Société, ou bien ce compte est inactif."
3120+
3121+#. module: account_override
3122+#: code:addons/account_override/account_invoice_sync.py:186
3123+#, python-format
3124+msgid "Impossible to retrieve the journal type, or the journal type is incorrect."
3125+msgstr "Impossible de récupérer le type de journal, ou le type de journal est incorrect."
3126+
3127+#. module: account_override
3128+#: code:addons/account_override/account_invoice_sync.py:100
3129+#, python-format
3130+msgid "Impossible to retrieve the line description."
3131+msgstr "Impossible de récupérer la description de la ligne."
3132+
3133+#. module: account_override
3134+#: code:addons/account_override/account_invoice_sync.py:128
3135+#, python-format
3136+msgid "The account \"%s - %s\" is inactive."
3137+msgstr "Le compte \"%s - %s\" est inactif."
3138+
3139+#. module: account_override
3140+#: code:addons/account_override/account_invoice_sync.py:135
3141+#, python-format
3142+msgid "Unit of Measure %s not found."
3143+msgstr "Unité de Mesure %s non trouvée."
3144+
3145+#. module: account_override
3146+#: code:addons/account_override/account_invoice_sync.py:109
3147+#, python-format
3148+msgid "Product %s not found."
3149+msgstr "Produit %s non trouvé."
3150+
3151+#. module: account_override
3152+#: code:addons/account_override/account_invoice_sync.py:181
3153+#, python-format
3154+msgid "The partner %s doesn't exist or is inactive."
3155+msgstr "Le partenaire %s n'existe pas ou est inactif."
3156+
3157+#. module: account_override
3158+#: code:addons/account_override/account_invoice_sync.py:113
3159+#, python-format
3160+msgid "The product %s is inactive."
3161+msgstr "Le produit %s est inactif."
3162+
3163+#. module: account_override
3164+#: code:addons/account_override/account_invoice_sync.py:214
3165+#, python-format
3166+msgid "Account Payable not found or inactive for the partner %s."
3167+msgstr "Compte Fournisseur non trouvé ou inactif pour le partenaire %s."
3168+
3169+#. module: account
3170+#: code:addons/account/wizard/account_invoice_refund.py:158
3171+#, python-format
3172+msgid "Cannot Cancel / Modify if the account can't be reconciled."
3173+msgstr "Impossible d'Annuler / Modifier si le compte n'est pas lettrable."
3174+
3175+#. module: account_override
3176+#: view:account.invoice:0
3177+msgid "This invoice will sync to its counterpart instance."
3178+msgstr "Cette facture sera synchronisée à l'instance de Contrepartie."
3179+>>>>>>> MERGE-SOURCE
3180
3181=== modified file 'bin/addons/msf_profile/msf_profile.py'
3182--- bin/addons/msf_profile/msf_profile.py 2019-07-24 09:13:25 +0000
3183+++ bin/addons/msf_profile/msf_profile.py 2019-07-30 10:04:49 +0000
3184@@ -67,6 +67,46 @@
3185 cr.execute("update ir_cron set function='send_backup_bg' where function='send_backup' and model='msf.instance.cloud'")
3186 return True
3187
3188+ # UF14.0
3189+ def us_6075_set_paid_invoices_as_closed(self, cr, uid, *a, **b):
3190+ cr.execute('''SELECT i.id, i.number
3191+ FROM account_invoice i
3192+ LEFT JOIN account_move_line l ON i.move_id=l.move_id
3193+ LEFT JOIN account_move_line rec_line ON rec_line.reconcile_id = l.reconcile_id
3194+ LEFT JOIN account_journal j ON j.id = rec_line.journal_id AND j.type in ('cash', 'bank', 'cheque')
3195+ WHERE i.state='paid'
3196+ AND l.reconcile_id is not null
3197+ AND l.account_id=i.account_id
3198+ AND l.is_counterpart
3199+ GROUP BY i.id, i.number
3200+ HAVING min(j.id) IS NULL
3201+ ORDER BY i.id
3202+ ''')
3203+ inv_ids = []
3204+ inv_name = []
3205+ for x in cr.fetchall():
3206+ inv_ids.append(x[0])
3207+ inv_name.append(x[1])
3208+ if inv_ids:
3209+ self._logger.warn('%d Invoices change state from Paid to Close: %s' % (len(inv_ids), ', '.join(inv_name)))
3210+ cr.execute("update account_invoice set state='inv_close' where state='paid' and id in %s", (tuple(inv_ids), ))
3211+ return True
3212+
3213+ def us_6076_set_inv_as_from_supply(self, cr, uid, *a, **b):
3214+ """
3215+ Set the new tag from_supply to True in the related account.invoices
3216+ """
3217+ update_inv = """
3218+ UPDATE account_invoice
3219+ SET from_supply = 't'
3220+ WHERE picking_id IS NOT NULL
3221+ OR id IN (SELECT DISTINCT (invoice_id) FROM shipment WHERE invoice_id IS NOT NULL);
3222+ """
3223+ cr.execute(update_inv)
3224+ self._logger.warn('Tag from_supply set to True in %s account.invoice(s).' % (cr.rowcount,))
3225+ return True
3226+
3227+
3228 # UF13.1
3229 def us_3413_align_in_partner_to_po(self,cr, uid, *a, **b):
3230 cr.execute("select p.name, p.id, po.partner_id, p.partner_id from stock_picking p, purchase_order po where p.type='in' and po.id = p.purchase_id and ( p.partner_id != po.partner_id or p.partner_id2 != po.partner_id) order by p.name")
3231
3232=== modified file 'bin/addons/msf_sync_data_server/data/sync_server.message_rule.csv'
3233--- bin/addons/msf_sync_data_server/data/sync_server.message_rule.csv 2019-02-16 16:57:55 +0000
3234+++ bin/addons/msf_sync_data_server/data/sync_server.message_rule.csv 2019-07-30 10:04:49 +0000
3235@@ -15,6 +15,8 @@
3236 msf_sync_data_server.validated_claim_create_claim,TRUE,TRUE,"['category_return_claim', 'creation_date_return_claim', 'description_return_claim', 'follow_up_return_claim', 'name', 'picking_id_return_claim/shipment_ref', 'po_id_return_claim/name', 'po_so_return_claim', 'goods_expected', 'processor_origin', 'state', 'type_return_claim', 'origin_claim', 'event_ids_return_claim/name', 'event_ids_return_claim/creation_date_claim_event', 'event_ids_return_claim/from_picking_wizard_claim_event', 'event_ids_return_claim/replacement_picking_expected_claim_event', 'event_ids_return_claim/type_claim_event', 'event_ids_return_claim/description_claim_event', 'product_line_ids_return_claim/price_unit_claim_product_line', 'product_line_ids_return_claim/qty_claim_product_line', 'product_line_ids_return_claim/product_id_claim_product_line/id', 'product_line_ids_return_claim/product_id_claim_product_line/name', 'product_line_ids_return_claim/price_currency_claim_product_line/id', 'product_line_ids_return_claim/price_currency_claim_product_line/name', 'product_line_ids_return_claim/uom_id_claim_product_line/id', 'product_line_ids_return_claim/uom_id_claim_product_line/name', 'product_line_ids_return_claim/type_check', 'product_line_ids_return_claim/expiry_date_claim_product_line']","[('state', '=', 'in_progress'), ('partner_id_return_claim.partner_type', 'in', ['internal', 'intermission', 'intersection']), ('type_return_claim', '=', 'supplier'), ('old_version', '=', False)]",partner_id_return_claim,MISSION,return.claim.validated_claim_create_claim,return.claim,Validated Claim creates Claim,28,,Valid
3237 msf_sync_data_server.origin_claim_close_claim,TRUE,TRUE,"['name', 'state', 'partner_id_return_claim/name', 'partner_id_return_claim/partner_type']","[('state', '=', 'done'), ('partner_id_return_claim.partner_type', '=', 'internal'), ('type_return_claim', '=', 'supplier'), ('old_version', '=', False)]",partner_id_return_claim,MISSION,return.claim.origin_claim_close_claim,return.claim,Original Closed Claim close counterpart Claim,29,,Valid
3238 msf_sync_data_server.goods_expecting_picking_from_claim_creates_fo,TRUE,TRUE,"['name', 'claim_name', 'purchase_id/name', 'purchase_id/delivery_requested_date','purchase_id/details', 'purchase_id/notes', 'purchase_id/categ', 'purchase_id/order_type', 'purchase_id/priority', 'purchase_id/loan_duration', 'purchase_id/analytic_distribution_id/id', 'purchase_id/is_a_counterpart', 'purchase_id/pricelist_id/name', 'purchase_id/stock_take_date', 'move_lines/product_id/name', 'move_lines/purchase_line_id/id', 'move_lines/purchase_line_id/sync_local_id', 'move_lines/name', 'move_lines/comment', 'move_lines/product_qty', 'move_lines/product_uom/name', 'move_lines/price_unit', 'move_lines/line_number']","['&', '&', ('state', '=', 'assigned'), ('partner_id.partner_type', '=', 'internal'), ('claim', '=', True), ('claim_name', '!=', False), '|', ('name', 'like', 'replacement'), ('name', 'like', 'missing')]",partner_id,MISSION,stock.picking.goods_expecting_picking_from_claim_creates_fo,stock.picking,IN-replacement/-missing created by Claim creates FO,30,,Valid
3239+msf_sync_data_server.create_account_invoice,TRUE,TRUE,"['number', 'document_date', 'date_invoice', 'journal_id/type', 'name', 'origin', 'from_supply', 'state', 'currency_id/name', 'invoice_line/name', 'invoice_line/quantity', 'invoice_line/uos_id/name', 'invoice_line/price_unit', 'invoice_line/discount', 'invoice_line/account_id/code', 'invoice_line/product_id/id', 'invoice_line/product_id/default_code']","[('type', '=', 'out_invoice'), ('is_debit_note', '=', False), ('state', '!=', 'draft'), ('number', '!=', False), ('synced', '=', True), ('partner_type', 'in', ('intermission', 'section'))]",partner_id,MISSION,account.invoice.create_invoice_from_sync,account.invoice,Account Invoice Creation,40,,Valid
3240+msf_sync_data_server.update_counterpart_inv,TRUE,TRUE,"['number', 'state', 'counterpart_inv_number']","[('synced', '=', True), ('partner_type', 'in', ('intermission', 'section')), ('number', '!=', False), ('state', 'in', ['open', 'paid', 'inv_close', 'cancel'])]",partner_id,MISSION,account.invoice.update_counterpart_inv,account.invoice,Account Invoice State Update,42,,Valid
3241 msf_sync_data_server.create_batch_object,FALSE,TRUE,"['name', 'xmlid_name', 'prefix', 'product_id/id', 'product_id/default_code', 'partner_id/id', 'date', 'ref','life_date','sequence_id','type']","[('name', '=', False)]",partner_id,MISSION,stock.picking.create_batch_number,stock.production.lot,Create Batch Object,1001,,Valid
3242 msf_sync_data_server.create_asset_object,TRUE,TRUE,"['name', 'xmlid_name', 'arrival_date', 'asset_type_id/id', 'partner_id/id', 'brand', 'comment', 'description', 'hq_ref', 'international_po', 'invo_certif_depreciation', 'invo_currency/id', 'invo_date', 'invo_donator_code', 'invo_num', 'invo_supplier', 'invo_value', 'local_ref', 'model', 'orig_mission_code', 'product_id/id', 'product_id/default_code', 'project_po', 'receipt_place', 'serial_nb', 'type', 'year']","[('name', '=', False)]",partner_id,MISSION,stock.picking.create_asset,product.asset,Create Asset Object,1002,,Valid
3243 msf_sync_data_server.reset_ref_by_recovery_mode,TRUE,TRUE,['name'],"[('name', '=', False)]",partner_id,MISSION,sale.order.reset_ref_by_recovery_mode,sale.order,Reset Due to Recovery,1003,,Valid
3244
3245=== modified file 'bin/addons/product_attributes/product_attributes.py'
3246--- bin/addons/product_attributes/product_attributes.py 2019-07-22 12:08:20 +0000
3247+++ bin/addons/product_attributes/product_attributes.py 2019-07-30 10:04:49 +0000
3248@@ -1584,7 +1584,7 @@
3249 # Check if the product is in an invoice
3250 has_invoice_line = invoice_obj.search(cr, uid, [('product_id', '=', product.id),
3251 ('invoice_id', '!=', False),
3252- ('invoice_id.state', 'not in', ['paid', 'proforma', 'proforma2', 'cancel'])], context=context)
3253+ ('invoice_id.state', 'not in', ['paid', 'inv_close', 'proforma', 'proforma2', 'cancel'])], context=context)
3254
3255 # Check if the product has stock in internal locations
3256 for loc_id in internal_loc:
3257
3258=== modified file 'bin/addons/purchase/purchase_workflow.py'
3259--- bin/addons/purchase/purchase_workflow.py 2019-05-14 08:00:10 +0000
3260+++ bin/addons/purchase/purchase_workflow.py 2019-07-30 10:04:49 +0000
3261@@ -502,15 +502,15 @@
3262
3263 def check_po_tax(self, cr, uid, ids, context=None):
3264 """
3265- Prevents from validating a PO with taxes when using an Intermission partner
3266+ Prevents from validating a PO with taxes when using an Intermission or Intersection partner
3267 """
3268 if context is None:
3269 context = {}
3270 if isinstance(ids, (int, long)):
3271 ids = [ids]
3272 for po_line in self.browse(cr, uid, ids, fields_to_fetch=['order_id', 'taxes_id'], context=context):
3273- if po_line.taxes_id and po_line.order_id.partner_type == 'intermission':
3274- raise osv.except_osv(_('Error'), _("You can't use taxes with an intermission partner."))
3275+ if po_line.taxes_id and po_line.order_id.partner_type in ('intermission', 'section'):
3276+ raise osv.except_osv(_('Error'), _("Taxes are forbidden with Intermission and Intersection partners."))
3277
3278 def check_origin_for_validation(self, cr, uid, ids, context=None):
3279 if not context:
3280
3281=== modified file 'bin/addons/register_accounting/account_invoice_view.xml'
3282--- bin/addons/register_accounting/account_invoice_view.xml 2018-05-15 08:55:26 +0000
3283+++ bin/addons/register_accounting/account_invoice_view.xml 2019-07-30 10:04:49 +0000
3284@@ -149,14 +149,14 @@
3285 <field name="type" invisible="1"/>
3286 <field name="currency_id" attrs="{'readonly': [('is_direct_invoice', '=', True)]}"/>
3287 <newline/>
3288- <field name="partner_id" domain="[('supplier', '=', True)]" on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id,is_inkind_donation,is_intermission,is_debit_note,is_direct_invoice)" context="{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', '=', 'paid')]}"/>
3289+ <field name="partner_id" domain="[('supplier', '=', True)]" on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id,is_inkind_donation,is_intermission,is_debit_note,is_direct_invoice)" context="{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', 'in', ['paid', 'inv_close'])]}"/>
3290
3291- <field domain="[('partner_id','=',partner_id)]" name="address_invoice_id" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', '=', 'paid')]}"/>
3292+ <field domain="[('partner_id','=',partner_id)]" name="address_invoice_id" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', 'in', ['paid', 'inv_close'])]}"/>
3293 <newline/>
3294- <field name="document_date" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', '=', 'paid')]}"/>
3295+ <field name="document_date" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', 'in', ['paid', 'inv_close'])]}"/>
3296 <field name="date_invoice" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True)]}"/>
3297 <field name="register_posting_date" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True)]}"/>
3298- <field name="reference" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', '=', 'paid')]}" />
3299+ <field name="reference" attrs="{'readonly': [('is_direct_invoice', '=', True),('state', 'in', ['paid', 'inv_close'])]}" />
3300 <newline/>
3301 <label string="" colspan="4"/>
3302 <field name="amount_total"/>
3303@@ -165,11 +165,11 @@
3304 <group colspan="2"/>
3305 <notebook colspan="4">
3306 <page string="Invoice">
3307- <field name="account_id" domain="[('company_id', '=', company_id), ('restricted_area', '=', 'in_invoice')]" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3308+ <field name="account_id" domain="[('company_id', '=', company_id), ('restricted_area', '=', 'in_invoice')]" required="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid', 'inv_close'])]}"/>
3309 <field name="check_total" readonly="1" invisible="1"/>
3310 <field colspan="4" default_get="{'check_total': check_total, 'address_invoice_id':
3311 address_invoice_id, 'partner_id': partner_id, 'price_type': 'price_type' in dir() and price_type or False}"
3312- name="invoice_line" nolabel="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}">
3313+ name="invoice_line" nolabel="1" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}">
3314 <tree editable="bottom" string="Invoice lines" >
3315 <field name="is_corrected" invisible="1"/>
3316 <button name="button_open_analytic_lines" string="Have been corrected" type="object" icon="terp-mail-" attrs="{'invisible': [('is_corrected', '=', False)]}"/>
3317@@ -193,23 +193,23 @@
3318 </field>
3319 </page>
3320 <page string="Other Info">
3321- <field domain="[('partner_id', '=', partner_id)]" name="partner_bank_id" on_change="onchange_partner_bank(partner_bank_id)" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3322+ <field domain="[('partner_id', '=', partner_id)]" name="partner_bank_id" on_change="onchange_partner_bank(partner_bank_id)" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid', 'inv_close'])]}"/>
3323 <field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)"
3324- widget="selection" groups="base.group_multi_company" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3325- <newline/>
3326- <field name="payment_term" widget="selection" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3327- <field name="name" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3328- <newline/>
3329- <field name="origin" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3330- <field domain="[('partner_id','=',partner_id)]" name="address_contact_id" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3331- <field name="user_id" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','=','paid')]}"/>
3332+ widget="selection" groups="base.group_multi_company" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid', 'inv_close'])]}"/>
3333+ <newline/>
3334+ <field name="payment_term" widget="selection" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}"/>
3335+ <field name="name" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}"/>
3336+ <newline/>
3337+ <field name="origin" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}"/>
3338+ <field domain="[('partner_id','=',partner_id)]" name="address_contact_id" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}"/>
3339+ <field name="user_id" attrs="{'readonly': [('is_direct_invoice', '=', True),('state','in',['paid','inv_close'])]}"/>
3340 <separator colspan="4" string="Additional Information"/>
3341 <field colspan="4" name="comment" nolabel="1"/>
3342 </page>
3343 </notebook>
3344 <group col="4" colspan="4">
3345 <field name="state" readonly="1" colspan="2"/>
3346- <button name="%(action_direct_invoice_refund)d" type='action' string='Refund' states='open,paid' icon="gtk-execute" colspan="2"/>
3347+ <button name="%(action_direct_invoice_refund)d" type='action' string='Refund' states='open,paid,inv_close' icon="gtk-execute" colspan="2"/>
3348 </group>
3349 </form>
3350 </field>
3351@@ -316,11 +316,15 @@
3352 </field>
3353 <xpath expr="/form/notebook/page[@string='Invoice']/field[@name='invoice_line']" position="before" >
3354 <group name="import" string=" Import Lines " colspan="4" col="4" attrs="{'invisible':[('state', '!=', 'draft')]}">
3355- <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object" attrs="{'invisible':[('state', '!=', 'draft')]}"/>
3356+ <button name="wizard_import_si_line" string="Import lines" icon="gtk-dnd" type="object"
3357+ attrs="{'invisible': [('state', '!=', 'draft')],
3358+ 'readonly': [('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
3359 </group>
3360 </xpath>
3361 <field name="journal_id" position="replace">
3362- <field name="journal_id" domain="[('is_current_instance','=',True), ('type', '=', context.get('journal_type'))]"/>
3363+ <field name="journal_id"
3364+ domain="[('is_current_instance','=',True), ('type', '=', context.get('journal_type'))]"
3365+ attrs="{'readonly': ['|', ('state', '!=', 'draft'), '&amp;', ('type', '=', 'in_invoice'), ('synced', '=', True)]}"/>
3366 <field name="vat_ok" invisible="1" />
3367 </field>
3368 <button name="action_cancel_draft" position="replace"/>
3369@@ -348,12 +352,16 @@
3370 </tree>
3371 </field>
3372 </page>
3373+ <!-- display the Counterpart Invoice tab in SI, hide it in SR -->
3374+ <page string="Counterpart Invoice" attrs="{'invisible': [('type', '!=', 'in_invoice')]}">
3375+ <field name="from_supply" invisible="1"/> <!-- make the field exportable -->
3376+ <field name="synced" readonly="1"/> <!-- SI can never be ticked as "Synced" manually -->
3377+ <newline/>
3378+ <field name="counterpart_inv_number"/>
3379+ <field name="counterpart_inv_status"/>
3380+ </page>
3381 </page>
3382
3383- <xpath expr="/form//field[@name='tax_line']" position="attributes">
3384- <attribute name="attrs">{'invisible': [('vat_ok', '=', False)]}</attribute>
3385- </xpath>
3386-
3387 <xpath expr="/form//field[@name='amount_untaxed']" position="attributes">
3388 <attribute name="attrs">{'invisible': [('vat_ok', '=', False)]}</attribute>
3389 </xpath>
3390@@ -371,26 +379,5 @@
3391 </record>
3392
3393
3394- <!-- Invoice search view -->
3395- <record id="inherit_view_account_invoice_filter2" model="ir.ui.view">
3396- <field name="name">inherit.view.account.invoice.filter.2</field>
3397- <field name="model">account.invoice</field>
3398- <field name="type">search</field>
3399- <field name="inherit_id" ref="account.view_account_invoice_filter"/>
3400- <field name="priority">18</field>
3401- <field name="arch" type="xml">
3402- <data>
3403- <xpath expr="/search/group[1]/filter[@name='paid']" position="after">
3404- <separator orientation="vertical"/>
3405- <filter name="not_imported" icon="gtk-cancel" string="Not imported" domain="[('imported_state', '=', 'not')]"/>
3406- <filter name="partial" icon="terp-dolar_ok!" string="Partially imported" domain="[('imported_state', '=', 'partial')]"/>
3407- <filter name="imported" icon="gtk-apply" string="Imported" domain="[('imported_state', '=', 'imported')]"/>
3408- <separator orientation="vertical"/>
3409- </xpath>
3410- </data>
3411- </field>
3412- </record>
3413-
3414-
3415 </data>
3416 </openerp>
3417
3418=== modified file 'bin/addons/register_accounting/wizard/down_payment.py'
3419--- bin/addons/register_accounting/wizard/down_payment.py 2018-08-29 12:37:13 +0000
3420+++ bin/addons/register_accounting/wizard/down_payment.py 2019-07-30 10:04:49 +0000
3421@@ -97,7 +97,7 @@
3422 raise osv.except_osv(_('Error'), _("Amounts IN can't be higher than Amounts OUT for the selected PO."))
3423
3424 # Cut away open and paid invoice linked to this PO
3425- invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('purchase_ids', 'in', [po_id]), ('state', 'in', ['paid', 'open'])])
3426+ invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('purchase_ids', 'in', [po_id]), ('state', 'in', ['paid', 'open', 'inv_close'])])
3427 included_dp_amls = []
3428 for inv in self.pool.get('account.invoice').read(cr, uid, invoice_ids, ['amount_total', 'down_payment_ids']):
3429 lines_amount -= inv.get('amount_total', 0.0)
3430
3431=== modified file 'bin/addons/res_currency_tables/res_currency.py'
3432--- bin/addons/res_currency_tables/res_currency.py 2018-07-30 14:02:59 +0000
3433+++ bin/addons/res_currency_tables/res_currency.py 2019-07-30 10:04:49 +0000
3434@@ -244,7 +244,7 @@
3435 'in at least one active partner form.') % keyword)
3436
3437 # Check on account.invoice
3438- if acc_inv_obj.search_exist(cr, uid, [('currency_id', 'in', ids), ('state', 'not in', ['paid', 'cancel'])], context=context):
3439+ if acc_inv_obj.search_exist(cr, uid, [('currency_id', 'in', ids), ('state', 'not in', ['paid', 'inv_close', 'cancel'])], context=context):
3440 raise osv.except_osv(_('Currency currently used!'), _('The currency you want to %s is used in at least '
3441 'one document in Draft or Open state.') % keyword)
3442
3443
3444=== modified file 'bin/addons/sale/report/sale_report.py'
3445--- bin/addons/sale/report/sale_report.py 2017-10-09 21:06:10 +0000
3446+++ bin/addons/sale/report/sale_report.py 2019-07-30 10:04:49 +0000
3447@@ -46,7 +46,7 @@
3448 else:
3449 res[report.id] = True
3450 for invoice in sale.invoice_ids:
3451- if invoice.state != 'paid':
3452+ if invoice.state not in ('paid', 'inv_close'):
3453 res[report.id] = False
3454 break
3455 if not sale.invoice_ids:
3456@@ -85,7 +85,7 @@
3457 'invoiced': fields.function(_invoiced, method=True, string='Paid',
3458 type='boolean', help="It indicates that an invoice has been paid."),
3459 'order_type': fields.selection([('regular', 'Regular'), ('donation_exp', 'Donation before expiry'),
3460- ('donation_st', 'Standard donation'), ('loan', 'Loan'),],
3461+ ('donation_st', 'Standard donation'), ('loan', 'Loan'),],
3462 string='Order Type', required=True, readonly=True, states={'draft': [('readonly', False)]}),
3463 'priority': fields.selection(ORDER_PRIORITY, string='Priority', readonly=True, states={'draft': [('readonly', False)]}),
3464 'categ': fields.selection(ORDER_CATEGORY, string='Order category', required=True, readonly=True, states={'draft': [('readonly', False)]}),
3465
3466=== modified file 'bin/addons/sale/sale_order.py'
3467--- bin/addons/sale/sale_order.py 2019-07-25 13:39:42 +0000
3468+++ bin/addons/sale/sale_order.py 2019-07-30 10:04:49 +0000
3469@@ -180,7 +180,7 @@
3470 else:
3471 res[sale.id] = True
3472 for invoice in sale.invoice_ids:
3473- if invoice.state != 'paid':
3474+ if invoice.state not in ('paid', 'inv_close'):
3475 res[sale.id] = False
3476 break
3477 if not sale.invoice_ids:
3478@@ -196,9 +196,9 @@
3479 for arg in args:
3480 if arg[1] == '=':
3481 if arg[2]:
3482- clause += 'AND inv.state = \'paid\' OR (sale.state != \'draft\' AND (sale.order_type != \'regular\' OR part.partner_type = \'internal\'))'
3483+ clause += 'AND inv.state in (\'paid\', \'inv_close\') OR (sale.state != \'draft\' AND (sale.order_type != \'regular\' OR part.partner_type = \'internal\'))'
3484 else:
3485- clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\' AND inv.state <> \'paid\' AND sale.order_type = \'regular\''
3486+ clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\' AND inv.state not in (\'paid\', \'inv_close\') AND sale.order_type = \'regular\''
3487 no_invoiced = True
3488
3489 cursor.execute('SELECT rel.order_id ' \
3490
3491=== modified file 'bin/addons/sale/sale_view.xml'
3492--- bin/addons/sale/sale_view.xml 2019-07-22 12:08:20 +0000
3493+++ bin/addons/sale/sale_view.xml 2019-07-30 10:04:49 +0000
3494@@ -430,7 +430,6 @@
3495 <button name="manual_invoice" states="manual" string="Create Final Invoice" icon="gtk-go-forward" type="object" invisible="1"/>
3496 <button name="ship_cancel" states="shipping_except" string="Cancel document" icon="gtk-cancel" help="all the lines will be Cancelled where this status change is feasible" />
3497 <button name="ask_resource_lines" states="draft,draft_p,validated,validated_p" string="Cancel document" type="object" icon="gtk-cancel" help="all the lines will be Cancelled where this status change is feasible" />
3498- <button name="invoice_cancel" states="invoice_except" string="Cancel document" icon="gtk-cancel" help="all the lines will be Cancelled where this status change is feasible" />
3499 <button name="order_confirm" states="validated" string="Confirm document" icon="gtk-apply" invisible="True" help="all the lines will be Confirmed where this status change is feasible" />
3500 <button name="do_order_confirm_method" type="object" states="validated" string="Confirm document" help="all the lines will be Confirmed where this status change is feasible" icon="gtk-apply" confirm="You are about to confirm the Field Order without going through the sourcing tool. Are you sure?" attrs="{'readonly': [('no_line', '=', True)]}"/>
3501 <button name="validate_lines" type="object" string="Validate document" icon="terp-check" states="draft,draft_p" attrs="{'readonly': [('no_line', '=', True)]}" help="all the lines will be Validated where this status change is feasible" />
3502
3503=== modified file 'bin/addons/sale/sale_workflow.py'
3504--- bin/addons/sale/sale_workflow.py 2019-07-24 09:39:53 +0000
3505+++ bin/addons/sale/sale_workflow.py 2019-07-30 10:04:49 +0000
3506@@ -529,15 +529,15 @@
3507
3508 def check_fo_tax(self, cr, uid, ids, context=None):
3509 """
3510- Prevents from validating a FO with taxes when using an Intermission partner
3511+ Prevents from validating a FO with taxes when using an Intermission or Intersection partner
3512 """
3513 if context is None:
3514 context = {}
3515 if isinstance(ids, (int, long)):
3516 ids = [ids]
3517 for fo_line in self.browse(cr, uid, ids, fields_to_fetch=['order_id', 'tax_id'], context=context):
3518- if fo_line.tax_id and fo_line.order_id.partner_type == 'intermission':
3519- raise osv.except_osv(_('Error'), _("You can't use taxes with an intermission partner."))
3520+ if fo_line.tax_id and fo_line.order_id.partner_type in ('intermission', 'section'):
3521+ raise osv.except_osv(_('Error'), _("Taxes are forbidden with Intermission and Intersection partners."))
3522
3523 def action_validate(self, cr, uid, ids, context=None):
3524 '''
3525
3526=== modified file 'bin/addons/stock/stock.py'
3527--- bin/addons/stock/stock.py 2019-06-17 14:48:35 +0000
3528+++ bin/addons/stock/stock.py 2019-07-30 10:04:49 +0000
3529@@ -1230,6 +1230,7 @@
3530 'company_id': picking.company_id.id,
3531 'user_id':uid,
3532 'picking_id': picking.id,
3533+ 'from_supply': True,
3534 }
3535 if picking.sale_id:
3536 if not partner.property_account_position.id:
3537@@ -1323,6 +1324,13 @@
3538 if origin_ivi:
3539 invoice_vals.update({'origin': origin_ivi})
3540
3541+ # Add "synced" tag for STV and IVO created from Supply flow
3542+ out_invoice = inv_type == 'out_invoice'
3543+ is_stv = out_invoice and not di and not inkind_donation and not intermission
3544+ is_ivo = out_invoice and not debit_note and not inkind_donation and intermission
3545+ if is_stv or is_ivo:
3546+ invoice_vals.update({'synced': True, })
3547+
3548 # Update Payment terms and due date for the Supplier Invoices and Refunds
3549 if is_si or inv_type == 'in_refund':
3550 si_payment_term = self._get_payment_term(cr, uid, picking)
3551
3552=== modified file 'bin/addons/stock_override/stock.py'
3553--- bin/addons/stock_override/stock.py 2019-06-17 14:48:35 +0000
3554+++ bin/addons/stock_override/stock.py 2019-07-30 10:04:49 +0000
3555@@ -944,6 +944,11 @@
3556 if sp.type == 'out' and sp.partner_id.partner_type == 'external' and invoice_type != 'in_refund':
3557 res = False
3558
3559+ # Move in on an intermission or intersection partner should not create an IVI / SI (generation of Donations shouldn't be blocked)
3560+ if sp.type == 'in' and sp.purchase_id and sp.purchase_id.order_type not in ('donation_st', 'donation_exp') \
3561+ and sp.partner_id and sp.partner_id.partner_type in ('intermission', 'section') and invoice_type == 'in_invoice':
3562+ res = False
3563+
3564 return res
3565
3566 def _create_invoice(self, cr, uid, stock_picking):
3567
3568=== modified file 'bin/addons/sync_so/picking.py'
3569--- bin/addons/sync_so/picking.py 2019-06-17 09:06:48 +0000
3570+++ bin/addons/sync_so/picking.py 2019-07-30 10:04:49 +0000
3571@@ -316,10 +316,7 @@
3572 if shipment:
3573 shipment_ref = shipment['name'] # shipment made
3574 else:
3575- #UFTP-332: Check if name is really an OUT, because DPO could have PICk but no SHIP nor OUT --> do not link this PICK to IN
3576 shipment_ref = pick_dict.get('name', False) # the case of OUT
3577- if shipment_ref and 'OUT' not in shipment_ref:
3578- shipment_ref = False
3579 if not po_id and pick_dict.get('sale_id') and pick_dict.get('sale_id', {}).get('claim_name_goods_return'):
3580 po_sync_name = pick_dict.get('sale_id', {}).get('client_order_ref')
3581 if po_sync_name:
3582@@ -756,6 +753,9 @@
3583 so_po_common = self.pool.get('so.po.common')
3584 so_po_common.create_invalid_recovery_message(cr, uid, source, in_name, context)
3585 return "Recovery: the reference to " + in_name + " at " + source + " will be set to void."
3586+ elif 'PICK' in out_doc_name:
3587+ return "Msg ignored"
3588+
3589 if message:
3590 self._logger.info(message)
3591 return message
3592
3593=== modified file 'bin/addons/sync_so/specific_xml_id.py'
3594--- bin/addons/sync_so/specific_xml_id.py 2019-03-01 13:32:06 +0000
3595+++ bin/addons/sync_so/specific_xml_id.py 2019-07-30 10:04:49 +0000
3596@@ -8,6 +8,7 @@
3597 from osv import fields
3598 from product_nomenclature.product_nomenclature import RANDOM_XMLID_CODE_PREFIX
3599 import time
3600+import netsvc
3601
3602 # Note:
3603 #
3604@@ -619,15 +620,26 @@
3605 return True
3606 if context is None:
3607 context = {}
3608+
3609+ # if unreconcile linked to paid/close invoice, then reopen SI
3610+ invoice_reopen = []
3611+ if context.get('sync_update_execution') and 'reconcile_id' in vals and not vals['reconcile_id']:
3612+ move_lines = self.browse(cr, uid, ids, fields_to_fetch=['invoice', 'reconcile_id'], context=context)
3613+ invoice_reopen = [line.invoice.id for line in move_lines if line.reconcile_id and line.invoice and line.invoice.state in ['paid','inv_close']]
3614+
3615 res = super(account_move_line, self).write(cr, uid, ids, vals, context=context, check=check, update_check=update_check)
3616 # Do workflow if line is coming from sync, is now reconciled and it has an unpaid invoice
3617 if context.get('sync_update_execution', False) and 'reconcile_id' in vals and vals['reconcile_id']:
3618 invoice_ids = []
3619- line_list = self.browse(cr, uid, ids, context=context)
3620+ line_list = self.browse(cr, uid, ids, fields_to_fetch=['invoice'], context=context)
3621 invoice_ids = [line.invoice.id for line in line_list if
3622- line.invoice and line.invoice.state != 'paid']
3623+ line.invoice and line.invoice.state not in ('paid','inv_close')]
3624 if self.pool.get('account.invoice').test_paid(cr, uid, invoice_ids):
3625 self.pool.get('account.invoice').confirm_paid(cr, uid, invoice_ids)
3626+
3627+ if invoice_reopen:
3628+ netsvc.LocalService("workflow").trg_validate(uid, 'account.invoice', invoice_reopen, 'open_test', cr)
3629+
3630 return res
3631
3632 account_move_line()
3633
3634=== modified file 'bin/addons/vertical_integration/report/report_open_invoices.py'
3635--- bin/addons/vertical_integration/report/report_open_invoices.py 2013-06-11 15:17:55 +0000
3636+++ bin/addons/vertical_integration/report/report_open_invoices.py 2019-07-30 10:04:49 +0000
3637@@ -20,7 +20,6 @@
3638
3639 from spreadsheet_xml.spreadsheet_xml_write import SpreadsheetReport
3640 from report import report_sxw
3641-from tools.translate import _
3642
3643
3644 class report_open_invoices2(report_sxw.rml_parse):
3645@@ -50,7 +49,7 @@
3646 LEFT JOIN res_users responsible ON invoice.user_id = responsible.id
3647 LEFT JOIN res_currency currency ON invoice.currency_id = currency.id
3648 WHERE
3649- invoice.state NOT IN ('paid', 'cancel') AND
3650+ invoice.state NOT IN ('paid', 'inv_close', 'cancel') AND
3651 invoice.type = %s
3652 ORDER BY invoice.date_invoice
3653 """

Subscribers

People subscribed via source and target branches