[MERGE] New Purchase V9
This commit is contained in:
@@ -150,7 +150,7 @@ class AccountChartTemplate(models.Model):
|
||||
return default_account
|
||||
|
||||
journals = [{'name': _('Customer Invoices'), 'type': 'sale', 'code': _('INV'), 'favorite': True, 'sequence': 5},
|
||||
{'name': _('Vendor Bills'), 'type': 'purchase', 'code': _('EXJ'), 'favorite': True, 'sequence': 6},
|
||||
{'name': _('Vendor Bills'), 'type': 'purchase', 'code': _('BILL'), 'favorite': True, 'sequence': 6},
|
||||
{'name': _('Miscellaneous Operations'), 'type': 'general', 'code': _('MISC'), 'favorite': False, 'sequence': 7},
|
||||
{'name': _('Exchange Difference'), 'type': 'general', 'code': _('EXCH'), 'favorite': False, 'sequence': 9},]
|
||||
if journals_dict != None:
|
||||
|
||||
@@ -639,8 +639,7 @@
|
||||
Click to record a new vendor bill.
|
||||
</p><p>
|
||||
You can control the invoice from your vendor according to
|
||||
what you purchased or received. Odoo can also generate
|
||||
draft invoices automatically from purchase orders or receipts.
|
||||
what you purchased or received.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,8 +5,8 @@ import mail_mail
|
||||
import purchase
|
||||
import partner
|
||||
import stock
|
||||
import wizard
|
||||
import report
|
||||
import stock
|
||||
import company
|
||||
import res_config
|
||||
import invoice
|
||||
|
||||
@@ -30,13 +30,11 @@ Dashboard / Reports for Purchase Management will include:
|
||||
'data': [
|
||||
'security/purchase_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'purchase_workflow.xml',
|
||||
'invoice_view.xml',
|
||||
'purchase_sequence.xml',
|
||||
'company_view.xml',
|
||||
'purchase_data.xml',
|
||||
'purchase_data.yml',
|
||||
'wizard/purchase_order_group_view.xml',
|
||||
'wizard/purchase_line_invoice_view.xml',
|
||||
'purchase_report.xml',
|
||||
'purchase_view.xml',
|
||||
'stock_view.xml',
|
||||
@@ -57,15 +55,9 @@ Dashboard / Reports for Purchase Management will include:
|
||||
'test/fifo_returns.yml',
|
||||
# 'test/costmethodchange.yml',
|
||||
'test/process/cancel_order.yml',
|
||||
'test/process/rfq2order2done.yml',
|
||||
'test/process/generate_invoice_from_reception.yml',
|
||||
'test/process/merge_order.yml',
|
||||
'test/process/invoice_on_poline.yml',
|
||||
'test/ui/duplicate_order.yml',
|
||||
'test/ui/delete_order.yml',
|
||||
'test/average_price.yml',
|
||||
'test/anglo_saxon.yml',
|
||||
'test/anglo_saxon_avg_fifo.yml',
|
||||
],
|
||||
'demo': [
|
||||
'purchase_order_demo.yml',
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv,fields
|
||||
from openerp import api, fields, models, _
|
||||
|
||||
class company(osv.osv):
|
||||
class company(models.Model):
|
||||
_inherit = 'res.company'
|
||||
_columns = {
|
||||
'po_lead': fields.float(
|
||||
'Purchase Lead Time', required=True,
|
||||
help="Margin of error for vendor lead times. When the system "\
|
||||
"generates Purchase Orders for procuring products, "\
|
||||
"they will be scheduled that many days earlier "\
|
||||
"to cope with unexpected vendor delays."),
|
||||
}
|
||||
_defaults = {
|
||||
'po_lead': lambda *a: 1.0,
|
||||
}
|
||||
po_lead = fields.Float(string='Purchase Lead Time', required=True,
|
||||
help="Margin of error for vendor lead times. When the system "\
|
||||
"generates Purchase Orders for procuring products, "\
|
||||
"they will be scheduled that many days earlier "\
|
||||
"to cope with unexpected vendor delays.", default=1.0)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.tools.float_utils import float_compare
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
purchase_id = fields.Many2one('purchase.order', string='Purchase Order', domain=[('invoice_status', '=', 'to invoice')])
|
||||
|
||||
# Load all unsold PO lines
|
||||
@api.onchange('purchase_id')
|
||||
def purchase_order_change(self):
|
||||
result = []
|
||||
if not self.purchase_id:
|
||||
return {}
|
||||
if not self.partner_id:
|
||||
self.partner_id = self.purchase_id.partner_id.id
|
||||
done = False
|
||||
for line in self.purchase_id.order_line:
|
||||
if line.product_id.purchase_method == 'purchase':
|
||||
qty = line.product_qty - line.qty_invoiced
|
||||
else:
|
||||
qty = line.qty_received - line.qty_invoiced
|
||||
if float_compare(qty, 0.0, precision_rounding=line.product_uom.rounding) <= 0:
|
||||
continue
|
||||
done = True
|
||||
account = self.env['account.invoice.line'].get_invoice_line_account('in_invoice', line.product_id, self.purchase_id.fiscal_position_id, self.env.user.company_id)
|
||||
taxes = line.taxes_id or line.product_id.supplier_taxes_id
|
||||
invoice_line_tax_ids = self.purchase_id.fiscal_position_id.map_tax(taxes)
|
||||
result.append({
|
||||
'purchase_line_id': line.id,
|
||||
'name': line.name,
|
||||
'origin': self.purchase_id.origin,
|
||||
'uom_id': line.product_uom.id,
|
||||
'product_id': line.product_id.id,
|
||||
'account_id': account,
|
||||
'price_unit': line.price_unit,
|
||||
'quantity': qty,
|
||||
'discount': 0.0,
|
||||
'account_analytic_id': line.account_analytic_id.id,
|
||||
'invoice_line_tax_ids': invoice_line_tax_ids
|
||||
})
|
||||
self.invoice_line_ids = result
|
||||
if not done:
|
||||
warning = {
|
||||
'title': _('Bill Control Warning!'),
|
||||
'message' : _('None of the products from this purchase order can be billed. You should control the purchase order.')
|
||||
}
|
||||
return {'warning': warning}
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
""" Override AccountInvoice_line to add the link to the purchase order line it is related to"""
|
||||
_inherit = 'account.invoice.line'
|
||||
purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', select=True, readonly=True)
|
||||
|
||||
@api.model
|
||||
def move_line_get(self, invoice_id):
|
||||
res = super(AccountInvoiceLine, self).move_line_get(invoice_id)
|
||||
invoice = self.browse(invoice_id)
|
||||
if self.env.user.company_id.anglo_saxon_accounting:
|
||||
if invoice.type in ['in_invoice', 'in_refund']:
|
||||
for i_line in invoice.invoice_line_ids:
|
||||
res.extend(self._anglo_saxon_purchase_move_lines(i_line, res))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _anglo_saxon_purchase_move_lines(self, i_line, res):
|
||||
"""Return the additional move lines for purchase invoices and refunds.
|
||||
|
||||
i_line: An account.invoice.line object.
|
||||
res: The move line entries produced so far by the parent move_line_get.
|
||||
"""
|
||||
inv = i_line.invoice_id
|
||||
company_currency = inv.company_id.currency_id
|
||||
if i_line.product_id and i_line.product_id.valuation == 'real_time':
|
||||
if i_line.product_id.type != 'service':
|
||||
# get the price difference account at the product
|
||||
acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id
|
||||
if not acc:
|
||||
# if not found on the product get the price difference account at the category
|
||||
acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id
|
||||
a = None
|
||||
|
||||
# oa will be the stock input account
|
||||
# first check the product, if empty check the category
|
||||
oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id
|
||||
if not oa:
|
||||
oa = i_line.product_id.categ_id.property_stock_account_input_categ_id and i_line.product_id.categ_id.property_stock_account_input_categ_id.id
|
||||
if oa:
|
||||
# get the fiscal position
|
||||
fpos = i_line.invoice_id.fiscal_position_id or False
|
||||
a = fpos.map_account(oa)
|
||||
diff_res = []
|
||||
account_prec = inv.company_id.currency_id.decimal_places
|
||||
# calculate and write down the possible price difference between invoice price and product price
|
||||
for line in res:
|
||||
if line.get('invl_id', 0) == i_line.id and a == line['account_id']:
|
||||
uom = i_line.product_id.uom_id
|
||||
valuation_price_unit = uom._compute_price(i_line.product_id.standard_price, i_line.uom_id.id)
|
||||
if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
|
||||
#for average/fifo/lifo costing method, fetch real cost price from incomming moves
|
||||
stock_move_obj = self.env['stock.move']
|
||||
valuation_stock_move = stock_move_obj.search([('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1)
|
||||
if valuation_stock_move:
|
||||
valuation_price_unit = valuation_stock_move[0].price_unit
|
||||
if inv.currency_id.id != company_currency.id:
|
||||
valuation_price_unit = company_currency.compute(inv.currency_id, valuation_price_unit, context={'date': inv.date_invoice})
|
||||
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
|
||||
# price with discount and without tax included
|
||||
price_unit = self.env['account.tax'].compute_all(line['taxes'], i_line.price_unit * (1-(i_line.discount or 0.0)/100.0),\
|
||||
inv.currency_id.id, line['quantity'])['total_excluded']
|
||||
price_line = round(valuation_price_unit * line['quantity'], account_prec)
|
||||
price_diff = round(price_unit - price_line, account_prec)
|
||||
line.update({'price': price_line})
|
||||
diff_res.append({
|
||||
'type': 'src',
|
||||
'name': i_line.name[:64],
|
||||
'price_unit': round(price_diff / line['quantity'], account_prec),
|
||||
'quantity': line['quantity'],
|
||||
'price': price_diff,
|
||||
'account_id': acc,
|
||||
'product_id': line['product_id'],
|
||||
'uom_id': line['uom_id'],
|
||||
'account_analytic_id': line['account_analytic_id'],
|
||||
'taxes': line.get('taxes', []),
|
||||
})
|
||||
return diff_res
|
||||
return []
|
||||
@@ -0,0 +1,68 @@
|
||||
<odoo>
|
||||
<record id="action_invoice_pending" model="ir.actions.act_window">
|
||||
<field name="name">Vendor Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','=','in_invoice')]</field>
|
||||
<field name="context">{'default_type':'in_invoice', 'type':'in_invoice', 'journal_type': 'purchase'}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a draft invoice.
|
||||
</p><p>
|
||||
Use this menu to control the invoices to be received from your
|
||||
vendor. When registering a new bill, set the purchase order
|
||||
and Odoo will fill the bill automatically according to ordered
|
||||
or received quantities.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_open_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Vendor Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','in',('in_invoice', 'in_refund')),('purchase_id','=',active_id)]</field>
|
||||
<field name="context">{'default_type': 'in_invoice', 'type': 'in_invoice', 'journal_type': 'purchase', 'default_purchase_id': active_id}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to record a vendor bill related to this purchase.
|
||||
</p>
|
||||
<p>
|
||||
You can control the invoice from your vendor according to
|
||||
what you purchased (services) or received (products).
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_invoice_supplier_tree1_view1" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="account.invoice_supplier_tree"/>
|
||||
<field name="act_window_id" ref="purchase_open_invoice"/>
|
||||
</record>
|
||||
<record id="action_invoice__supplier_tree1_view2" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="act_window_id" ref="purchase_open_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="view_invoice_supplier_purchase_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.supplier.purchase</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reference" position="after" >
|
||||
<field name="purchase_id" domain="[('invoice_status', '=', 'to invoice'), ('partner_id', '=', partner_id)]" attrs="{'invisible': [('state', '<>', 'draft')]}" class="oe_edit_only"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='company_id']" position="after">
|
||||
<field name="purchase_line_id" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
+16
-23
@@ -1,32 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import api, fields, models
|
||||
|
||||
class res_partner(osv.osv):
|
||||
class res_partner(models.Model):
|
||||
_name = 'res.partner'
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def _purchase_invoice_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
PurchaseOrder = self.pool['purchase.order']
|
||||
Invoice = self.pool['account.invoice']
|
||||
return {
|
||||
partner_id: {
|
||||
'purchase_order_count': PurchaseOrder.search_count(cr,uid, [('partner_id', 'child_of', partner_id)], context=context),
|
||||
'supplier_invoice_count': Invoice.search_count(cr,uid, [('partner_id', 'child_of', partner_id), ('type','=','in_invoice')], context=context)
|
||||
}
|
||||
for partner_id in ids
|
||||
}
|
||||
@api.multi
|
||||
def _purchase_invoice_count(self):
|
||||
PurchaseOrder = self.env['purchase.order']
|
||||
Invoice = self.env['account.invoice']
|
||||
for partner in self:
|
||||
partner.purchase_order_count = PurchaseOrder.search_count([('partner_id', 'child_of', partner.id)])
|
||||
partner.supplier_invoice_count = Invoice.search_count([('partner_id', 'child_of', partner.id), ('type', '=', 'in_invoice')])
|
||||
|
||||
def _commercial_fields(self, cr, uid, context=None):
|
||||
return super(res_partner, self)._commercial_fields(cr, uid, context=context)
|
||||
@api.model
|
||||
def _commercial_fields(self):
|
||||
return super(res_partner, self)._commercial_fields()
|
||||
|
||||
_columns = {
|
||||
'property_purchase_currency_id': fields.property(
|
||||
type='many2one',
|
||||
relation='res.currency',
|
||||
string="Supplier Currency",
|
||||
help="This currency will be used, instead of the default one, for purchases from the current partner"),
|
||||
'purchase_order_count': fields.function(_purchase_invoice_count, string='# of Purchase Order', type='integer', multi="count"),
|
||||
'supplier_invoice_count': fields.function(_purchase_invoice_count, string='# Vendor Bills', type='integer', multi="count"),
|
||||
}
|
||||
property_purchase_currency_id = fields.Many2one('res.currency', string="Supplier Currency",\
|
||||
help="This currency will be used, instead of the default one, for purchases from the current partner")
|
||||
purchase_order_count = fields.Integer(compute='_purchase_invoice_count', string='# of Purchase Order')
|
||||
supplier_invoice_count = fields.Integer(compute='_purchase_invoice_count', string='# Vendor Bills')
|
||||
|
||||
+665
-1712
File diff suppressed because it is too large
Load Diff
@@ -3,86 +3,135 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_1}:
|
||||
partner_id: base.res_partner_1
|
||||
invoice_method: order
|
||||
order_line:
|
||||
- product_id: product.product_product_15
|
||||
price_unit: 79.80
|
||||
product_qty: 15.0
|
||||
- product_id: product.product_product_25
|
||||
price_unit: 2868.70
|
||||
product_qty: 5.0
|
||||
- product_id: product.product_product_27
|
||||
price_unit: 3297.20
|
||||
product_qty: 4.0
|
||||
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_1}:
|
||||
order_id: purchase.purchase_order_1
|
||||
product_id: product.product_product_15
|
||||
name: RAM SR3
|
||||
price_unit: 79.80
|
||||
product_qty: 15.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_2}:
|
||||
order_id: purchase_order_1
|
||||
product_id: product.product_product_25
|
||||
name: Laptop E5023
|
||||
price_unit: 2868.70
|
||||
product_qty: 5.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
!record {model: purchase.order.line, id: purchase_order_line_3}:
|
||||
order_id: purchase_order_1
|
||||
product_id: product.product_product_27
|
||||
name: Laptop Customized
|
||||
price_unit: 3297.20
|
||||
product_qty: 4.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
-
|
||||
Creating second order
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_2}:
|
||||
partner_id: base.res_partner_3
|
||||
invoice_method: picking
|
||||
order_line:
|
||||
- product_id: product.product_product_31
|
||||
name: Multimedia Speakers
|
||||
price_unit: 132.50
|
||||
product_qty: 20.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_29
|
||||
name: Pen drive, SP-2
|
||||
price_unit: 89
|
||||
product_qty: 5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_3}:
|
||||
partner_id: base.res_partner_12
|
||||
order_line:
|
||||
- product_id: product.product_product_2
|
||||
name: Support Services
|
||||
price_unit: 25.50
|
||||
product_qty: 10.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_4}:
|
||||
partner_id: base.res_partner_4
|
||||
order_line:
|
||||
- product_id: product.product_product_14
|
||||
name: RAM SR2 (kit)
|
||||
price_unit: 85.50
|
||||
product_qty: 6.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_20
|
||||
name: Motherboard I9P57
|
||||
price_unit: 1690
|
||||
product_qty: 5.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_6
|
||||
name: iPad Mini
|
||||
price_unit: 800
|
||||
product_qty: 7.0
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_5}:
|
||||
partner_id: base.res_partner_2
|
||||
order_line:
|
||||
- product_id: product.product_product_22
|
||||
name: Processor Core i5 2.70 Ghz
|
||||
product_qty: 3
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_24
|
||||
name: Graphics Card
|
||||
product_qty: 3
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_6}:
|
||||
partner_id: base.res_partner_1
|
||||
order_line:
|
||||
- product_id: product.product_product_38
|
||||
name: Ink Cartridge
|
||||
price_unit: 58
|
||||
product_qty: 9
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_39
|
||||
name: Toner Cartridge
|
||||
product_qty: 3
|
||||
price_unit: 65
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_44
|
||||
name: GrapWorks Software
|
||||
product_qty: 4
|
||||
price_unit: 154.5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_7}:
|
||||
partner_id: base.res_partner_4
|
||||
order_line:
|
||||
- product_id: product.product_product_12
|
||||
name: Mouse, Wireless
|
||||
product_qty: 5
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
- product_id: product.product_product_34
|
||||
name: Webcam
|
||||
product_qty: 15
|
||||
-
|
||||
!python {model: purchase.order} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type_id', '=', ref('account.data_account_type_expenses'))])
|
||||
if account_id:
|
||||
self.signal_workflow(cr, uid, [ref('purchase_order_2')], 'purchase_confirm')
|
||||
self.signal_workflow(cr, uid, [ref('purchase_order_6')], 'purchase_confirm')
|
||||
product_uom: product.product_uom_unit
|
||||
date_planned: !eval time.strftime('%Y-%m-%d')
|
||||
|
||||
+105
-251
@@ -18,9 +18,10 @@
|
||||
<menuitem
|
||||
id="menu_purchase_config_pricelist" name="Pricelists"
|
||||
parent="menu_purchase_config" sequence="20" groups="base.group_no_one"/>
|
||||
|
||||
<menuitem
|
||||
action="product.product_supplierinfo_type_action" id="menu_product_pricelist_action2_purchase"
|
||||
parent="menu_purchase_config_pricelist" sequence="1" groups="base.group_no_one"/>
|
||||
action="product.product_supplierinfo_type_action" id="menu_product_pricelist_action2_purchase"
|
||||
parent="menu_purchase_config_pricelist" sequence="1" groups="base.group_no_one"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_product_in_config_purchase" name="Products"
|
||||
@@ -50,39 +51,16 @@
|
||||
<!-- Purchase Control Menu -->
|
||||
<menuitem id="menu_purchase_control" name="Control" parent="base.menu_purchase_root" sequence="4"/>
|
||||
|
||||
<!--Inventory control-->
|
||||
<menuitem id="menu_procurement_management_inventory" name="Products"
|
||||
parent="menu_purchase_control" sequence="4"/>
|
||||
<!--Inventory control-->
|
||||
<menuitem action="stock.action_receipt_picking_move" id="menu_action_picking_tree_in_move"
|
||||
parent="menu_procurement_management_inventory" sequence="11"/>
|
||||
parent="menu_purchase_control" sequence="11"/>
|
||||
|
||||
<!--Invoice control-->
|
||||
<menuitem id="menu_procurement_management_invoice" name="Bills"
|
||||
parent="menu_purchase_control" sequence="6"/>
|
||||
|
||||
<record id="action_invoice_pending" model="ir.actions.act_window">
|
||||
<field name="name">Draft Bills</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar,pivot,graph</field>
|
||||
<field eval="False" name="view_id"/>
|
||||
<field name="domain">[('type','=','in_invoice')]</field>
|
||||
<field name="context">{'default_type':'in_invoice', 'type':'in_invoice', 'journal_type': 'purchase', 'search_default_draft': 1}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a draft invoice.
|
||||
</p><p>
|
||||
Use this menu to control the invoices to be received from your
|
||||
vendor. Odoo generates draft invoices from your purchase
|
||||
orders or receipts, according to your settings.
|
||||
</p><p>
|
||||
Once you receive a vendor bill, you can match it with the
|
||||
draft invoice and validate it.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_procurement_management_pending_invoice"
|
||||
action="action_invoice_pending"
|
||||
parent="menu_purchase_control"
|
||||
sequence="13"/>
|
||||
|
||||
<record id="product_normal_action_puchased" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
@@ -108,13 +86,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem
|
||||
id="menu_procurement_management_pending_invoice"
|
||||
action="action_invoice_pending"
|
||||
parent="menu_procurement_management_invoice"
|
||||
sequence="13"/>
|
||||
|
||||
<!-- Product menu-->
|
||||
<menuitem name="Products" id="menu_procurement_partner_contact_form" action="product_normal_action_puchased"
|
||||
parent="menu_procurement_management" sequence="20"/>
|
||||
@@ -124,7 +95,7 @@
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Calendar View" date_start="minimum_planned_date" color="partner_id">
|
||||
<calendar string="Calendar View" date_start="date_planned" color="partner_id">
|
||||
<field name="name"/>
|
||||
<field name="amount_total" widget="monetary"/>
|
||||
<field name="partner_id"/>
|
||||
@@ -152,30 +123,49 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_open_picking" model="ir.actions.act_window">
|
||||
<field name="name">Receptions</field>
|
||||
<field name="res_model">stock.picking</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('purchase_id', '=', active_id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_order_form" model="ir.ui.view">
|
||||
<field name="name">purchase.order.form</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Purchase Order">
|
||||
<header>
|
||||
<button name="bid_received" states="sent" string="Bid Received" class="oe_highlight"/>
|
||||
<button name="wkf_send_rfq" states="draft" string="Send RFQ by Email" type="object" context="{'send_rfq':True}" class="oe_highlight"/>
|
||||
<button name="wkf_send_rfq" states="sent" string="Re-Send RFQ by Email" type="object" context="{'send_rfq':True}"/>
|
||||
<button name="action_rfq_send" states="draft" string="Send RFQ by Email" type="object" context="{'send_rfq':True}" class="oe_highlight"/>
|
||||
<button name="action_rfq_send" states="sent" string="Re-Send RFQ by Email" type="object" context="{'send_rfq':True}"/>
|
||||
<button name="print_quotation" string="Print RFQ" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="print_quotation" string="Re-Print RFQ" type="object" states="sent" groups="base.group_user"/>
|
||||
<button name="purchase_confirm" states="draft" string="Confirm Order" id="draft_confirm"/>
|
||||
<button name="purchase_confirm" states="bid" string="Confirm Order" class="oe_highlight" id="bid_confirm"/>
|
||||
<button name="picking_ok" states="except_picking" string="Manually Corrected"/>
|
||||
<button name="invoice_ok" states="except_invoice" string="Manually Corrected"/>
|
||||
<button name="purchase_approve" states="confirmed" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
|
||||
<button name="wkf_send_rfq" states="approved" string="Send PO by Email" type="object" context="{'send_rfq':False}"/>
|
||||
<button name="view_picking" string="Receive Products" type="object" attrs="{'invisible': ['|', ('shipped','=',True), ('state','!=', 'approved')]}" class="oe_highlight"/>
|
||||
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','in', ['picking', 'manual']), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
|
||||
<button name="action_cancel_draft" states="cancel,sent,confirmed" string="Set to Draft" type="object" />
|
||||
<button name="action_cancel" states="draft,confirmed,sent,bid,approved,except_picking,except_invoice" string="Cancel" type="object" />
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,bid,approved,done" statusbar_colors='{"except_picking":"red","except_invoice":"red","confirmed":"blue"}' readonly="1"/>
|
||||
<button name="button_confirm" type="object" states="draft" string="Confirm Order" id="draft_confirm"/>
|
||||
<button name="button_confirm" type="object" states="sent" string="Confirm Order" class="oe_highlight" id="bid_confirm"/>
|
||||
<button name="button_approve" type="object" states="to approve" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
|
||||
<button name="action_rfq_send" states="approved" string="Send PO by Email" type="object" context="{'send_rfq':False}"/>
|
||||
<button name="%(purchase_open_picking)d" string="Receive Products" type="action" attrs="{'invisible': [('state','not in', ('purchase','done'))]}"/>
|
||||
<button name="button_draft" states="cancel" string="Set to Draft" type="object" />
|
||||
<button name="button_cancel" states="draft,to approve,sent,purchase" string="Cancel" type="object" />
|
||||
<button name="button_done" type="object" string="Set to Done" states="purchase"
|
||||
help="If a purchase order is done, you can not modify it manually anymore. But you will still be able to bill or receive."/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,purchase,done" readonly="1"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="action"
|
||||
name="%(purchase_open_picking)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck">
|
||||
<field name="picking_count" widget="statinfo" string="Shipment" help="Incoming Shipments"/>
|
||||
</button>
|
||||
<button type="action" name="%(purchase_open_invoice)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o">
|
||||
<field name="invoice_count" widget="statinfo" string="Invoices"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label string="Request for Quotation " attrs="{'invisible': [('state','not in',('draft','sent','bid'))]}"/>
|
||||
<label string="Purchase Order " attrs="{'invisible': [('state','in',('draft','sent','bid'))]}"/>
|
||||
@@ -185,81 +175,63 @@
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id, context)" context="{'search_default_supplier':1, 'default_supplier':1, 'default_customer':0}" domain="[('supplier','=',True)]"/>
|
||||
<field name="partner_id" context="{'search_default_supplier':1, 'default_supplier':1, 'default_customer':0}" domain="[('supplier','=',True)]"/>
|
||||
<field name="partner_ref"/>
|
||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||
<field name="journal_id" invisible='1'/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_order"/>
|
||||
<field name="origin" attrs="{'invisible': [('origin','=',False)]}"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="related_usage" invisible="1"/>
|
||||
<field name="bid_date" invisible="1"/>
|
||||
<field name="bid_validity" attrs="{'invisible':[('bid_date','=',False)]}"/>
|
||||
<field name="dest_address_id" string="Customer Address" on_change="onchange_dest_address_id(dest_address_id, context)"
|
||||
attrs="{'invisible':[('related_usage','!=','customer')],
|
||||
'required': [('related_usage','=', 'customer')]}"
|
||||
groups="stock.group_locations"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Products">
|
||||
<field name="order_line">
|
||||
<tree string="Purchase Order Lines" editable="bottom">
|
||||
<field name="product_id"
|
||||
on_change="onchange_product_id(product_id, 0, False,
|
||||
parent.partner_id, parent.date_order, parent.fiscal_position_id, date_planned,
|
||||
name, False, parent.state, True, parent.currency_id,context)"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<field name="product_id" context="{'partner_id': parent.partner_id}"/>
|
||||
<field name="name"/>
|
||||
<field name="date_planned"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="account_analytic_id" context="{'default_partner_id':parent.partner_id}" groups="purchase.group_analytic_accounting" domain="[('type','not in',('view','template'))]"/>
|
||||
<field name="product_qty"
|
||||
on_change="onchange_product_id(product_id, product_qty,
|
||||
product_uom, parent.partner_id, parent.date_order, parent.fiscal_position_id,
|
||||
date_planned, name, False, parent.state, False, parent.currency_id, context)"/>
|
||||
<field name="product_uom" groups="product.group_uom" on_change="onchange_product_uom(product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position_id,date_planned,name,False,parent.state,parent.currency_id,context)"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="qty_received" invisible="not context.get('show_purchase', False)"/>
|
||||
<field name="qty_invoiced" invisible="not context.get('show_purchase', False)"/>
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use','=','purchase')]"/>
|
||||
<field name="price_subtotal" widget="monetary"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</tree>
|
||||
<form>
|
||||
<group>
|
||||
<form string="Purchase Order Line">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
on_change="onchange_product_id(product_id, 0, False,
|
||||
parent.partner_id, parent.date_order, parent.fiscal_position_id, date_planned,
|
||||
name, False, parent.state, True, parent.currency_id, context)"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"
|
||||
on_change="onchange_product_id(product_id, product_qty,
|
||||
product_uom, parent.partner_id, parent.date_order, parent.fiscal_position_id,
|
||||
date_planned, name, False, parent.state, False, parent.currency_id, context)"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"
|
||||
on_change="onchange_product_uom(product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position_id,date_planned,name,False,parent.state,parent.currency_id,context)"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty"
|
||||
class="oe_inline"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
<group class="oe_subtotal_footer oe_right">
|
||||
@@ -267,8 +239,6 @@
|
||||
<field name="amount_tax" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
<div class="oe_subtotal_footer_separator oe_inline">
|
||||
<label for="amount_total"/>
|
||||
<button name="button_dummy"
|
||||
states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
</group>
|
||||
@@ -278,19 +248,14 @@
|
||||
<page string="Deliveries & Invoices">
|
||||
<group>
|
||||
<group>
|
||||
<field name="minimum_planned_date"/>
|
||||
<field name="picking_type_id" on_change="onchange_picking_type_id(picking_type_id, context)" domain="[('code','=','incoming')]" options="{'no_create': True}" context="{'special_shortened_wh_name': True}" groups="stock.group_locations"/>
|
||||
<field name="location_id" groups="stock.group_locations" string="Location"/>
|
||||
<field name="shipped" groups="base.group_no_one"/>
|
||||
<field name="date_planned"/>
|
||||
<field name="picking_type_id" domain="[('code','=','incoming')]" options="{'no_create': True}" context="{'special_shortened_wh_name': True}" groups="stock.group_locations"/>
|
||||
<field name="incoterm_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="invoice_method"/>
|
||||
<field name="invoiced" invisible="1"/>
|
||||
<field name="payment_term_id" options="{'no_open': True, 'no_create': True}"/>
|
||||
<field name="fiscal_position_id" attrs="{'readonly': [('invoiced','=', True)]}" />
|
||||
<!-- We do not need these fields anymore, the information is in open chatter -->
|
||||
<field name="validator" groups="base.group_no_one"/>
|
||||
<field name="invoice_status"/>
|
||||
<field name="payment_term_id" options="{'no_open': True, 'no_create': True}" attrs="{'readonly': [('invoice_status','=', 'invoiced')]}"/>
|
||||
<field name="fiscal_position_id" attrs="{'readonly': [('invoice_status','=', 'invoiced')]}" />
|
||||
<field name="date_approve" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
@@ -305,7 +270,7 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_request_for_quotation_filter" model="ir.ui.view">
|
||||
<record id="view_purchase_order_filter" model="ir.ui.view">
|
||||
<field name="name">request.quotation.select</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
@@ -314,45 +279,21 @@
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="product_id"/>
|
||||
<field name="create_uid"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter name="approved" string="Approved" domain="[('state','in',('approved','done'))]"/>
|
||||
<filter name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','in',('draft','sent','to approve'))]"/>
|
||||
<filter name="approved" string="Purchase Orders" domain="[('state','in',('purchase','done'))]"/>
|
||||
<separator/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_status','=', 'to invoice')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter name="invoiced" string="Invoiced" domain="[('invoice_status','=', 'invoiced')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Vendor" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Order Date" domain="[]" context="{'group_by':'date_order'}"/>
|
||||
<filter string="Expected Date" domain="[]" context="{'group_by':'minimum_planned_date'}"/>
|
||||
<filter string="Expected Date" domain="[]" context="{'group_by':'date_planned'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_purchase_order_filter" model="ir.ui.view">
|
||||
<field name="name">purchase.order.list.select</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Purchase Order">
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="product_id"/>
|
||||
<field name="create_uid"/>
|
||||
<filter name="draft" string="Quotations" domain="[('state','in',('draft','sent'))]"/>
|
||||
<filter name="approved" string="Purchase Orders" domain="[('state','not in',('draft','cancel'))]"/>
|
||||
<filter name="todo" string="To Do" domain="[('state','not in',('cancel','done'))]"/>
|
||||
<filter name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]"/>
|
||||
<separator/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]"/>
|
||||
<separator/>
|
||||
<filter string="Important Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Vendor" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Order Month" domain="[]" context="{'group_by':'date_order'}"/>
|
||||
<filter string="Expected Month" domain="[]" context="{'group_by':'minimum_planned_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Purchase Orders Kanban View -->
|
||||
<record model="ir.ui.view" id="view_sale_order_kanban">
|
||||
@@ -381,7 +322,7 @@
|
||||
<span><t t-esc="record.name.value"/> <t t-esc="record.date_order.value and record.date_order.value.split(' ')[0] or False"/></span>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<span t-attf-class="pull-right text-right label #{['draft', 'cancel'].indexOf(record.state.raw_value) > -1 ? 'label-default' : ['except_picking', 'except_invoice'].indexOf(record.state.raw_value) > -1 ? 'label-danger' : ['approved'].indexOf(record.state.raw_value) > -1 ? 'label-warning' : ['done'].indexOf(record.state.raw_value) > -1 ? 'label-success' : 'label-primary'}"><t t-esc="record.state.value"/></span>
|
||||
<span t-attf-class="pull-right text-right label #{['draft', 'cancel'].indexOf(record.state.raw_value) > -1 ? 'label-default' : ['approved'].indexOf(record.state.raw_value) > -1 ? 'label-warning' : ['done'].indexOf(record.state.raw_value) > -1 ? 'label-success' : 'label-primary'}"><t t-esc="record.state.value"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -395,13 +336,13 @@
|
||||
<field name="name">purchase.order.tree</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-bf="message_needaction==True" decoration-muted="state=='cancel'" decoration-info="state in ('wait','confirmed')" decoration-danger="state in ('except_invoice','except_picking')" string="Purchase Order">
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<tree decoration-bf="message_unread==True" decoration-muted="state=='cancel'" decoration-info="state in ('wait','confirmed')" string="Purchase Order">
|
||||
<field name="message_unread" invisible="1"/>
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="date_order" />
|
||||
<field name="partner_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="minimum_planned_date" invisible="context.get('quotation_only', False)"/>
|
||||
<field name="date_planned" invisible="context.get('quotation_only', False)"/>
|
||||
<field name="origin"/>
|
||||
<field name="amount_untaxed" sum="Total Untaxed amount" string="Untaxed" widget="monetary"/>
|
||||
<field name="amount_total" sum="Total amount" widget="monetary"/>
|
||||
@@ -440,7 +381,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">purchase.order</field>
|
||||
<field name="view_mode">tree,kanban,form,pivot,graph,calendar</field>
|
||||
<field name="context">{'search_default_todo':1}</field>
|
||||
<field name="context">{'search_default_todo':1, 'show_purchase': True}</field>
|
||||
<field name="domain">[('state','not in',('draft','sent','bid', 'confirmed'))]</field>
|
||||
<field name="search_view_id" ref="view_purchase_order_filter"/>
|
||||
<field name="help" type="html">
|
||||
@@ -456,42 +397,6 @@
|
||||
</record>
|
||||
<menuitem action="purchase_form_action" id="menu_purchase_form_action" parent="menu_procurement_management" sequence="6"/>
|
||||
|
||||
<record id="purchase_order_line_form" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.form</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Purchase Order Line">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id"/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="price_unit"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]"/>
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="name"/>
|
||||
</page><page string="Invoices and Incoming Shipments">
|
||||
<field name="invoice_lines"/>
|
||||
<field name="move_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_order_line_tree" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.tree</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
@@ -506,12 +411,10 @@
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="price_subtotal" widget="monetary"/>
|
||||
<field name="date_planned" widget="date" width="135"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="invoiced" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="purchase_order_line_form2" model="ir.ui.view">
|
||||
<field name="name">purchase.order.line.form2</field>
|
||||
<field name="model">purchase.order.line</field>
|
||||
@@ -521,7 +424,7 @@
|
||||
<sheet>
|
||||
<label for="order_id" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="order_id" class="oe_inline" domain="[('invoice_method','=','manual')]" />
|
||||
<field name="order_id" class="oe_inline"/>
|
||||
<label string="," attrs="{'invisible':[('date_order','=',False)]}"/>
|
||||
<field name="date_order" class="oe_inline"/>
|
||||
</h1>
|
||||
@@ -543,7 +446,6 @@
|
||||
<field name="date_planned" widget="date" readonly="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="account_analytic_id" colspan="4" groups="purchase.group_analytic_accounting"/>
|
||||
<field name="invoiced"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="name"/>
|
||||
@@ -574,42 +476,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_line_form_action2" model="ir.actions.act_window">
|
||||
<field name="name">Purchase Order Lines</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">purchase.order.line</field>
|
||||
<field name="domain">[('order_id.invoice_method','=','manual'), ('state','in',('confirmed','done')), ('invoiced', '=', False)]</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="purchase_order_line_search"/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
Here you can track all the lines of purchase orders where the
|
||||
invoicing is "Based on Purchase Order Lines", and for which you
|
||||
have not received a vendor bill yet. You can generate a
|
||||
draft vendor bill based on the lines from this list.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="purchase_line_form_action_tree2" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="purchase_order_line_tree"/>
|
||||
<field name="act_window_id" ref="purchase_line_form_action2"/>
|
||||
</record>
|
||||
<record id="purchase_line_form_action_form2" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="purchase_order_line_form2"/>
|
||||
<field name="act_window_id" ref="purchase_line_form_action2"/>
|
||||
</record>
|
||||
<menuitem
|
||||
action="purchase_line_form_action2"
|
||||
id="menu_purchase_line_order_draft"
|
||||
parent="menu_procurement_management_invoice"
|
||||
sequence="72"/>
|
||||
|
||||
<!-- Procurements -->
|
||||
|
||||
<record id="view_procurement_form_inherit" model="ir.ui.view">
|
||||
@@ -636,6 +502,9 @@
|
||||
<label for="purchase_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="uom_po_id" position="after">
|
||||
<field name="purchase_method" widget="radio" groups="base.group_no_one"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -664,7 +533,8 @@
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_purchase_line_product_tree">
|
||||
<field name="context">{}</field><!-- force empty -->
|
||||
<field name="context">{}</field>
|
||||
<field name="domain">[('product_id','in',active_ids)]</field>
|
||||
<field name="name">Purchases</field>
|
||||
<field name="res_model">purchase.order.line</field>
|
||||
<field name="view_id" ref="purchase_order_line_tree"/>
|
||||
@@ -691,25 +561,9 @@
|
||||
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" name="action_view_purchases" type="object"
|
||||
icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<field string="Purchases" name="purchase_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_product_normal_purchase_buttons_from" model="ir.ui.view">
|
||||
<field name="name">product.product.purchase.button.inherit</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" name="action_view_purchases" type="object"
|
||||
icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<button class="oe_stat_button" name="%(purchase.action_purchase_line_product_tree)d"
|
||||
type="action" icon="fa-shopping-cart"
|
||||
groups="base.group_no_one">
|
||||
<field string="Purchases" name="purchase_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="purchase_order" model="workflow">
|
||||
<field name="name">Purchase Order Basic Workflow</field>
|
||||
<field name="osv">purchase.order</field>
|
||||
<field name="on_create">True</field>
|
||||
</record>
|
||||
|
||||
<record id="act_draft" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="flow_start">True</field>
|
||||
<field name="name">draft</field>
|
||||
</record>
|
||||
<record id="act_sent" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">sent</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'sent'})</field>
|
||||
</record>
|
||||
<record id="act_bid" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">bid</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">wkf_bid_received()</field>
|
||||
</record>
|
||||
<record id="act_confirmed" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">confirmed</field>
|
||||
<field name="split_mode">OR</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">wkf_confirm_order()</field>
|
||||
</record>
|
||||
<record id="act_cancel" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">cancel</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="flow_stop">True</field>
|
||||
<field name="action">wkf_action_cancel()</field>
|
||||
</record>
|
||||
<record id="act_except_invoice" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">except_invoice</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'except_invoice'})</field>
|
||||
</record>
|
||||
<record id="act_except_picking" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">except_picking</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'except_picking'})</field>
|
||||
</record>
|
||||
<record id="act_router" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">router</field>
|
||||
<field name="split_mode">OR</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="join_mode">AND</field>
|
||||
<field name="action">wkf_approve_order()</field>
|
||||
</record>
|
||||
<record id="act_invoice" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice</field>
|
||||
<field name="kind">subflow</field>
|
||||
<field name="subflow_id" search="[('osv','=','account.invoice')]"/>
|
||||
<field name="action">action_invoice_create()</field>
|
||||
</record>
|
||||
<record id="act_invoice_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice_done</field>
|
||||
<field name="action">invoice_done()</field>
|
||||
<field name="kind">function</field>
|
||||
</record>
|
||||
<record id="act_invoice_end" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">invoice_end</field>
|
||||
</record>
|
||||
<record id="act_picking" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">picking</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">action_picking_create()</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="act_picking_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">picking_done</field>
|
||||
<field name="action">picking_done()</field>
|
||||
<field name="kind">function</field>
|
||||
</record>
|
||||
<record id="act_done" model="workflow.activity">
|
||||
<field name="wkf_id" ref="purchase_order"/>
|
||||
<field name="name">done</field>
|
||||
<field name="action">wkf_po_done()</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="flow_stop">True</field>
|
||||
<field name="join_mode">AND</field>
|
||||
</record>
|
||||
|
||||
<record id="trans_draft_confirmed" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_confirmed"/>
|
||||
<field name="signal">purchase_confirm</field>
|
||||
</record>
|
||||
<record id="trans_draft_sent" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_sent"/>
|
||||
<field name="signal">send_rfq</field>
|
||||
</record>
|
||||
<record id="trans_bid_confirmed" model="workflow.transition">
|
||||
<field name="act_from" ref="act_bid"/>
|
||||
<field name="act_to" ref="act_confirmed"/>
|
||||
<field name="signal">purchase_confirm</field>
|
||||
</record>
|
||||
<record id="trans_sent_bid" model="workflow.transition">
|
||||
<field name="act_from" ref="act_sent"/>
|
||||
<field name="act_to" ref="act_bid"/>
|
||||
<field name="signal">bid_received</field>
|
||||
</record>
|
||||
<record id="trans_sent_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_sent"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_bid_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_bid"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
|
||||
<record id="trans_confirmed_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_confirmed"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_draft_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_confirmed_router" model="workflow.transition">
|
||||
<field name="act_from" ref="act_confirmed"/>
|
||||
<field name="act_to" ref="act_router"/>
|
||||
<!-- <field name="signal">purchase_approve</field> removed from simplification/useability -->
|
||||
</record>
|
||||
<record id="trans_router_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_picking"/>
|
||||
<field name="condition">has_stockable_product()</field>
|
||||
</record>
|
||||
<record id="trans_router_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="condition">not has_stockable_product()</field>
|
||||
</record>
|
||||
<record id="trans_router_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_invoice"/>
|
||||
<field name="condition">invoice_method=='order'</field>
|
||||
</record>
|
||||
<record id="trans_router_invoice_no_order" model="workflow.transition">
|
||||
<field name="act_from" ref="act_router"/>
|
||||
<field name="act_to" ref="act_invoice_end"/>
|
||||
<field name="condition">invoice_method<>'order'</field>
|
||||
</record>
|
||||
<record id="trans_except_picking_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_picking"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="signal">picking_ok</field>
|
||||
</record>
|
||||
<record id="trans_except_invoice_invoice_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_invoice"/>
|
||||
<field name="act_to" ref="act_invoice_done"/>
|
||||
<field name="signal">invoice_ok</field>
|
||||
</record>
|
||||
<record id="trans_except_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_picking"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_except_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_except_invoice"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
</record>
|
||||
<record id="trans_picking_except_picking" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking"/>
|
||||
<field name="act_to" ref="act_except_picking"/>
|
||||
<field name="signal">picking_cancel</field>
|
||||
</record>
|
||||
<record id="trans_invoice_except_invoice" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice"/>
|
||||
<field name="act_to" ref="act_except_invoice"/>
|
||||
<field name="signal">subflow.cancel</field>
|
||||
</record>
|
||||
<record id="trans_picking_picking_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking"/>
|
||||
<field name="act_to" ref="act_picking_done"/>
|
||||
<field name="signal">picking_done</field>
|
||||
|
||||
</record>
|
||||
<record id="trans_invoice_invoice_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice"/>
|
||||
<field name="act_to" ref="act_invoice_done"/>
|
||||
<field name="signal">subflow.paid</field>
|
||||
</record>
|
||||
<record id="trans_picking_done_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_picking_done"/>
|
||||
<field name="act_to" ref="act_done"/>
|
||||
</record>
|
||||
<record id="trans_invoice_done_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_done"/>
|
||||
<field name="act_to" ref="act_invoice_end"/>
|
||||
</record>
|
||||
<record id="trans_invoice_end_done" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_end"/>
|
||||
<field name="act_to" ref="act_done"/>
|
||||
<field name="condition">invoiced</field>
|
||||
</record>
|
||||
<record id="trans_invoice_end_cancel" model="workflow.transition">
|
||||
<field name="act_from" ref="act_invoice_end"/>
|
||||
<field name="act_to" ref="act_cancel"/>
|
||||
<field name="signal">purchase_cancel</field>
|
||||
<field name="condition">invoice_method<>'order'</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -14,20 +14,17 @@ class purchase_report(osv.osv):
|
||||
_auto = False
|
||||
_columns = {
|
||||
'date': fields.datetime('Order Date', readonly=True, help="Date on which this document has been created"), # TDE FIXME master: rename into date_order
|
||||
'state': fields.selection([('draft', 'Request for Quotation'),
|
||||
('confirmed', 'Waiting Vendor Ack'),
|
||||
('approved', 'Approved'),
|
||||
('except_picking', 'Shipping Exception'),
|
||||
('except_invoice', 'Invoice Exception'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')],'Order Status', readonly=True),
|
||||
'state': fields.selection([('draft', 'Draft RFQ'),
|
||||
('sent', 'RFQ Sent'),
|
||||
('to approve', 'To Approve'),
|
||||
('purchase', 'Purchase Order'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')
|
||||
],'Order Status', readonly=True),
|
||||
'product_id':fields.many2one('product.product', 'Product', readonly=True),
|
||||
'picking_type_id': fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
|
||||
'location_id': fields.many2one('stock.location', 'Destination', readonly=True),
|
||||
'partner_id':fields.many2one('res.partner', 'Vendor', readonly=True),
|
||||
'date_approve':fields.date('Date Approved', readonly=True),
|
||||
'expected_date':fields.date('Expected Date', readonly=True),
|
||||
'validator' : fields.many2one('res.users', 'Validated By', readonly=True),
|
||||
'product_uom' : fields.many2one('product.uom', 'Reference Unit of Measure', required=True),
|
||||
'company_id':fields.many2one('res.company', 'Company', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
@@ -64,11 +61,9 @@ class purchase_report(osv.osv):
|
||||
select
|
||||
min(l.id) as id,
|
||||
s.date_order as date,
|
||||
l.state,
|
||||
s.state,
|
||||
s.date_approve,
|
||||
s.minimum_planned_date as expected_date,
|
||||
s.dest_address_id,
|
||||
s.validator,
|
||||
spt.warehouse_id as picking_type_id,
|
||||
s.partner_id as partner_id,
|
||||
s.create_uid as user_id,
|
||||
@@ -78,7 +73,6 @@ class purchase_report(osv.osv):
|
||||
p.product_tmpl_id,
|
||||
t.categ_id as category_id,
|
||||
t.uom_id as product_uom,
|
||||
s.location_id as location_id,
|
||||
sum(l.product_qty/u.factor*u2.factor) as quantity,
|
||||
extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
|
||||
extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
|
||||
@@ -108,20 +102,17 @@ class purchase_report(osv.osv):
|
||||
s.create_uid,
|
||||
s.partner_id,
|
||||
u.factor,
|
||||
s.location_id,
|
||||
l.price_unit,
|
||||
s.date_approve,
|
||||
l.date_planned,
|
||||
l.product_uom,
|
||||
s.minimum_planned_date,
|
||||
s.validator,
|
||||
s.dest_address_id,
|
||||
s.fiscal_position_id,
|
||||
l.product_id,
|
||||
p.product_tmpl_id,
|
||||
t.categ_id,
|
||||
s.date_order,
|
||||
l.state,
|
||||
s.state,
|
||||
spt.warehouse_id,
|
||||
u.uom_type,
|
||||
u.category_id,
|
||||
|
||||
@@ -61,13 +61,10 @@
|
||||
<field name="product_id"/>
|
||||
<group expand="0" string="Extended Filters">
|
||||
<field name="user_id"/>
|
||||
<field name="validator"/>
|
||||
<field name="location_id"/>
|
||||
<field name="picking_type_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="date"/>
|
||||
<field name="date_approve"/>
|
||||
<field name="expected_date"/>
|
||||
</group>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Vendor" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
|
||||
@@ -15,11 +15,6 @@ class purchase_config_settings(osv.osv_memory):
|
||||
], "Product Variants",
|
||||
help='Work with product variant allows you to define some variant of the same products, an ease the product management in the ecommerce for example',
|
||||
implied_group='product.group_product_variant'),
|
||||
'default_invoice_method': fields.selection(
|
||||
[('manual', 'Control vendor bill on purchase order line'),
|
||||
('picking', 'Control vendor bill on incoming shipments'),
|
||||
('order', 'Control vendor bill on a pregenerated draft invoice'),
|
||||
], 'Default invoicing control method', required=True, default_model='purchase.order'),
|
||||
'group_uom':fields.selection([
|
||||
(0, 'Products have only one unit of measure (easier)'),
|
||||
(1, 'Some products may be sold/puchased in different unit of measures (advanced)')
|
||||
@@ -53,10 +48,6 @@ class purchase_config_settings(osv.osv_memory):
|
||||
'-This installs the module stock_dropshipping.'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'default_invoice_method': 'order',
|
||||
}
|
||||
|
||||
|
||||
class account_config_settings(osv.osv_memory):
|
||||
_inherit = 'account.config.settings'
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
|
||||
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
|
||||
</header>
|
||||
<group string="Invoicing Process">
|
||||
<label for="id" string="Default Invoicing Settings"/>
|
||||
<div>
|
||||
<field name="default_invoice_method" widget="radio"/>
|
||||
</div>
|
||||
</group>
|
||||
<group string="Purchase Order">
|
||||
<field name="group_product_variant" widget="radio"/>
|
||||
<field name="group_uom" widget="radio"/>
|
||||
|
||||
+8
-141
@@ -6,6 +6,14 @@ from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
_columns = {
|
||||
'purchase_id': fields.related('move_lines', 'purchase_line_id', 'order_id', string="Purchase Orders",
|
||||
readonly=True, relation="many2one"),
|
||||
}
|
||||
|
||||
|
||||
class stock_move(osv.osv):
|
||||
_inherit = 'stock.move'
|
||||
_columns = {
|
||||
@@ -18,34 +26,8 @@ class stock_move(osv.osv):
|
||||
""" Returns the unit price to store on the quant """
|
||||
if move.purchase_line_id:
|
||||
return move.price_unit
|
||||
|
||||
return super(stock_move, self).get_price_unit(cr, uid, move, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
res = super(stock_move, self).write(cr, uid, ids, vals, context=context)
|
||||
from openerp import workflow
|
||||
if vals.get('state') in ['done', 'cancel']:
|
||||
po_to_check = []
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.purchase_line_id and move.purchase_line_id.order_id:
|
||||
order = move.purchase_line_id.order_id
|
||||
order_id = order.id
|
||||
# update linked purchase order as superuser as the warehouse
|
||||
# user may not have rights to access purchase.order
|
||||
if self.pool.get('purchase.order').test_moves_done(cr, uid, [order_id], context=context):
|
||||
workflow.trg_validate(SUPERUSER_ID, 'purchase.order', order_id, 'picking_done', cr)
|
||||
if self.pool.get('purchase.order').test_moves_except(cr, uid, [order_id], context=context):
|
||||
workflow.trg_validate(SUPERUSER_ID, 'purchase.order', order_id, 'picking_cancel', cr)
|
||||
if order_id not in po_to_check and vals['state'] == 'cancel' and order.invoice_method == 'picking':
|
||||
po_to_check.append(order_id)
|
||||
# Some moves which are cancelled might be part of a PO line which is partially
|
||||
# invoiced, so we check if some PO line can be set on "invoiced = True".
|
||||
if po_to_check:
|
||||
self.pool.get('purchase.order')._set_po_lines_invoiced(cr, uid, po_to_check, context=context)
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
default = default or {}
|
||||
context = context or {}
|
||||
@@ -54,121 +36,6 @@ class stock_move(osv.osv):
|
||||
default['purchase_line_id'] = False
|
||||
return super(stock_move, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def _get_master_data(self, cr, uid, move, inv_type, context=None):
|
||||
if inv_type == 'in_invoice' and move.purchase_line_id:
|
||||
purchase_order = move.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
if inv_type == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
|
||||
purchase_order = move.origin_returned_move_id.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
elif inv_type in ('in_invoice', 'in_refund') and move.picking_id:
|
||||
# In case of an extra move, it is better to use the data from the original moves
|
||||
for purchase_move in move.picking_id.move_lines:
|
||||
if purchase_move.purchase_line_id:
|
||||
purchase_order = purchase_move.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
|
||||
|
||||
partner = move.picking_id and move.picking_id.partner_id or False
|
||||
code = self.get_code_from_locs(cr, uid, move, context=context)
|
||||
if partner and code == 'incoming':
|
||||
currency = purchase_order.currency_id.id
|
||||
return partner, uid, currency
|
||||
return super(stock_move, self)._get_master_data(cr, uid, move, inv_type, context=context)
|
||||
|
||||
def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
|
||||
res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
|
||||
purchase_line = False
|
||||
if inv_type == 'in_invoice' and move.purchase_line_id:
|
||||
purchase_line = move.purchase_line_id
|
||||
elif inv_type == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
|
||||
purchase_line = move.origin_returned_move_id.purchase_line_id
|
||||
if purchase_line:
|
||||
res['invoice_line_tax_ids'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
|
||||
res['price_unit'] = purchase_line.price_unit
|
||||
res['account_analytic_id'] = purchase_line.account_analytic_id.id
|
||||
res['purchase_line_ids'] = [(4, purchase_line.id)]
|
||||
return res
|
||||
|
||||
def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None):
|
||||
is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, inv_type, context=context)
|
||||
if inv_type == 'in_invoice':
|
||||
for move in moves:
|
||||
if move.purchase_line_id:
|
||||
is_extra_move[move.id] = False
|
||||
extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.purchase_line_id.taxes_id])]
|
||||
elif move.product_id.product_tmpl_id.supplier_taxes_id:
|
||||
mov_id = self.search(cr, uid, [('purchase_line_id', '!=', False), ('picking_id', '=', move.picking_id.id)], limit=1, context=context)
|
||||
if mov_id:
|
||||
mov = self.browse(cr, uid, mov_id[0], context=context)
|
||||
fp = mov.purchase_line_id.order_id.fiscal_position
|
||||
res = self.pool.get("account.invoice.line").product_id_change(cr, uid, [], move.product_id.id, None, partner_id=move.picking_id.partner_id.id, fposition_id=(fp and fp.id), type='in_invoice', context=context)
|
||||
extra_move_tax[0, move.product_id] = [(6, 0, res['value']['invoice_line_tax_ids'])]
|
||||
return (is_extra_move, extra_move_tax)
|
||||
|
||||
def _get_taxes(self, cr, uid, move, context=None):
|
||||
if move.origin_returned_move_id.purchase_line_id.taxes_id:
|
||||
return [tax.id for tax in move.origin_returned_move_id.purchase_line_id.taxes_id]
|
||||
return super(stock_move, self)._get_taxes(cr, uid, move, context=context)
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
def _get_to_invoice(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for picking in self.browse(cr, uid, ids, context=context):
|
||||
res[picking.id] = False
|
||||
for move in picking.move_lines:
|
||||
if move.purchase_line_id and move.purchase_line_id.order_id.invoice_method == 'picking':
|
||||
if not move.move_orig_ids:
|
||||
res[picking.id] = True
|
||||
return res
|
||||
|
||||
def _get_picking_to_recompute(self, cr, uid, ids, context=None):
|
||||
picking_ids = set()
|
||||
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
|
||||
if move.picking_id and move.purchase_line_id:
|
||||
picking_ids.add(move.picking_id.id)
|
||||
return list(picking_ids)
|
||||
|
||||
_columns = {
|
||||
'reception_to_invoice': fields.function(_get_to_invoice, type='boolean', string='Invoiceable on incoming shipment',
|
||||
help='Does the picking contain some moves related to a purchase order invoiceable on the receipt?',
|
||||
store={
|
||||
'stock.move': (_get_picking_to_recompute, ['purchase_line_id', 'picking_id'], 10),
|
||||
}),
|
||||
}
|
||||
|
||||
def _get_invoice_vals(self, cr, uid, key, inv_type, journal_id, moves, context=None):
|
||||
inv_vals = super(stock_picking, self)._get_invoice_vals(cr, uid, key, inv_type, journal_id, moves, context=context)
|
||||
purchases = []
|
||||
for move in moves:
|
||||
if move.purchase_line_id or move.origin_returned_move_id.purchase_line_id:
|
||||
purchase = move.purchase_line_id.order_id or move.origin_returned_move_id.purchase_line_id.order_id
|
||||
inv_vals.update({
|
||||
'fiscal_position_id': purchase.fiscal_position_id.id,
|
||||
'payment_term_id': purchase.payment_term_id.id,
|
||||
})
|
||||
purchases.append(purchase.id)
|
||||
if purchases:
|
||||
inv_vals['purchase_ids'] = [(6, 0, list(set(purchases)))]
|
||||
return inv_vals
|
||||
|
||||
def get_service_line_vals(self, cr, uid, moves, partner, inv_type, context=None):
|
||||
purchase_obj = self.pool['purchase.order']
|
||||
purchase_line_obj = self.pool['purchase.order.line']
|
||||
res = super(stock_picking, self).get_service_line_vals(cr, uid, moves, partner, inv_type, context=context)
|
||||
# Add service lines for purchases
|
||||
if inv_type == 'in_invoice':
|
||||
purchase_ids = list(set([x.purchase_line_id.order_id.id for x in moves if x.purchase_line_id]))
|
||||
purchase_line_ids = purchase_line_obj.search(cr, uid, [('order_id', 'in', purchase_ids), ('invoice_lines', '=', False), '|', ('product_id', '=', False),
|
||||
('product_id.type', '=', 'service')], context=context)
|
||||
for po_line in purchase_line_obj.browse(cr, uid, purchase_line_ids, context=context):
|
||||
acc_id = purchase_obj._choose_account_from_po_line(cr, uid, po_line, context=context)
|
||||
inv_line_data = purchase_obj._prepare_inv_line(cr, uid, acc_id, po_line, context=context)
|
||||
inv_line_data['purchase_line_ids'] = [(4, po_line.id)]
|
||||
res += [(0, 0, inv_line_data)]
|
||||
return res
|
||||
|
||||
|
||||
class stock_warehouse(osv.osv):
|
||||
_inherit = 'stock.warehouse'
|
||||
|
||||
@@ -23,32 +23,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- is it need ? we have another method "Receive Products"-->
|
||||
<record id="purchase_order_2_stock_picking" model="ir.ui.view">
|
||||
<field name="name">Purchase Picking Inherited</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="inherit_id" ref="purchase.purchase_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[contains(@class, 'oe_title')]" position="before">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button type="object"
|
||||
name="view_picking"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
attrs="{'invisible': [('shipment_count', '=', 0)]}">
|
||||
<field name="shipment_count" widget="statinfo" string="Shipment" help="Incoming Shipments"/>
|
||||
</button>
|
||||
<button type="object" name="invoice_open"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
attrs="{'invisible': [('invoice_count', '=', 0)]}">
|
||||
<field name="invoice_count" widget="statinfo" string="Invoices"/>
|
||||
</button>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_warehouse_inherited" model="ir.ui.view">
|
||||
<field name="name">Stock Warehouse Inherited</field>
|
||||
<field name="model">stock.warehouse</field>
|
||||
@@ -60,28 +34,5 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_picking_tree_picking_to_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Incoming Shipments</field>
|
||||
<field name="res_model">stock.picking</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
<field name="context">{"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_reception_to_invoice": 1}</field>
|
||||
<field name="search_view_id" ref="stock.view_picking_internal_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new incoming shipment.
|
||||
</p><p>
|
||||
Here you can track all the product receipts of purchase
|
||||
orders where the invoicing is "Based on Incoming Shipments",
|
||||
and for which you have not received a supplier bill yet.
|
||||
You can generate a supplier bill based on those receipts.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_picking_tree_picking_to_invoice"
|
||||
id="menu_action_picking_tree_picking_to_invoice"
|
||||
parent="purchase.menu_procurement_management_invoice" sequence="90"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
-
|
||||
I first set the company to use anglo saxon accounting.
|
||||
-
|
||||
!python {model: res.company}: |
|
||||
self.pool.get('res.company').write(cr, uid, ref("base.main_company"), {'anglo_saxon_accounting': True,})
|
||||
-
|
||||
In order to test anglo_saxon Configure Different Accounts.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_valuation}:
|
||||
code: X3000
|
||||
name: Stock Valuation Account- (test)
|
||||
user_type_id: account.data_account_type_current_assets
|
||||
-
|
||||
Configure Stock Interim account (Received).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_input}:
|
||||
code: X2800
|
||||
name: Stock Interim account (Received)
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Stock Interim account (Delivered).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_output}:
|
||||
code: X2801
|
||||
name: Stock Interim account (Delivered)
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
Configure Price difference creditor Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_price_difference}:
|
||||
code: X7095
|
||||
name: Price difference creditor Account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Cash Bank Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cash}:
|
||||
code: X5000
|
||||
name: Cash/Bank Account
|
||||
user_type_id: account.data_account_type_liquidity
|
||||
reconcile: True
|
||||
-
|
||||
Configure Creditor Account Payable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_payable}:
|
||||
code: X440001
|
||||
name: Creditor Account Payable
|
||||
user_type_id: account.data_account_type_payable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Debtor Account Receivable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_receivable}:
|
||||
code: X400001
|
||||
name: Debtor Account Receivable
|
||||
user_type_id: account.data_account_type_receivable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Cost of Good sale Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cogs}:
|
||||
code: X7000
|
||||
name: Cost of goods sale account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Income Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_income}:
|
||||
code: X8000
|
||||
name: Income Account
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
I configure the account receivable of supplier
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_3}:
|
||||
property_account_payable_id: account_anglo_payable
|
||||
property_account_receivable_id: account_anglo_receivable
|
||||
-
|
||||
I configure the account receivable of Customer.
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_2}:
|
||||
property_account_payable_id: account_anglo_payable
|
||||
property_account_receivable_id: account_anglo_receivable
|
||||
-
|
||||
I configure the product category with stock valuation account.
|
||||
-
|
||||
!record {model: product.category, id: product.product_category_5}:
|
||||
property_stock_valuation_account_id: account_anglo_stock_valuation
|
||||
-
|
||||
I configure the product with required accounts, and cost method = standard
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
self.write(cr, uid, [ref('product.product_product_10')], {'list_price': 20.00,'standard_price': 9,'categ_id': ref('product.product_category_5'),'valuation': 'real_time',
|
||||
'property_account_income_id': ref('account_anglo_income'),'property_account_expense_id': ref('account_anglo_cogs'),
|
||||
'property_account_creditor_price_difference': ref('account_anglo_price_difference'),'property_stock_account_input': ref('account_anglo_stock_input'),
|
||||
'property_stock_account_output': ref('account_anglo_stock_output'), 'cost_method': 'standard'})
|
||||
-
|
||||
I create a draft Purchase Order.
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_001}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product.product_product_10
|
||||
product_qty: 1
|
||||
price_unit: 10
|
||||
date_planned: !eval "'%s' % (time.strftime('%Y-%m-%d'))"
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, ref: purchase_order_001, action: purchase_confirm}
|
||||
-
|
||||
Receipt is ready for process so now we do it.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001"), context=context).picking_ids[0]
|
||||
picking_id.do_transfer()
|
||||
-
|
||||
I check the Stock Interim account (Received) is credited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_input')).credit
|
||||
# float_compare(credit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not credited successfully."
|
||||
-
|
||||
I check the Stock valuation account is debited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_valuation')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock valuation account is not debited successfully."
|
||||
-
|
||||
I Validate Invoice of Purchase Order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001")).invoice_ids]
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
|
||||
-
|
||||
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_input')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not debited successfully."
|
||||
-
|
||||
I check the Price difference creditor Account is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_price_difference')).debit
|
||||
# float_compare(debit, 1, precision_digits=2) == 0, "Price difference creditor Account is not debited successfully."
|
||||
-
|
||||
I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_payable')).credit
|
||||
# float_compare(credit, 10, precision_digits=2) == 0, "Payable(creditor) Account is not Credited successfully."
|
||||
-
|
||||
I open the Invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
po = self.browse(cr, uid, ref("purchase_order_001"))
|
||||
for invoice in po.invoice_ids:
|
||||
invoice.signal_workflow('invoice_open')
|
||||
-
|
||||
I pay the invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = self.browse(cr, uid, ref("purchase_order_001")).invoice_ids
|
||||
order = self.browse(cr, uid, ref("purchase_order_001"))
|
||||
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
|
||||
import time
|
||||
for invoice in invoice_ids:
|
||||
self.pool.get('account.invoice').pay_and_reconcile(cr, uid, [invoice.id], journal_ids[0])
|
||||
-
|
||||
I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_payable')).debit
|
||||
# assert float_compare(debit, 10, precision_digits=2) == 0, "Payable(Creditors) Account is not Debited successfully."
|
||||
-
|
||||
I check Bank/Cash account is credited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_cash')).credit
|
||||
# float_compare(credit, 10, precision_digits=2) == 0, "Bank/Cash account is not credited successfully."
|
||||
-
|
||||
I create an Outgoing Picking order
|
||||
-
|
||||
!record {model: stock.picking, id: stock_picking_out001}:
|
||||
partner_id: base.res_partner_2
|
||||
move_lines:
|
||||
- company_id: base.main_company
|
||||
location_id: stock.stock_location_stock
|
||||
product_id: product.product_product_10
|
||||
product_uom_qty: 1.0
|
||||
product_uom: product.product_uom_unit
|
||||
location_dest_id: stock.stock_location_customers
|
||||
move_type: direct
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
I need to check the availability of the product, So I make my picking order for processing later.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('stock_picking_out001')], context=context)
|
||||
|
||||
-
|
||||
I check the product availability, Product is available in the stock and ready to be sent.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref("stock_picking_out001"))
|
||||
assert picking.state == "confirmed", "Picking should be confirmed."
|
||||
for move_line in picking.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
|
||||
-
|
||||
I process the delivery.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001"), context=context)
|
||||
picking.do_transfer()
|
||||
-
|
||||
I check Stock Interim account (Delivery) is debited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_output')).debit
|
||||
# float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Delivery) is not debited successfully."
|
||||
-
|
||||
I check the Stock valuation account is credited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_valuation')).credit
|
||||
# float_compare(credit, 9, precision_digits=2) == 0, "Stock valuation account is not credited successfully."
|
||||
@@ -1,247 +0,0 @@
|
||||
-
|
||||
I first set the company to use anglo saxon accounting.
|
||||
-
|
||||
!python {model: res.company}: |
|
||||
self.pool.get('res.company').write(cr, uid, ref("base.main_company"), {'anglo_saxon_accounting': True,})
|
||||
-
|
||||
In order to test anglo_saxon Configure Different Accounts.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_valuation_fifo}:
|
||||
code: X3000f
|
||||
name: Stock Valuation Account- (test)
|
||||
user_type_id: account.data_account_type_current_assets
|
||||
-
|
||||
Configure Stock Interim account (Received).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_input_fifo}:
|
||||
code: X2800f
|
||||
name: Stock Interim account (Received)
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Stock Interim account (Delivered).
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_stock_output_fifo}:
|
||||
code: X2801f
|
||||
name: Stock Interim account (Delivered)
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
Configure Price difference creditor Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_price_difference_fifo}:
|
||||
code: X7095f
|
||||
name: Price difference creditor Account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Cash Bank Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cash_fifo}:
|
||||
code: X5000f
|
||||
name: Cash/Bank Account
|
||||
user_type_id: account.data_account_type_liquidity
|
||||
reconcile: True
|
||||
-
|
||||
Configure Creditor Account Payable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_payable_fifo}:
|
||||
code: X440001f
|
||||
name: Creditor Account Payable
|
||||
user_type_id: account.data_account_type_payable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Debtor Account Receivable.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_receivable_fifo}:
|
||||
code: X400001f
|
||||
name: Debtor Account Receivable
|
||||
user_type_id: account.data_account_type_receivable
|
||||
reconcile: True
|
||||
-
|
||||
Configure Cost of Good sale Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_cogs_fifo}:
|
||||
code: X7000f
|
||||
name: Cost of goods sale account
|
||||
user_type_id: account.data_account_type_expenses
|
||||
-
|
||||
Configure Income Account.
|
||||
-
|
||||
!record {model: account.account, id: account_anglo_income_fifo}:
|
||||
code: X8000f
|
||||
name: Income Account
|
||||
user_type_id: account.data_account_type_revenue
|
||||
-
|
||||
I configure the account receivable of supplier
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_3}:
|
||||
property_account_payable_id: account_anglo_payable_fifo
|
||||
property_account_receivable_id: account_anglo_receivable_fifo
|
||||
-
|
||||
I configure the account receivable of Customer.
|
||||
-
|
||||
!record {model: res.partner, id: base.res_partner_2}:
|
||||
property_account_payable_id: account_anglo_payable_fifo
|
||||
property_account_receivable_id: account_anglo_receivable_fifo
|
||||
-
|
||||
I configure the product category with stock valuation account.
|
||||
-
|
||||
!record {model: product.category, id: product.product_category_5}:
|
||||
property_stock_valuation_account_id: account_anglo_stock_valuation_fifo
|
||||
-
|
||||
I create a product with required accounts, and cost method average (but same applies for fifo)
|
||||
-
|
||||
!record {model: product.product, id: product_fifo_anglo_saxon}:
|
||||
name: 'FIFO product for anglo saxon tests'
|
||||
lst_price: 20.00
|
||||
standard_price: 0
|
||||
categ_id: product.product_category_5
|
||||
valuation: 'real_time'
|
||||
property_account_income_id: account_anglo_income_fifo
|
||||
property_account_expense_id: account_anglo_cogs_fifo
|
||||
property_account_creditor_price_difference: account_anglo_price_difference_fifo
|
||||
property_stock_account_input: account_anglo_stock_input_fifo
|
||||
property_stock_account_output: account_anglo_stock_output_fifo
|
||||
cost_method: 'average'
|
||||
-
|
||||
I create a draft Purchase Order.
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_001_fifo}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_anglo_saxon
|
||||
product_qty: 1
|
||||
price_unit: 9
|
||||
date_planned: !eval "'%s' % (time.strftime('%Y-%m-%d'))"
|
||||
taxes_id: []
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, ref: purchase_order_001_fifo, action: purchase_confirm}
|
||||
-
|
||||
Receipt is ready for process so now we do it.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo"), context=context).picking_ids[0]
|
||||
picking_id.do_transfer()
|
||||
-
|
||||
I check the Stock Interim account (Received) is credit successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_input_fifo')).credit
|
||||
# assert float_compare(credit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not credited successfully."
|
||||
-
|
||||
I check the Stock valuation account is debit sucessfully.
|
||||
-
|
||||
!python {model: account.account, id}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_valuation_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock valuation account is not debited successfully."
|
||||
-
|
||||
I Validate Invoice of Purchase Order after having changed the price to 10.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids]
|
||||
line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)])
|
||||
self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10})
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
|
||||
-
|
||||
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_input_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Received) is not debited successfully."
|
||||
-
|
||||
I check the Price difference creditor Account is debited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_price_difference_fifo')).debit
|
||||
# assert float_compare(debit, 1, precision_digits=2) == 0, "Price difference creditor Account is not debited successfully."
|
||||
-
|
||||
I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_payable_fifo')).credit
|
||||
# assert float_compare(credit, 10, precision_digits=2) == 0, "Payable(creditor) Account is not Credited successfully."
|
||||
-
|
||||
I pay the invoice.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_ids = self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids
|
||||
order = self.browse(cr, uid, ref("purchase_order_001_fifo"))
|
||||
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
|
||||
import time
|
||||
for invoice in invoice_ids:
|
||||
self.pool.get('account.invoice').pay_and_reconcile(cr, uid, [invoice.id], journal_ids[0])
|
||||
-
|
||||
I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_payable_fifo')).debit
|
||||
# assert float_compare(debit, 10, precision_digits=2) == 0, "Payable(Creditors) Account is not Debited successfully."
|
||||
-
|
||||
I check Bank/Cash account is credited sucessfully after invoice paid.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_cash_fifo')).credit
|
||||
# assert float_compare(credit, 10, precision_digits=2) == 0, "Bank/Cash account is not credited successfully."
|
||||
-
|
||||
I create an Outgoing Picking order
|
||||
-
|
||||
!record {model: stock.picking, id: stock_picking_out001_fifo}:
|
||||
partner_id: base.res_partner_2
|
||||
move_lines:
|
||||
- company_id: base.main_company
|
||||
location_id: stock.stock_location_stock
|
||||
product_id: product_fifo_anglo_saxon
|
||||
product_uom_qty: 1.0
|
||||
location_dest_id: stock.stock_location_customers
|
||||
move_type: direct
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
I need to check the availability of the product, So I make my picking order for processing later.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
self.action_confirm(cr, uid, [ref('stock_picking_out001_fifo')], context=context)
|
||||
-
|
||||
I check the product availability, Product is available in the stock and ready to be sent.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.browse(cr, uid, ref("stock_picking_out001_fifo"))
|
||||
assert picking.state == "confirmed", "Picking should be confirmed."
|
||||
for move_line in picking.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
-
|
||||
I process the delivery.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001_fifo"), context=context)
|
||||
picking.do_transfer()
|
||||
-
|
||||
I check Stock Interim account (Delivery) is debited successfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to debit field is removed
|
||||
# debit = self.browse(cr, uid, ref('account_anglo_stock_output_fifo')).debit
|
||||
# assert float_compare(debit, 9, precision_digits=2) == 0, "Stock Interim account (Delivery) is not debited successfully."
|
||||
-
|
||||
I check the Stock valuation account is credited sucessfully.
|
||||
-
|
||||
!python {model: account.account}: |
|
||||
from openerp.tools import float_compare
|
||||
# Due to credit field is removed
|
||||
# credit = self.browse(cr, uid, ref('account_anglo_stock_valuation_fifo')).credit
|
||||
# assert float_compare(credit, 9, precision_digits=2) == 0, "Stock valuation account is not credited successfully."
|
||||
@@ -18,7 +18,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 10.0
|
||||
@@ -28,12 +27,13 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average1")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_average1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -52,7 +52,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 30.0
|
||||
@@ -62,7 +61,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
@@ -106,7 +106,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_average3}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_average_icecream
|
||||
product_qty: 500.0
|
||||
@@ -116,7 +115,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_average3}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_average3")])
|
||||
-
|
||||
Process the reception of purchase order 3 in grams
|
||||
-
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 10.0
|
||||
@@ -31,7 +30,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 30.0
|
||||
@@ -41,16 +39,18 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable1")])
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable2")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_variable1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -113,7 +113,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_variable3}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_variable_icecream
|
||||
product_qty: 20.0
|
||||
@@ -123,7 +122,8 @@
|
||||
-
|
||||
I confirm this third purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_variable3}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_variable3")])
|
||||
-
|
||||
Process the reception of purchase order 3
|
||||
-
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
!record {model: purchase.order, id: purchase_order_fifo1}:
|
||||
partner_id: base.res_partner_3
|
||||
currency_id: base.EUR
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 10.0
|
||||
@@ -36,12 +35,13 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo1")])
|
||||
-
|
||||
I check the "Approved" status of purchase order 1
|
||||
I check the "Purchase" status of purchase order 1
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_fifo1}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
Process the reception of purchase order 1 and set date
|
||||
-
|
||||
@@ -58,7 +58,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 30.0
|
||||
@@ -68,7 +67,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
@@ -160,7 +160,6 @@
|
||||
!record {model: purchase.order, id: purchase_order_fifo_usd}:
|
||||
partner_id: base.res_partner_3
|
||||
currency_id: new_USD
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_icecream
|
||||
product_qty: 30000
|
||||
@@ -174,7 +173,8 @@
|
||||
-
|
||||
I confirm the purchase order in USD
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_usd}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_usd")])
|
||||
-
|
||||
Process the reception of purchase order with usd
|
||||
-
|
||||
@@ -202,7 +202,7 @@
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
self.action_assign(cr, uid, [ref("outgoing_fifo_shipment_cur")])
|
||||
-
|
||||
-
|
||||
Process the delivery of the outgoing shipment
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
@@ -218,7 +218,7 @@
|
||||
-
|
||||
!record {model: stock.picking, id: outgoing_fifo_shipment_ret}:
|
||||
picking_type_id: stock.picking_type_out
|
||||
-
|
||||
-
|
||||
Picking needs movement from stock
|
||||
-
|
||||
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_ret}:
|
||||
@@ -320,7 +320,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo_neg}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_negative
|
||||
product_qty: 50.0
|
||||
@@ -330,7 +329,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg")])
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -348,7 +348,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fifo_neg2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fifo_negative
|
||||
product_qty: 60.0
|
||||
@@ -358,7 +357,8 @@
|
||||
-
|
||||
I confirm the second negative purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fifo_neg2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fiforet1}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fiforet_icecream
|
||||
product_qty: 10.0
|
||||
@@ -31,7 +30,6 @@
|
||||
-
|
||||
!record {model: purchase.order, id: purchase_order_fiforet2}:
|
||||
partner_id: base.res_partner_3
|
||||
location_id: stock.stock_location_stock
|
||||
order_line:
|
||||
- product_id: product_fiforet_icecream
|
||||
product_qty: 30.0
|
||||
@@ -41,7 +39,8 @@
|
||||
-
|
||||
I confirm the first purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fiforet1}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fiforet1")])
|
||||
-
|
||||
Process the reception of purchase order 1
|
||||
-
|
||||
@@ -56,7 +55,8 @@
|
||||
-
|
||||
I confirm the second purchase order
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fiforet2}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_fiforet2")])
|
||||
-
|
||||
Process the reception of purchase order 2
|
||||
-
|
||||
|
||||
@@ -8,50 +8,24 @@
|
||||
-
|
||||
I confirm the purchase order.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_5}
|
||||
!python {model: purchase.order}: |
|
||||
self.button_confirm(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check the "Approved" status after confirmed RFQ.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_5}:
|
||||
- state == 'approved'
|
||||
- state == 'purchase'
|
||||
-
|
||||
First I cancel receptions related to this order if order shipped.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
order = self.browse(cr, uid, ref("purchase_order_5"))
|
||||
self.pool.get('stock.picking').action_cancel(cr, uid, [picking.id for picking in order.picking_ids])
|
||||
-
|
||||
I check order status in "Shipping Exception".
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
order = self.browse(cr, uid, ref("purchase_order_5"))
|
||||
assert order.state == "except_picking", "order should be in Ship Exception state after cancel shipment"
|
||||
-
|
||||
Now I am able to cancel purchase order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check that order is cancelled.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_5}:
|
||||
- state == 'cancel'
|
||||
-
|
||||
After cancel the order, I check that it's related invoice cancelled.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
order = self.browse(cr, uid, ref("purchase_order_5"))
|
||||
assert order.invoice_ids[0].state == "cancel", "order's related invoice should be cancelled"
|
||||
-
|
||||
Now again set cancelled order to draft.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel_draft(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
Now I again to cancel draft order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
self.action_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
self.button_cancel(cr, uid, [ref("purchase_order_5")])
|
||||
-
|
||||
I check that order is cancelled.
|
||||
-
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
-
|
||||
Purchase user can create an invoice for order on receptions therfore test with that user which have Purchase user rights.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
I confirm another order where invoice control is 'Bases on incoming shipments'.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_2}
|
||||
-
|
||||
I check that the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_2"))
|
||||
assert len(purchase_order.invoice_ids) == 0, "Invoice should not be generated on order confirmation."
|
||||
-
|
||||
Now I create an invoice for order on reception.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
pick_ids = [self.browse(cr, uid, ref("purchase_order_2")).id]
|
||||
self.action_invoice_create(cr, uid, pick_ids)
|
||||
-
|
||||
I check that the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_2"))
|
||||
assert len(purchase_order.invoice_ids) == 1, "Invoice should be generated."
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
-
|
||||
Purchase User confirm the order and create invoice based on purchase order line.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
I confirm purchase order which has invoicing control method "Based on Purchase Order Lines".
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_6}
|
||||
-
|
||||
In order to test create invoice for purchase order line.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
invoice_line_obj = self.pool.get('purchase.order.line_invoice')
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_6"))
|
||||
context.update({'active_model': 'purchase.order', 'active_ids': [ref("purchase_order_6")]})
|
||||
for purchase_line in purchase_order.order_line:
|
||||
invoice_line_obj.makeInvoices(cr, uid, purchase_line.id, context=context)
|
||||
-
|
||||
I check the invoice of order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_6"))
|
||||
for purchase_line in purchase_order.order_line:
|
||||
assert len(purchase_order.invoice_ids) == 1, "Invoice should be generated."
|
||||
@@ -1,44 +0,0 @@
|
||||
-
|
||||
Give access rights of Purchase user to merge two RFQ.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_purchase_user'
|
||||
-
|
||||
In order to merge RFQ, I merge two RFQ which has same supplier and check new merged order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
context.update({"mail_create_nolog" : True })
|
||||
order3 = self.browse(cr, uid, ref('purchase_order_4'))
|
||||
order7 = self.browse(cr, uid, ref('purchase_order_7'))
|
||||
total_qty = sum([x.product_qty for x in order3.order_line] + [x.product_qty for x in order7.order_line])
|
||||
new_id = self.do_merge(cr, uid, [ref('purchase_order_4'), ref('purchase_order_7')], context=context)
|
||||
|
||||
assert order3.state == 'cancel', "Merged order should be canceled"
|
||||
assert order7.state == 'cancel', "Merged order should be canceled"
|
||||
|
||||
def merged_data(lines):
|
||||
product_id =[]
|
||||
product_uom = []
|
||||
res = {}
|
||||
for line in lines:
|
||||
product_id.append(line.product_id.id)
|
||||
product_uom.append(line.product_uom.id)
|
||||
res.update({'product_ids': product_id,'product_uom':product_uom})
|
||||
return res
|
||||
|
||||
for order in self.browse(cr, uid, new_id.keys()):
|
||||
assert order.state == 'draft',"New created order state should be in draft"
|
||||
assert order.partner_id == order3.partner_id ,"partner is not correspond"
|
||||
assert order.location_id == order3.location_id ,"Location is not correspond"
|
||||
|
||||
total_new_qty = sum(x.product_qty for x in order.order_line)
|
||||
assert total_new_qty == total_qty,"product quantities are not correspond"
|
||||
|
||||
date_order = min(order3.date_order, order7.date_order)
|
||||
assert order.date_order == date_order, "Date of order is not correspond"
|
||||
|
||||
n_product_data = merged_data(order.order_line)
|
||||
o_product_data= merged_data(order3.order_line)
|
||||
o_pro_data = merged_data(order7.order_line)
|
||||
assert n_product_data == o_product_data or o_pro_data,"product data are not correspond"
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
-
|
||||
In order to test the purchase order flow I compute the total of the listed products
|
||||
-
|
||||
I check the total untaxed amount of the RFQ is correctly computed
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
from openerp.tools import float_compare
|
||||
po = self.browse(cr, uid, ref('purchase_order_1'))
|
||||
assert float_compare(sum([l.price_subtotal for l in po.order_line]), po.amount_untaxed, precision_digits=2) == 0, "The amount of RFQ is not correctly computed"
|
||||
-
|
||||
I confirm the RFQ.
|
||||
-
|
||||
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_1}
|
||||
-
|
||||
I check the "Approved" status after confirmed RFQ.
|
||||
-
|
||||
!assert {model: purchase.order, id: purchase_order_1}:
|
||||
- state == 'approved'
|
||||
-
|
||||
I check that the invoice details which is generated after confirmed RFQ.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
from openerp.tools import float_compare
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_1"))
|
||||
assert len(purchase_order.invoice_ids) >= 1, "Invoice is not generated more or less than one"
|
||||
for invoice in purchase_order.invoice_ids:
|
||||
assert invoice.state == "draft", "Invoice state should be draft"
|
||||
assert invoice.partner_id.id == purchase_order.partner_id.id, "Vendor is not correspond with purchase order"
|
||||
assert invoice.reference == purchase_order.partner_ref or purchase_order.name,"Invoice reference is not correspond with purchase order"
|
||||
assert invoice.type == 'in_invoice',"Invoice type is not correspond with purchase order"
|
||||
assert invoice.origin == purchase_order.name,"Invoice origin is not correspond with purchase order"
|
||||
assert invoice.company_id.id == purchase_order.company_id.id ,"Invoice company is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_untaxed, purchase_order.amount_untaxed, precision_digits=2) == 0, "Invoice untaxed amount is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_tax, purchase_order.amount_tax, precision_digits=2) == 0, "Invoice tax amount is not correspond with purchase order"
|
||||
assert float_compare(invoice.amount_total, purchase_order.amount_total, precision_digits=2) == 0, "Invoice total amount is not correspond with purchase order"
|
||||
assert len(invoice.invoice_line_ids) == len(purchase_order.order_line), "Lines of Invoice and Purchase Order are not correspond"
|
||||
-
|
||||
I check that Reception details after confirmed RFQ.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
purchase_order = self.browse(cr, uid, ref("purchase_order_1"))
|
||||
assert len(purchase_order.picking_ids) >= 1, "You should have only one reception order"
|
||||
for picking in purchase_order.picking_ids:
|
||||
assert picking.state == "assigned", "Reception state should be in assigned state"
|
||||
assert picking.partner_id.id == purchase_order.partner_id.id, "Delivery address of reception id is different from order"
|
||||
assert picking.company_id.id == purchase_order.company_id.id, "Company is not correspond with purchase order"
|
||||
-
|
||||
Reception is ready for process so now done the reception.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_1"), context=context).picking_ids[0]
|
||||
pick_ids.do_transfer()
|
||||
-
|
||||
I check that purchase order is shipped.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
assert self.browse(cr, uid, ref("purchase_order_1")).shipped == True,"Purchase order should be delivered"
|
||||
|
||||
-
|
||||
I Validate Invoice of Purchase Order.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
for invoice in self.browse(cr, uid, ref('purchase_order_1'), context=context).invoice_ids:
|
||||
invoice.signal_workflow('invoice_open')
|
||||
-
|
||||
I check that purchase order is invoiced.
|
||||
-
|
||||
!python {model: purchase.order}: |
|
||||
assert self.browse(cr, uid, ref("purchase_order_1")).invoiced == True,"Purchase Order should be invoiced"
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_purchase_to_invoice
|
||||
from . import test_onchange_product_id
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
from openerp.tests.common import TransactionCase
|
||||
|
||||
class TestOnchangeProductId(TransactionCase):
|
||||
"""Test that when an included tax is mapped by a fiscal position, the included tax must be
|
||||
subtracted to the price of the product.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestOnchangeProductId, self).setUp()
|
||||
self.fiscal_position_model = self.registry('account.fiscal.position')
|
||||
self.fiscal_position_tax_model = self.registry('account.fiscal.position.tax')
|
||||
self.tax_model = self.registry('account.tax')
|
||||
self.res_partner_model = self.registry('res.partner')
|
||||
self.product_model = self.registry('product.product')
|
||||
self.product_uom_model = self.registry('product.uom')
|
||||
self.po_line_model = self.registry('purchase.order.line')
|
||||
|
||||
def test_onchange_product_id(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
uom_id = self.product_uom_model.search(cr, uid, [('name', '=', 'Unit(s)')])[0]
|
||||
partner_id = self.res_partner_model.create(cr, uid, dict(name="George"))
|
||||
tax_include_id = self.tax_model.create(cr, uid, dict(name="Include tax",
|
||||
amount_type='percent',
|
||||
amount='21.0',
|
||||
type_tax_use='purchase',
|
||||
price_include=True))
|
||||
tax_exclude_id = self.tax_model.create(cr, uid, dict(name="Exclude tax",
|
||||
amount_type='percent',
|
||||
type_tax_use='purchase',
|
||||
amount='0.00'))
|
||||
product_id = self.product_model.create(cr, uid, dict(name="Voiture",
|
||||
list_price='121',
|
||||
supplier_taxes_id=[(6, 0, [tax_include_id])]))
|
||||
fp_id = self.fiscal_position_model.create(cr, uid, dict(name="fiscal position",
|
||||
sequence=1))
|
||||
self.fiscal_position_tax_model.create(cr, uid, dict(position_id=fp_id,
|
||||
tax_src_id=tax_include_id,
|
||||
tax_dest_id=tax_exclude_id))
|
||||
res = self.po_line_model.onchange_product_id(cr, uid, [], product_id, 1.0, uom_id, partner_id,
|
||||
fiscal_position_id=fp_id)
|
||||
|
||||
self.assertEquals(0, res['value']['price_unit'], "The default price for products having no seller set is 0")
|
||||
#TODO: add back a test on this
|
||||
#self.assertEquals(100, res['value']['price_unit'], "The included tax must be subtracted to the price")
|
||||
@@ -1,60 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class TestPurchase(common.TransactionCase):
|
||||
|
||||
def test_purchase_to_invoice(self):
|
||||
""" Testing for invoice create,validate and pay with invoicing and payment user."""
|
||||
group_id = self.ref('account.group_account_invoice')
|
||||
product_id = self.ref('product.product_category_3')
|
||||
company_id = self.ref('base.main_company')
|
||||
location_id = self.ref('stock.stock_location_3')
|
||||
|
||||
# Useful accounts
|
||||
user_type_id = self.ref('account.data_account_type_expenses')
|
||||
account_exp_id = self.env['account.account'].create({'code': 'X2020', 'name': 'Purchase - Test Expense Account', 'user_type_id': user_type_id, 'reconcile': True})
|
||||
user_type_id = self.ref('account.data_account_type_payable')
|
||||
account_pay_id = self.env['account.account'].create({'code': 'X1012', 'name': 'Purchase - Test Payable Account', 'user_type_id': user_type_id, 'reconcile': True})
|
||||
|
||||
self.env['product.product'].browse(product_id).product_tmpl_id.write({'property_account_expense_id': account_exp_id})
|
||||
|
||||
# Create Purchase Journal
|
||||
self.env['account.journal'].create({'name': 'Purchase Journal - Test', 'code': 'PTPJ', 'type': 'purchase'})
|
||||
|
||||
# In order to test, I create new user and applied Invoicing & Payments group.
|
||||
user = self.env['res.users'].with_context({'no_reset_password': True}).create({
|
||||
'name': 'Test User',
|
||||
'login': 'test@test.com',
|
||||
'company_id': company_id,
|
||||
'groups_id': [(6, 0, [group_id])]})
|
||||
assert user, "User will not created."
|
||||
# I create partner for purchase order.
|
||||
partner = self.env['res.partner'].create({
|
||||
'name': 'Test Customer',
|
||||
'email': 'testcustomer@test.com',
|
||||
'property_account_payable_id': account_pay_id,
|
||||
})
|
||||
|
||||
# In order to test I create purchase order and confirmed it.
|
||||
order = self.env['purchase.order'].create({
|
||||
'partner_id': partner.id,
|
||||
'location_id': location_id, })
|
||||
self.env['purchase.order.line'].create({
|
||||
'order_id': order.id,
|
||||
'product_id': product_id,
|
||||
'product_qty': 100.0,
|
||||
'product_uom': 1,
|
||||
'price_unit': 89.0,
|
||||
'name': 'Service',
|
||||
'date_planned': '2014-05-31'})
|
||||
assert order, "purchase order will not created."
|
||||
context = {"active_model": 'purchase.order', "active_ids": [order.id], "active_id": order.id}
|
||||
order.with_context(context).wkf_confirm_order()
|
||||
# In order to test I create invoice.
|
||||
invoice = order.with_context(context).action_invoice_create()
|
||||
assert invoice, "No any invoice is created for this purchase order"
|
||||
# In order to test I validate invoice wihth Test User(invoicing and payment).
|
||||
res = self.env['account.invoice'].browse(invoice).with_context(context).invoice_validate()
|
||||
self.assertTrue(res, 'Invoice will not validated')
|
||||
@@ -43,10 +43,6 @@
|
||||
<strong>Order Date:</strong>
|
||||
<p t-field="o.date_order"/>
|
||||
</div>
|
||||
<div t-if="o.validator" class="col-xs-3">
|
||||
<strong>Validated By:</strong>
|
||||
<p t-field="o.validator"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-condensed">
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import purchase_order_group
|
||||
import purchase_line_invoice
|
||||
@@ -1,99 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class purchase_line_invoice(osv.osv_memory):
|
||||
|
||||
""" To create invoice for purchase order line"""
|
||||
|
||||
_name = 'purchase.order.line_invoice'
|
||||
_description = 'Purchase Order Line Make Invoice'
|
||||
|
||||
def _make_invoice_by_partner(self, cr, uid, partner, orders, lines_ids, context=None):
|
||||
"""
|
||||
create a new invoice for one vendor
|
||||
@param cr : Cursor
|
||||
@param uid : Id of current user
|
||||
@param partner : The object partner
|
||||
@param orders : The set of orders to add in the invoice
|
||||
@param lines : The list of line's id
|
||||
"""
|
||||
purchase_obj = self.pool.get('purchase.order')
|
||||
account_jrnl_obj = self.pool.get('account.journal')
|
||||
invoice_obj = self.pool.get('account.invoice')
|
||||
name = orders and orders[0].name or ''
|
||||
journal_id = account_jrnl_obj\
|
||||
.search(cr, uid, [('type', '=', 'purchase')], context=None)
|
||||
journal_id = journal_id and journal_id[0] or False
|
||||
a = partner.property_account_payable_id.id
|
||||
inv = {
|
||||
'name': name,
|
||||
'origin': name,
|
||||
'type': 'in_invoice',
|
||||
'journal_id': journal_id,
|
||||
'reference': partner.ref,
|
||||
'account_id': a,
|
||||
'partner_id': partner.id,
|
||||
'invoice_line_ids': [(6, 0, lines_ids)],
|
||||
'currency_id': orders[0].currency_id.id,
|
||||
'comment': " \n".join([order.notes for order in orders if order.notes]),
|
||||
'payment_term_id': orders[0].payment_term_id.id,
|
||||
'fiscal_position_id': partner.property_account_position_id.id
|
||||
}
|
||||
inv_id = invoice_obj.create(cr, uid, inv, context=context)
|
||||
purchase_obj.write(cr, uid, [order.id for order in orders], {'invoice_ids': [(4, inv_id)]}, context=context)
|
||||
return inv_id
|
||||
|
||||
def makeInvoices(self, cr, uid, ids, context=None):
|
||||
|
||||
"""
|
||||
To get Purchase Order line and create Invoice
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param context: A standard dictionary
|
||||
@return : retrun view of Invoice
|
||||
"""
|
||||
|
||||
if context is None:
|
||||
context={}
|
||||
|
||||
record_ids = context.get('active_ids',[])
|
||||
if record_ids:
|
||||
res = False
|
||||
invoices = {}
|
||||
purchase_obj = self.pool.get('purchase.order')
|
||||
purchase_line_obj = self.pool.get('purchase.order.line')
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
|
||||
for line in purchase_line_obj.browse(cr, uid, record_ids, context=context):
|
||||
if (not line.invoiced) and (line.state not in ('draft', 'cancel')):
|
||||
if not line.partner_id.id in invoices:
|
||||
invoices[line.partner_id.id] = []
|
||||
acc_id = purchase_obj._choose_account_from_po_line(cr, uid, line, context=context)
|
||||
inv_line_data = purchase_obj._prepare_inv_line(cr, uid, acc_id, line, context=context)
|
||||
inv_line_data.update({'origin': line.order_id.name})
|
||||
inv_id = invoice_line_obj.create(cr, uid, inv_line_data, context=context)
|
||||
purchase_line_obj.write(cr, uid, [line.id], {'invoiced': True, 'invoice_lines': [(4, inv_id)]})
|
||||
invoices[line.partner_id.id].append((line,inv_id))
|
||||
|
||||
res = []
|
||||
for result in invoices.values():
|
||||
il = map(lambda x: x[1], result)
|
||||
orders = list(set(map(lambda x : x[0].order_id, result)))
|
||||
|
||||
res.append(self._make_invoice_by_partner(cr, uid, orders[0].partner_id, orders, il, context=context))
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', ["+','.join(map(str,res))+"])]",
|
||||
'name': _('Vendor Bills'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'account.invoice',
|
||||
'view_id': False,
|
||||
'context': "{'type':'in_invoice', 'journal_type': 'purchase'}",
|
||||
'type': 'ir.actions.act_window'
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Make the invoice-->
|
||||
|
||||
<record id="view_purchase_line_invoice" model="ir.ui.view">
|
||||
<field name="name">Create invoices</field>
|
||||
<field name="model">purchase.order.line_invoice</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select an Open Sales Order">
|
||||
<group>
|
||||
<label string="Do you want to generate the supplier bills?"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="makeInvoices" string="Confirm" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window name="Create invoices"
|
||||
res_model="purchase.order.line_invoice"
|
||||
src_model="purchase.order.line"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="action_view_purchase_line_invoice"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import time
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class purchase_order_group(osv.osv_memory):
|
||||
_name = "purchase.order.group"
|
||||
_description = "Purchase Order Merge"
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
|
||||
context=None, toolbar=False, submenu=False):
|
||||
"""
|
||||
Changes the view dynamically
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param context: A standard dictionary
|
||||
@return: New arch of view.
|
||||
"""
|
||||
if context is None:
|
||||
context={}
|
||||
res = super(purchase_order_group, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
|
||||
if context.get('active_model','') == 'purchase.order' and len(context['active_ids']) < 2:
|
||||
raise UserError(_('Please select multiple order to merge in the list view.'))
|
||||
return res
|
||||
def merge_orders(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
To merge similar type of purchase orders.
|
||||
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: the ID or list of IDs
|
||||
@param context: A standard dictionary
|
||||
|
||||
@return: purchase order view
|
||||
|
||||
"""
|
||||
order_obj = self.pool.get('purchase.order')
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
mod_obj =self.pool.get('ir.model.data')
|
||||
if context is None:
|
||||
context = {}
|
||||
result = mod_obj._get_id(cr, uid, 'purchase', 'view_purchase_order_filter')
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
allorders = order_obj.do_merge(cr, uid, context.get('active_ids',[]), context)
|
||||
|
||||
return {
|
||||
'domain': "[('id','in', [" + ','.join(map(str, allorders.keys())) + "])]",
|
||||
'name': _('Purchase Orders'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'purchase.order',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id']
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_purchase_order_group" model="ir.ui.view">
|
||||
<field name="name">Merger Purchase Orders</field>
|
||||
<field name="model">purchase.order.group</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Merge orders">
|
||||
<group>
|
||||
<separator string="Are you sure you want to merge these orders?"/>
|
||||
<label string="
|
||||
Please note that:
|
||||
Orders will only be merged if:
|
||||
* Purchase Orders are in draft
|
||||
* Purchase Orders belong to the same supplier
|
||||
* Purchase Orders are have same stock location, same pricelist, same currency
|
||||
Lines will only be merged if:
|
||||
* Order lines are exactly the same except for the product,quantity and unit
|
||||
" colspan="4"/>
|
||||
</group>
|
||||
|
||||
<footer>
|
||||
<button name="merge_orders" string="Merge orders" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window name="Merge Purchase orders"
|
||||
context="{'search_default_draft': 1, 'search_default_approved': False}"
|
||||
res_model="purchase.order.group"
|
||||
src_model="purchase.order"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
multi="True"
|
||||
key2="client_action_multi"
|
||||
id="action_view_purchase_order_group"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import purchase_double_validation_installer
|
||||
@@ -1,29 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
{
|
||||
'name' : 'Double Validation on Purchases',
|
||||
'version' : '1.1',
|
||||
'category': 'Purchase Management',
|
||||
'depends' : ['base','purchase'],
|
||||
'description': """
|
||||
Double-validation for purchases exceeding minimum amount.
|
||||
=========================================================
|
||||
|
||||
This module modifies the purchase workflow in order to validate purchases that
|
||||
exceeds minimum amount set by configuration wizard.
|
||||
""",
|
||||
'website': 'https://www.odoo.com/page/purchase',
|
||||
'data': [
|
||||
'purchase_double_validation_workflow.xml',
|
||||
'purchase_double_validation_installer.xml',
|
||||
'purchase_double_validation_view.xml',
|
||||
],
|
||||
'test': [
|
||||
'test/purchase_double_validation_demo.yml',
|
||||
'test/purchase_double_validation_test.yml'
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
# Arabic translation for openobject-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-08-14 13:09+0000\n"
|
||||
"PO-Revision-Date: 2014-08-14 16:10+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Arabic <ar@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-08-15 07:44+0000\n"
|
||||
"X-Generator: Launchpad (build 17156)\n"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: help:purchase.config.settings,limit_amount:0
|
||||
msgid "Amount after which validation of purchase is required."
|
||||
msgstr "المبلغ الكلي لطلب الشراء الذي يحتاج إلى موافقة"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "Purchase orders which are not approved yet."
|
||||
msgstr "طلبات الشراء التي لم تتم الموافقة عليها."
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "To Approve"
|
||||
msgstr "للموافقة"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: field:purchase.config.settings,limit_amount:0
|
||||
msgid "limit to require a second approval"
|
||||
msgstr "تحديد لتتطلب موافقة ثانية"
|
||||
@@ -1,38 +0,0 @@
|
||||
# Bulgarian translation for openobject-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-08-14 13:09+0000\n"
|
||||
"PO-Revision-Date: 2014-08-14 16:10+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Bulgarian <bg@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-08-15 07:44+0000\n"
|
||||
"X-Generator: Launchpad (build 17156)\n"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: help:purchase.config.settings,limit_amount:0
|
||||
msgid "Amount after which validation of purchase is required."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "Purchase orders which are not approved yet."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "To Approve"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: field:purchase.config.settings,limit_amount:0
|
||||
msgid "limit to require a second approval"
|
||||
msgstr ""
|
||||
@@ -1,38 +0,0 @@
|
||||
# Bosnian translation for openobject-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-08-14 13:09+0000\n"
|
||||
"PO-Revision-Date: 2014-08-14 16:10+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Bosnian <bs@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-08-15 07:44+0000\n"
|
||||
"X-Generator: Launchpad (build 17156)\n"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: help:purchase.config.settings,limit_amount:0
|
||||
msgid "Amount after which validation of purchase is required."
|
||||
msgstr "Iznos nakon kojeg je potrebno odobrenje kupovine"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "Purchase orders which are not approved yet."
|
||||
msgstr "Prodajne narudžbe koje još nisu odobrene."
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "To Approve"
|
||||
msgstr "Za odobriti"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: field:purchase.config.settings,limit_amount:0
|
||||
msgid "limit to require a second approval"
|
||||
msgstr "ograniči da zahtjeva duplo odobrenje"
|
||||
@@ -1,38 +0,0 @@
|
||||
# Catalan translation for openobject-addons
|
||||
# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2014-08-14 13:09+0000\n"
|
||||
"PO-Revision-Date: 2014-08-14 16:10+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Catalan <ca@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-08-15 07:44+0000\n"
|
||||
"X-Generator: Launchpad (build 17156)\n"
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: help:purchase.config.settings,limit_amount:0
|
||||
msgid "Amount after which validation of purchase is required."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "Purchase orders which are not approved yet."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: view:purchase.order:purchase_double_validation.purchase_order_search_inherit
|
||||
msgid "To Approve"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_double_validation
|
||||
#: field:purchase.config.settings,limit_amount:0
|
||||
msgid "limit to require a second approval"
|
||||
msgstr ""
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user