Merge lp:~akretion-team/openobject-addons/trunk-payment-term-on-purchase-v2 into lp:openobject-addons

Proposed by Alexis de Lattre
Status: Rejected
Rejected by: qdp (OpenERP)
Proposed branch: lp:~akretion-team/openobject-addons/trunk-payment-term-on-purchase-v2
Merge into: lp:openobject-addons
Diff against target: 236 lines (+52/-24)
10 files modified
account/account.py (+5/-1)
account/account_invoice.py (+2/-1)
account/account_move_line.py (+11/-4)
account/partner.py (+10/-3)
account/partner_view.xml (+2/-1)
base_vat/base_vat_view.xml (+1/-1)
purchase/purchase.py (+15/-6)
purchase/purchase_view.xml (+1/-0)
purchase/stock.py (+2/-0)
purchase/wizard/purchase_line_invoice.py (+3/-7)
To merge this branch: bzr merge lp:~akretion-team/openobject-addons/trunk-payment-term-on-purchase-v2
Reviewer Review Type Date Requested Status
Stefan Rijnhart (Opener) (community) functional Approve
Fabien (Open ERP) Disapprove
Review via email: mp+93048@code.launchpad.net

Description of the change

This is a new version of my merge proposal to add payment term on purchase orders.

My previous merge proposal https://code.launchpad.net/~akretion-team/openobject-addons/trunk-payment-term-on-purchase/+merge/90872 was refused by Quentin for a number of reasons. I have addresses Quentin's objections in this new merge proposal :

1. We now have 2 payment terms on res.partner : one when the partner is a customer ("Customer payment term"), another one when the partner is a supplier ("Supplier payment term")

2. I have a better handling of the cases where no payment_term are given on the PO, as suggested by Quentin : when there is no payment term on the PO, the "Supplier payment term" is used

I hope that this merge proposal will be accepted. If you would like more modifications in it, please tell me and I will work on it.

To post a comment you must log in.
Revision history for this message
Fabien (Open ERP) (fp-tinyerp) wrote :

Hello,

I would tend to refuse this merge proposal. I's a good contribution but I propose to put it in a separate modules.

Most of the time, when you do a Purchase Order, you just want to set a due date provided by the supplier (like on the supplier invoice) and not create a complex payment term object that reflect the due date. As every supplier may have different payment terms or due dates, it's complex to create a payment term on each PO.

So, in my opinion, the official way of working on OpenERP should be to just set a due date on the PO and not a payment term. This is the most simple solution and most SMEs will prefer that way of working because it's easier to record a PO.

But I agree some companies may need a complex payment term management (as an example in the case where you negociate a payment term with your supplier for future purchaes). In that case, those companies will install the module of Alexis.

review: Disapprove
Revision history for this message
Alexis de Lattre (alexis-via) wrote :

Dear Fabien,

You say "Most of the time, when you do a Purchase Order, you just want to set a due date provided by the supplier", but it doesn't make sense to me : when your write a PO, you won't print a "due date" on your PO, you will print the "Payment term" that will apply on the supplier invoice that you will receive after the delivery of the goods/services. How could you print a "due date" on the PO when you don't know the delivery date yet (I suppose that delivery date = invoice date) ?

Let's take an example :
On 01/01/2012, Company A sends a PO to company B to buy a laptop. On the PO, it displays "Payment term = 30 days net". The laptop is delivered on 15/01/2012. On the invoice, company B wrote :
- date = 15/01/2012
- payment term = 30 days net
- due date = 14/02/2012.
When company A generates the supplier invoice in it's ERP, they may just want to set the "due date" that is displayed on the invoice... but they still needed to have the "payment term" displayed on the PO !

I could agree if you had said "When you do a Supplier invoice, you just want to set the due date that is displayed on the supplier invoice".

So I here is what I propose :
- we create a field 'supplier_payment_term' on res.partner
- we create a field 'payment_term' on purchase.order and we display it on the PO's report
- on purchase.order, the on_change of partner_id copies the "supplier_payment_term" of res.partner to the "payment_term" of purchase.order (that way, if there is a specific payment term for a particular PO, the user can change it on the PO without impacting the default payment term of future POs)
- when invoice control = "Based on receptions", the wizard asks for the invoice date AND the due date (it currently only asks for the invoice date). The payment term of the PO is NOT copied on the supplier invoice.
- when invoice control = "Based on generated draft invoice", we don't change the current behaviour. The payment term of the PO is NOT copied on the supplier invoice.

If you agree with what I propose, I will prepare a new merge proposal.

In fact, it was not a good thing to copy the "payment_term" from the PO to the supplier invoice (as I did in this merge proposal) because, if, on the supplier invoice, you manually set the "invoice date" and the "payment term" and the "due date" and you click on "Create", the "due date" is re-computed from the payment term and the invoice date just before the real validation. So you may end-up having a due date that is different from the due date that you entered manually by looking at the "due date" displayed on the supplier invoice.

Revision history for this message
Ana Juaristi Olalde (ajuaristio) wrote :

Payment terms on PO is needed functionality. It should be included on core as said by Raphaël and Alexis.
It's needed verifying that the due date coming in invoice is correct regarding the agreement you made on po.
We have got it included on l10n_es since 5.0 If it's also needed in other countries, I think it should be on core. Just my opinion.

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

+1

Stefan

review: Approve (functional)
Revision history for this message
Alexis de Lattre (alexis-via) wrote :

Just a short comment to inform you that Akretion is working on a third version of the merge proposal to add payment term on purchase.order. This third merge proposal will include :
- the remarks made by Quentin on the first (refused) merge proposal
https://code.launchpad.net/~akretion-team/openobject-addons/trunk-payment-term-on-purchase/+merge/90872
- the remarks made by Fabien on this merge proposal (= the second one, also refused). In fact, this third merge proposal will implement what I proposed 3 comments above this comment.

The code is being prepared in this branch : https://code.launchpad.net/~akretion-team/openobject-addons/trunk-payment-term-on-purchase-v3

The code is mostly written, but we can't test it because of this bug :
https://bugs.launchpad.net/openobject-server/+bug/1001926
(there is another bug concerning the generation of invoice from picking : https://bugs.launchpad.net/openobject-addons/+bug/1001806 but I wrote a patch for this one, so it's not blocking).

Revision history for this message
qdp (OpenERP) (qdp) wrote :

as per the last comment of Alexis, this merge proposal is deprecated.

Let's reject this one for the sake of "having-the-most-rejected-merge-proposal-that-finally-land-to-trunk" and let's focuss on what happens in v3 of this MP.

See you,
Quentin

Unmerged revisions

6459. By Alexis de Lattre

Remove useless 'a' variable.

6458. By Alexis de Lattre

Took into account the remarks made by Quentin de Paoli on my previous MP :
1. add a property "Supplier payment term" on res.partner
. rename the existing property to "Customer payment term"
. in the res.partner form view, add the "Supplier payment term" next to the "Customer payment term"
. modify the code of the 'account' module to use the supplier or customer payment term
  depending on the journal
2. better handle the case where no payment_term is given on the PO : if there is no payment_ter
  m on the PO, we use the payment term on the partner.

6457. By Alexis de Lattre

Remove my code change on fiscal_position (it had no impact... but I guess it is better not to change anything else)

6456. By Alexis de Lattre

Add payment_term on purchase.order object.
The behavior of payment_term is the same as for the sale order :
- the payment_term is copied from the partner to the purchase order
- then it is copied from the purchase order to the supplier invoice
Add payment_term to the purchase.order form view, next to fiscal position (same as for sale.order form view)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account/account.py'
2--- account/account.py 2012-02-14 13:30:53 +0000
3+++ account/account.py 2012-02-14 18:43:08 +0000
4@@ -2291,8 +2291,12 @@
5 if not line.partner_id:
6 raise osv.except_osv(_('Error !'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \
7 "\nPlease define partner on it!")%(line.name, model.name))
8- if line.partner_id.property_payment_term:
9+ payment_term_id = False
10+ if model.journal_id.type in ('purchase', 'purchase_refund') and line.partner_id.property_supplier_payment_term:
11+ payment_term_id = line.partner_id.property_supplier_payment_term.id
12+ elif line.partner_id.property_payment_term:
13 payment_term_id = line.partner_id.property_payment_term.id
14+ if payment_term_id:
15 pterm_list = pt_obj.compute(cr, uid, payment_term_id, value=1, date_ref=date_maturity)
16 if pterm_list:
17 pterm_list = [l[0] for l in pterm_list]
18
19=== modified file 'account/account_invoice.py'
20--- account/account_invoice.py 2012-02-14 12:25:20 +0000
21+++ account/account_invoice.py 2012-02-14 18:43:08 +0000
22@@ -434,10 +434,11 @@
23
24 if type in ('out_invoice', 'out_refund'):
25 acc_id = p.property_account_receivable.id
26+ partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
27 else:
28 acc_id = p.property_account_payable.id
29+ partner_payment_term = p.property_supplier_payment_term and p.property_supplier_payment_term.id or False
30 fiscal_position = p.property_account_position and p.property_account_position.id or False
31- partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
32 if p.bank_ids:
33 bank_id = p.bank_ids[0].id
34
35
36=== modified file 'account/account_move_line.py'
37--- account/account_move_line.py 2012-02-13 18:07:41 +0000
38+++ account/account_move_line.py 2012-02-14 18:43:08 +0000
39@@ -652,17 +652,24 @@
40 return {'value':val}
41 if not date:
42 date = datetime.now().strftime('%Y-%m-%d')
43+ jt = False
44+ if journal:
45+ jt = journal_obj.browse(cr, uid, journal).type
46 part = partner_obj.browse(cr, uid, partner_id)
47
48- if part.property_payment_term:
49- res = payment_term_obj.compute(cr, uid, part.property_payment_term.id, 100, date)
50+ payment_term_id = False
51+ if jt and jt in ('purchase', 'purchase_refund') and part.property_supplier_payment_term:
52+ payment_term_id = part.property_supplier_payment_term.id
53+ elif jt and part.property_payment_term:
54+ payment_term_id = part.property_payment_term.id
55+ if payment_term_id:
56+ res = payment_term_obj.compute(cr, uid, payment_term_id, 100, date)
57 if res:
58 val['date_maturity'] = res[0][0]
59 if not account_id:
60 id1 = part.property_account_payable.id
61 id2 = part.property_account_receivable.id
62- if journal:
63- jt = journal_obj.browse(cr, uid, journal).type
64+ if jt:
65 if jt in ('sale', 'purchase_refund'):
66 val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id2)
67 elif jt in ('purchase', 'sale_refund'):
68
69=== modified file 'account/partner.py'
70--- account/partner.py 2011-08-24 21:19:43 +0000
71+++ account/partner.py 2012-02-14 18:43:08 +0000
72@@ -180,9 +180,16 @@
73 'account.payment.term',
74 type='many2one',
75 relation='account.payment.term',
76- string ='Payment Term',
77- view_load=True,
78- help="This payment term will be used instead of the default one for the current partner"),
79+ string ='Customer Payment Term',
80+ view_load=True,
81+ help="This payment term will be used instead of the default one for sale orders and customer invoices"),
82+ 'property_supplier_payment_term': fields.property(
83+ 'account.payment.term',
84+ type='many2one',
85+ relation='account.payment.term',
86+ string ='Supplier Payment Term',
87+ view_load=True,
88+ help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
89 'ref_companies': fields.one2many('res.company', 'partner_id',
90 'Companies that refers to partner'),
91 'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were reconciled last time')
92
93=== modified file 'account/partner_view.xml'
94--- account/partner_view.xml 2011-09-21 07:13:12 +0000
95+++ account/partner_view.xml 2012-02-14 18:43:08 +0000
96@@ -80,12 +80,13 @@
97 <group col="2" colspan="2">
98 <separator string="Customer Accounting Properties" colspan="2"/>
99 <field name="property_account_receivable" groups="account.group_account_invoice" />
100+ <field name="property_payment_term" widget="selection"/>
101 <field name="property_account_position" widget="selection"/>
102- <field name="property_payment_term" widget="selection"/>
103 </group>
104 <group col="2" colspan="2">
105 <separator string="Supplier Accounting Properties" colspan="2"/>
106 <field name="property_account_payable" groups="account.group_account_invoice"/>
107+ <field name="property_supplier_payment_term" widget="selection"/>
108 </group>
109 <group col="2" colspan="2">
110 <separator string="Customer Credit" colspan="2"/>
111
112=== modified file 'base_vat/base_vat_view.xml'
113--- base_vat/base_vat_view.xml 2012-02-08 15:26:47 +0000
114+++ base_vat/base_vat_view.xml 2012-02-14 18:43:08 +0000
115@@ -7,7 +7,7 @@
116 <field name="model">res.partner</field>
117 <field name="inherit_id" ref="account.view_partner_property_form"/>
118 <field name="arch" type="xml">
119- <field name="property_account_payable" position="after">
120+ <field name="property_supplier_payment_term" position="after">
121 <group colspan="2" col="6">
122 <field name="vat" on_change="vat_change(vat)"/>
123 <button name="button_check_vat" string="Check VAT" type="object" icon="gtk-execute"/>
124
125=== modified file 'purchase/purchase.py'
126--- purchase/purchase.py 2012-02-14 12:25:20 +0000
127+++ purchase/purchase.py 2012-02-14 18:43:08 +0000
128@@ -204,6 +204,7 @@
129 'purchase.order.line': (_get_order, None, 10),
130 }, multi="sums",help="The total amount"),
131 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
132+ 'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
133 'product_id': fields.related('order_line','product_id', type='many2one', relation='product.product', string='Product'),
134 'create_uid': fields.many2one('res.users', 'Responsible'),
135 'company_id': fields.many2one('res.company','Company',required=True,select=1),
136@@ -266,12 +267,19 @@
137 def onchange_partner_id(self, cr, uid, ids, partner_id):
138 partner = self.pool.get('res.partner')
139 if not partner_id:
140- return {'value':{'partner_address_id': False, 'fiscal_position': False}}
141+ return {'value':{
142+ 'partner_address_id': False,
143+ 'fiscal_position': False,
144+ 'payment_term': False
145+ }}
146 supplier_address = partner.address_get(cr, uid, [partner_id], ['default'])
147 supplier = partner.browse(cr, uid, partner_id)
148- pricelist = supplier.property_product_pricelist_purchase.id
149- fiscal_position = supplier.property_account_position and supplier.property_account_position.id or False
150- return {'value':{'partner_address_id': supplier_address['default'], 'pricelist_id': pricelist, 'fiscal_position': fiscal_position}}
151+ return {'value': {
152+ 'partner_address_id': supplier_address['default'],
153+ 'pricelist_id': supplier.property_product_pricelist_purchase.id,
154+ 'fiscal_position': supplier.property_account_position and supplier.property_account_position.id or False,
155+ 'payment_term': supplier.property_supplier_payment_term and supplier.property_supplier_payment_term.id or False,
156+ }}
157
158 def wkf_approve_order(self, cr, uid, ids, context=None):
159 self.write(cr, uid, ids, {'state': 'approved', 'date_approve': fields.date.context_today(self,cr,uid,context=context)})
160@@ -382,7 +390,7 @@
161 'invoice_line': [(6, 0, inv_lines)],
162 'origin': order.name,
163 'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,
164- 'payment_term': order.partner_id.property_payment_term and order.partner_id.property_payment_term.id or False,
165+ 'payment_term': order.payment_term.id or order.partner_id.property_supplier_payment_term.id,
166 'company_id': order.company_id.id,
167 }
168 inv_id = inv_obj.create(cr, uid, inv_data, context=context)
169@@ -915,7 +923,8 @@
170 'pricelist_id': pricelist_id,
171 'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
172 'company_id': procurement.company_id.id,
173- 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False
174+ 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False,
175+ 'payment_term': partner.property_payment_term.id or False
176 }
177 res[procurement.id] = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=context)
178 self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': res[procurement.id]})
179
180=== modified file 'purchase/purchase_view.xml'
181--- purchase/purchase_view.xml 2012-01-31 13:36:57 +0000
182+++ purchase/purchase_view.xml 2012-02-14 18:43:08 +0000
183@@ -217,6 +217,7 @@
184 <group colspan="2" col="2">
185 <separator string="Invoice Control" colspan="2"/>
186 <field name="invoice_method"/>
187+ <field name="payment_term" widget="selection"/>
188 <field name="fiscal_position" widget="selection"/>
189 </group>
190 <newline/>
191
192=== modified file 'purchase/stock.py'
193--- purchase/stock.py 2012-02-01 11:37:24 +0000
194+++ purchase/stock.py 2012-02-14 18:43:08 +0000
195@@ -60,6 +60,8 @@
196 if picking.purchase_id:
197 invoice_vals['address_contact_id'], invoice_vals['address_invoice_id'] = \
198 self.pool.get('res.partner').address_get(cr, uid, [partner.id], ['contact', 'invoice']).values()
199+ invoice_vals['payment_term'] = picking.purchase_id.payment_term.id or \
200+ partner.property_supplier_payment_term.id
201 invoice_vals['fiscal_position'] = picking.purchase_id.fiscal_position.id
202 return invoice_vals
203
204
205=== modified file 'purchase/wizard/purchase_line_invoice.py'
206--- purchase/wizard/purchase_line_invoice.py 2011-09-08 09:27:55 +0000
207+++ purchase/wizard/purchase_line_invoice.py 2012-02-14 18:43:08 +0000
208@@ -73,25 +73,21 @@
209 name = orders and orders[0].name or ''
210 journal_id = account_jrnl_obj.search(cr, uid, [('type', '=', 'purchase')], context=None)
211 journal_id = journal_id and journal_id[0] or False
212- a = partner.property_account_payable.id
213- if partner and partner.property_payment_term.id:
214- pay_term = partner.property_payment_term.id
215- else:
216- pay_term = False
217 inv = {
218 'name': name,
219 'origin': name,
220 'type': 'in_invoice',
221 'journal_id':journal_id,
222 'reference' : partner.ref,
223- 'account_id': a,
224+ 'account_id': partner.property_account_payable.id,
225 'partner_id': partner.id,
226 'address_invoice_id': orders[0].partner_address_id.id,
227 'address_contact_id': orders[0].partner_address_id.id,
228 'invoice_line': [(6,0,lines_ids)],
229 'currency_id' : orders[0].pricelist_id.currency_id.id,
230 'comment': multiple_order_invoice_notes(orders),
231- 'payment_term': pay_term,
232+ 'payment_term': orders[0].payment_term.id or \
233+ partner.property_payment_term.id,
234 'fiscal_position': partner.property_account_position.id
235 }
236 inv_id = invoice_obj.create(cr, uid, inv)

Subscribers

People subscribed via source and target branches

to all changes: