Add a button to create invoices manually from purchase

#12412
This commit is contained in:
Cédric Krier
2023-07-19 11:26:33 +02:00
parent f86cd2c6d4
commit 3dac1d819d
5 changed files with 134 additions and 6 deletions
+1
View File
@@ -1,3 +1,4 @@
* Add a button to create invoices manually
Version 6.8.0 - 2023-05-01
--------------------------
+21 -6
View File
@@ -306,6 +306,12 @@ class Purchase(
'tryton-forward', 'tryton-refresh'),
'depends': ['state'],
},
'manual_invoice': {
'invisible': (
(Eval('invoice_method') != 'manual')
| ~Eval('state').in_(['processing', 'done'])),
'depends': ['invoice_method', 'state'],
},
'handle_invoice_exception': {
'invisible': ((Eval('invoice_state') != 'exception')
| (Eval('state') == 'cancelled')),
@@ -763,8 +769,9 @@ class Purchase(
def create_invoice(self):
'Create an invoice for the purchase and return it'
if self.invoice_method == 'manual':
context = Transaction().context
if (self.invoice_method == 'manual'
and not context.get('_purchase_manual_invoice', False)):
return
invoice_lines = []
@@ -998,6 +1005,13 @@ class Purchase(
if done:
cls.do(done)
@classmethod
@ModelView.button
def manual_invoice(cls, purchases):
purchases = [p for p in purchases if p.invoice_method == 'manual']
with Transaction().set_context(_purchase_manual_invoice=True):
cls.process(purchases)
@classmethod
@ModelView.button_action('purchase.wizard_modify_header')
def modify_header(cls, purchases):
@@ -1670,7 +1684,8 @@ class Line(sequence_ordered(), ModelSQL, ModelView):
def _get_invoice_not_line(self):
'Return if the not line should be invoiced'
return (self.purchase.invoice_method == 'order'
return (
self.purchase.invoice_method in {'order', 'manual'}
and not self.invoice_lines)
def _get_invoice_line_quantity(self):
@@ -1678,7 +1693,7 @@ class Line(sequence_ordered(), ModelSQL, ModelView):
pool = Pool()
Uom = pool.get('product.uom')
if (self.purchase.invoice_method == 'order'
if (self.purchase.invoice_method in {'order', 'manual'}
or not self.product
or self.product.type == 'service'):
return self.quantity
@@ -1717,7 +1732,7 @@ class Line(sequence_ordered(), ModelSQL, ModelView):
def _get_invoice_line_moves(self):
'Return the stock moves that should be invoiced'
moves = []
if self.purchase.invoice_method == 'order':
if self.purchase.invoice_method in {'order', 'manual'}:
moves.extend(self.moves)
elif self.purchase.invoice_method == 'shipment':
for move in self.moves:
@@ -1790,7 +1805,7 @@ class Line(sequence_ordered(), ModelSQL, ModelView):
def _get_move_invoice_lines(self, move_type):
'Return the invoice lines that should be shipped'
if self.purchase.invoice_method == 'order':
if self.purchase.invoice_method in {'order', 'manual'}:
return [l for l in self.invoice_lines]
else:
return [l for l in self.invoice_lines if not l.stock_moves]
+14
View File
@@ -344,6 +344,20 @@ this repository contains the full copyright notices and license terms. -->
<field name="group" ref="group_purchase_admin"/>
</record>
<record model="ir.model.button" id="purchase_manual_invoice_button">
<field name="name">manual_invoice</field>
<field name="string">Create Invoice</field>
<field name="model" search="[('model', '=', 'purchase.purchase')]"/>
</record>
<record model="ir.model.button-res.group" id="purchase_manual_button_group_purchase">
<field name="button" ref="purchase_manual_invoice_button"/>
<field name="group" ref="group_purchase"/>
</record>
<record model="ir.model.button-res.group" id="purchase_manual_button_group_account">
<field name="button" ref="purchase_manual_invoice_button"/>
<field name="group" ref="account.group_account"/>
</record>
<record model="ir.model.button" id="purchase_modify_header_button">
<field name="name">modify_header</field>
<field name="string">Modify Header</field>
@@ -0,0 +1,97 @@
================================
Purchase Manual Invoice Scenario
================================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.account.tests.tools import (
... create_chart, get_accounts)
Activate modules::
>>> config = activate_modules('purchase')
>>> Party = Model.get('party.party')
>>> ProductCategory = Model.get('product.category')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> Purchase = Model.get('purchase.purchase')
Create company::
>>> _ = create_company()
Create chart of accounts::
>>> _ = create_chart()
>>> accounts = get_accounts()
Create party::
>>> supplier = Party(name='Supplier')
>>> supplier.save()
Create account category::
>>> account_category = ProductCategory(name="Account Category")
>>> account_category.accounting = True
>>> account_category.account_expense = accounts['expense']
>>> account_category.save()
Create product::
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
>>> template.type = 'service'
>>> template.purchasable = True
>>> template.account_category = account_category
>>> product, = template.products
>>> product.cost_price = Decimal('5')
>>> template.save()
>>> product, = template.products
Purchase with manual invoice method::
>>> purchase = Purchase()
>>> purchase.party = supplier
>>> purchase.invoice_method = 'manual'
>>> line = purchase.lines.new()
>>> line.product = product
>>> line.quantity = 10
>>> purchase.click('quote')
>>> purchase.click('confirm')
>>> purchase.state
'done'
>>> purchase.invoice_state
'none'
>>> len(purchase.invoices)
0
Manually create an invoice::
>>> purchase.click('manual_invoice')
>>> purchase.state
'processing'
>>> purchase.invoice_state
'pending'
Change quantity on invoice and create a new invoice::
>>> invoice, = purchase.invoices
>>> line, = invoice.lines
>>> line.quantity = 5
>>> invoice.save()
>>> len(purchase.invoices)
1
>>> purchase.click('manual_invoice')
>>> len(purchase.invoices)
2
+1
View File
@@ -77,6 +77,7 @@ this repository contains the full copyright notices and license terms. -->
<button name="handle_shipment_exception" icon="tryton-forward"/>
<button name="confirm" icon="tryton-ok"/>
<button name="process"/>
<button name="manual_invoice" icon="tryton-forward"/>
</group>
<field name="party_lang" invisible="1" colspan="6"/>
</form>