Shipping address :
- [[ o.partner_id.name ]] [[ o.partner_id.title or '' ]]
+ [[ o.partner_id.title or '' ]] [[ o.partner_id.name ]]
[[ o.partner_shipping_id.title or '' ]] [[ o.partner_shipping_id.name ]]
[[ o.partner_shipping_id.street ]]
[[ o.partner_shipping_id.street2 or '' ]]
@@ -144,10 +144,10 @@
Invoice address :
- [[ o.partner_invoice_id.title or '' ]] [[ o.partner_invoice_id.name or '' ]]
+ [[ o.partner_invoice_id.title or '' ]] [[ o.partner_invoice_id.name or '' ]]
[[ o.partner_invoice_id.street ]] [[ o.partner_invoice_id.street2 and (', %s' % o.partner_invoice_id.street2 or '') ]]
[[ o.partner_invoice_id.zip or '' ]] [[ o.partner_invoice_id.city or '' ]]
- [[ o.partner_invoice_id.state_id and o.partner_invoice_id.state_id.name or '' ]] [[ o.partner_invoice_id.country_id and o.partner_invoice_id.country_id.name or '' ]]
+ [[ o.partner_invoice_id.state_id and o.partner_invoice_id.state_id.name or '' ]][[ o.partner_invoice_id.country_id and o.partner_invoice_id.country_id.name or '' ]]
@@ -155,7 +155,7 @@
- [[ o.partner_id.name ]] [[ o.partner_id.title or '' ]]
+ [[ o.partner_id.title or '' ]] [[ o.partner_id.name ]]
[[ o.partner_order_id.title or '' ]] [[ o.partner_order_id.name ]]
[[ o.partner_order_id.street ]]
[[ o.partner_order_id.street2 or '' ]]
@@ -187,7 +187,8 @@
Your Reference
- [[ o.state=='draft' and 'Quotation Date' or 'Date Ordered' ]]
+ [[ o.state=='draft' and removeParentNode('para') ]] Date Ordered
+ [[ o.state <> 'draft' and removeParentNode('para') ]] Quotation Date
Our Salesman
@@ -240,7 +241,7 @@
[[repeatIn(o.order_line,'line')]]
-
+
[[ line.name ]]
@@ -370,4 +371,4 @@
-
+
\ No newline at end of file
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index 332a551ec5d..fe88fa33555 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -78,10 +78,6 @@
-
form
tree,graph
- {'search_default_month':1,'search_default_User':1,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_month':1,'search_default_User':1,'search_default_user_id':uid,'group_by_no_leaf':1,'group_by':[]}
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 718f29f12d7..272ee0ecd70 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -52,6 +52,7 @@ def _incoterm_get(self, cr, uid, context=None):
class sale_order(osv.osv):
_name = "sale.order"
+ _log_create = True
_description = "Sale Order"
def copy(self, cr, uid, id, default=None, context=None):
@@ -106,17 +107,19 @@ class sale_order(osv.osv):
for id in ids:
res[id] = [0.0, 0.0]
cr.execute('''SELECT
- p.sale_id,sum(m.product_qty), m.state
+ p.sale_id,sum(m.product_qty), mp.state as mp_state
FROM
stock_move m
LEFT JOIN
stock_picking p on (p.id=m.picking_id)
+ LEFT JOIN
+ mrp_procurement mp on (mp.move_id=m.id)
WHERE
- p.sale_id = ANY(%s) GROUP BY m.state, p.sale_id''',(ids,))
- for oid, nbr, state in cr.fetchall():
- if state == 'cancel':
+ p.sale_id = ANY(%s) GROUP BY mp.state, p.sale_id''',(ids,))
+ for oid, nbr, mp_state in cr.fetchall():
+ if mp_state == 'cancel':
continue
- if state == 'done':
+ if mp_state == 'done':
res[oid][0] += nbr or 0.0
res[oid][1] += nbr or 0.0
else:
@@ -434,7 +437,7 @@ class sale_order(osv.osv):
'currency_id': order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': pay_term,
- 'fiscal_position': order.partner_id.property_account_position.id,
+ 'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,
'date_invoice' : context.get('date_invoice',False),
'company_id' : order.company_id.id,
}
@@ -508,18 +511,14 @@ class sale_order(osv.osv):
def action_invoice_end(self, cr, uid, ids, context=None):
if context is None:
context = {}
+
for order in self.browse(cr, uid, ids, context=context):
- val = {'invoiced': True}
- if order.state == 'invoice_except':
- val['state'] = 'progress'
-
for line in order.order_line:
- towrite = []
if line.state == 'exception':
- towrite.append(line.id)
- if towrite:
- self.pool.get('sale.order.line').write(cr, uid, towrite, {'state': 'confirmed'}, context=context)
- self.write(cr, uid, [order.id], val)
+ self.pool.get('sale.order.line').write(cr, uid, [line.id], {'state': 'confirmed'}, context=context)
+
+ if order.state == 'invoice_except':
+ self.write(cr, uid, [order.id], {'state' : 'progress'}, context=context)
return True
@@ -553,16 +552,10 @@ class sale_order(osv.osv):
return True
def action_wait(self, cr, uid, ids, *args):
- event_p = self.pool.get('res.partner.event.type').check(cr, uid, 'sale_open')
- event_obj = self.pool.get('res.partner.event')
+ for (id,name) in self.name_get(cr, uid, ids):
+ message = _('Quotation ') + " '" + name + "' "+ _("converted to sale order.")
+ self.log(cr, uid, id, message)
for o in self.browse(cr, uid, ids):
- if event_p:
- event_obj.create(cr, uid, {'name': 'Sale Order: '+ o.name,\
- 'partner_id': o.partner_id.id,\
- 'date': time.strftime('%Y-%m-%d %H:%M:%S'),\
- 'user_id': (o.user_id and o.user_id.id) or uid,\
- 'partner_type': 'customer', 'probability': 1.0,\
- 'planned_revenue': o.amount_untaxed})
if (o.order_policy == 'manual'):
self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': time.strftime('%Y-%m-%d')})
else:
@@ -813,7 +806,7 @@ class sale_order_line(osv.osv):
return res
_name = 'sale.order.line'
- _description = 'Sale Order line'
+ _description = 'Sale Order Line'
_columns = {
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
'name': fields.char('Description', size=256, required=True, select=True, readonly=True, states={'draft':[('readonly',False)]}),
@@ -1072,7 +1065,7 @@ class sale_order_line(osv.osv):
'product_uos':
[('category_id', '=', uos_category_id)]}
- elif uos: # only happens if uom is False
+ elif uos and not uom: # only happens if uom is False
result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id
result['product_uom_qty'] = qty_uos / product_obj.uos_coeff
result['th_weight'] = result['product_uom_qty'] * product_obj.weight
@@ -1117,7 +1110,7 @@ class sale_order_line(osv.osv):
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
lang=False, update_tax=True, date_order=False):
res = self.product_id_change(cursor, user, ids, pricelist, product,
- qty=0, uom=uom, qty_uos=qty_uos, uos=uos, name=name,
+ qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name,
partner_id=partner_id, lang=lang, update_tax=update_tax,
date_order=date_order)
if 'product_uom' in res['value']:
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 894ff6b2e6c..5add715a0cc 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -97,20 +97,20 @@
@@ -279,6 +277,7 @@
sale.order
form
tree,form,calendar,graph
+ {"search_default_user_id":uid}
@@ -366,11 +365,11 @@
-
-
+
+
-
+
@@ -417,16 +416,16 @@
-
-
-
-
+
+
+
+
-
+
@@ -445,14 +444,14 @@
domain="[('state','=','done')]"
name="unshipped"
separator="1" />
-
-
-
-
-
+
+
+
+
diff --git a/addons/sale/stock.py b/addons/sale/stock.py
index e2f632bf711..48c00d8afba 100644
--- a/addons/sale/stock.py
+++ b/addons/sale/stock.py
@@ -63,11 +63,8 @@ class stock_picking(osv.osv):
user, picking)
def _get_comment_invoice(self, cursor, user, picking):
- if picking.sale_id and picking.sale_id.note:
- if picking.note:
- return picking.note + '\n' + picking.sale_id.note
- else:
- return picking.sale_id.note
+ if picking.note or (picking.sale_id and picking.sale_id.note):
+ return picking.note or picking.sale_id.note
return super(stock_picking, self)._get_comment_invoice(cursor, user,
picking)
@@ -139,6 +136,10 @@ class stock_picking(osv.osv):
sale_lines = picking.sale_id.order_line
invoice_created = invoices[result[picking.id]]
+ for inv in invoice_obj.browse(cursor, user, [invoice_created.id], context=context):
+ if not inv.fiscal_position:
+ invoice_obj.write(cursor, user, [inv.id], {'fiscal_position': picking.sale_id.fiscal_position.id}, context=context)
+
if picking.sale_id.client_order_ref:
inv_name = picking.sale_id.client_order_ref + " : " + invoice_created.name
invoice_obj.write(cursor, user, [invoice_created.id], {'name': inv_name}, context=context)
@@ -188,6 +189,19 @@ class stock_picking(osv.osv):
})
return result
+
+ def action_cancel(self, cr, uid, ids, context={}):
+ res = super(stock_picking, self).action_cancel(cr, uid, ids, context=context)
+ for pick in self.browse(cr, uid, ids, context):
+ call_ship_end = True
+ if pick.sale_id:
+ for picks in pick.sale_id.picking_ids:
+ if picks.state not in ('done','cancel'):
+ call_ship_end = False
+ break
+ if call_ship_end:
+ self.pool.get('sale.order').action_ship_end(cr, uid, [pick.sale_id.id], context)
+ return res
stock_picking()
diff --git a/addons/sale/test/advance_invoice.yml b/addons/sale/test/advance_invoice.yml
new file mode 100644
index 00000000000..870b3ec0428
--- /dev/null
+++ b/addons/sale/test/advance_invoice.yml
@@ -0,0 +1,301 @@
+-
+ In order to test the sale module in the Open-ERP, I need to configure details regarding product & customer.
+-
+ I am going to sell my Mobile products to the customer with name Cleartrail
+-
+ I create View Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_view0}:
+ close_method: none
+ code: View
+ name: View
+ sign: 1
+-
+ I create Income Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_income0}:
+ close_method: unreconciled
+ code: Income
+ name: Income
+ sign: 1
+-
+ I create Expense Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_expense0}:
+ close_method: unreconciled
+ code: Expense
+ name: Expense
+ sign: 1
+-
+ I create Cash Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_cash0}:
+ close_method: balance
+ code: Cash
+ name: Cash
+ sign: 1
+-
+ I create Minimal Chart Account.
+-
+ !record {model: account.account, id: account_account_minimalchart0}:
+ code: '0'
+ company_id: base.main_company
+ currency_mode: current
+ name: Minimal Chart
+ parent_left: 1
+ parent_right: 12
+ type: view
+ user_type: account_account_type_view0
+-
+ I create Payable Account.
+-
+ !record {model: account.account, id: account_account_payable1}:
+ code: AP
+ company_id: base.main_company
+ currency_mode: current
+ name: Payable
+ parent_id: account_account_minimalchart0
+ parent_left: 2
+ parent_right: 3
+ reconcile: true
+ type: payable
+ user_type: account_account_type_expense0
+-
+ I create Receivable Account.
+-
+ !record {model: account.account, id: account_account_receivable0}:
+ code: AR
+ company_id: base.main_company
+ currency_mode: current
+ name: Receivable
+ parent_id: account_account_minimalchart0
+ parent_left: 4
+ parent_right: 5
+ reconcile: true
+ type: receivable
+ user_type: account_account_type_income0
+-
+ I create Cash Account.
+-
+ !record {model: account.account, id: account_account_cash0}:
+ code: C
+ company_id: base.main_company
+ currency_mode: current
+ name: Cash
+ parent_id: account_account_minimalchart0
+ parent_left: 6
+ parent_right: 7
+ type: other
+ user_type: account_account_type_cash0
+-
+ I create Purchases Account.
+-
+ !record {model: account.account, id: account_account_purchases0}:
+ code: P
+ company_id: base.main_company
+ currency_mode: current
+ name: Purchases
+ parent_id: account_account_minimalchart0
+ parent_left: 8
+ parent_right: 9
+ type: other
+ user_type: account_account_type_expense0
+-
+ I create Sales Account.
+-
+ !record {model: account.account, id: account_account_sales0}:
+ code: S
+ company_id: base.main_company
+ currency_mode: current
+ name: Sales
+ parent_id: account_account_minimalchart0
+ parent_left: 10
+ parent_right: 11
+ type: other
+ user_type: account_account_type_income0
+-
+ I create Purchase Journal.
+-
+ !record {model: account.journal, id: account_journal_purchasejournal0}:
+ code: PUJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_purchases0
+ default_debit_account_id: account_account_purchases0
+ name: Purchase Journal
+ sequence_id: account.sequence_purchase_journal
+ type: purchase
+ view_id: account.account_journal_view
+-
+ I create Sale Journal.
+-
+ !record {model: account.journal, id: account_journal_salejournal0}:
+ code: SAJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_sales0
+ default_debit_account_id: account_account_sales0
+ name: Sale Journal
+ sequence_id: account.sequence_sale_journal
+ type: sale
+ view_id: account.account_journal_view
+-
+ I create Bank Journal.
+-
+ !record {model: account.journal, id: account_journal_bankjournal0}:
+ code: BNK
+ company_id: base.main_company
+ default_credit_account_id: account_account_cash0
+ default_debit_account_id: account_account_cash0
+ name: Bank Journal
+ sequence_id: account.sequence_journal
+ type: cash
+ view_id: account.account_journal_bank_view
+-
+ I create ir.property for account payable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_payable
+ name: property_account_expense_categ
+ value_reference: account.account,5
+-
+ I create ir.property for account receivable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_receivable
+ name: property_account_income_categ
+ value_reference: account.account,6
+-
+ I create Partner category Customers.
+-
+ !record {model: res.partner.category, id: res_partner_category_customers0}:
+ name: Customers
+-
+ I create Cleartrail Customer.
+-
+ !record {model: res.partner, id: res_partner_cleartrail0}:
+ category_id:
+ - res_partner_category_customers0
+ name: Cleartrail
+-
+ I create contact address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_1}:
+ partner_id: res_partner_cleartrail0
+ street: onam plaza, 14 B palasia A B Road
+ type: contact
+-
+ I create invoice address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_2}:
+ partner_id: res_partner_cleartrail0
+ street: sarda house 24 B palasia, A B Road
+ type: invoice
+-
+ I create delivery address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_3}:
+ partner_id: res_partner_cleartrail0
+ street: sangam house 15 B palasia, A B Road
+ type: delivery
+-
+ Customer Cleartrail has specific instrument requirement regarding the stockable products.
+-
+ I define product category Mobile Products Sellable.
+-
+ !record {model: product.category, id: product_category_allproductssellable0}:
+ name: Mobile Products Sellable
+
+
+-
+ I define product category Mobile Services.
+-
+ !record {model: product.category, id: product_category_services0}:
+ name: Mobile Services
+-
+ I define LG Viewty Smart product template.
+-
+ !record {model: product.template, id: product_template_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ procure_method: make_to_order
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+
+-
+ I define LG Viewty Smart product.
+-
+ !record {model: product.product, id: product_product_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 160.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 170.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I create a Sale Order for LG Viewty Smart for qty 500 having order_policy prepaid.
+-
+ !record {model: sale.order, id: sale_order_so0}:
+ date_order: '2010-05-03'
+ invoice_quantity: order
+ name: SO004
+ order_line:
+ - name: LG Viewty Smart
+ price_unit: 170.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_lgviewtysmart0
+ product_uos_qty: 500.0
+ th_weight: 0.0
+ type: make_to_order
+ order_policy: prepaid
+ partner_id: sale.res_partner_cleartrail0
+ partner_invoice_id: sale.res_partner_address_2
+ partner_order_id: sale.res_partner_address_1
+ partner_shipping_id: sale.res_partner_address_3
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+
+-
+ I use the Advance Payment wizard.
+-
+ !record {model: sale.advance.payment.inv, id: sale_advance_payment_inv_0}:
+ amount: 1000.0
+ product_id: product.product_product_pc3
+ qtty: 3.0
+
+
+-
+ Performing an osv_memory action create_invoices on module sale.advance.payment.inv
+-
+ !python {model: sale.advance.payment.inv}: |
+ self.create_invoices(cr, uid, [ref("sale_advance_payment_inv_0")], {"lang": 'en_US',
+ "active_model": 'sale.order', "active_ids": [ref("sale_order_so0")], "tz":
+ False, "active_id": ref("sale_order_so0"), })
+-
+ I will verify whether the invoice has been generated.
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so0"))
+ assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
+
+
diff --git a/addons/sale/test/prepaid_sale_order.yml b/addons/sale/test/prepaid_sale_order.yml
new file mode 100644
index 00000000000..cd33b1bc73e
--- /dev/null
+++ b/addons/sale/test/prepaid_sale_order.yml
@@ -0,0 +1,379 @@
+-
+ In order to test the sale module in the Open-ERP, I need to configure details regarding product & customer.
+-
+ I am going to sell my Mobile products to the customer with name Cleartrail
+-
+ I create View Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_view0}:
+ close_method: none
+ code: View
+ name: View
+ sign: 1
+-
+ I create Income Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_income0}:
+ close_method: unreconciled
+ code: Income
+ name: Income
+ sign: 1
+-
+ I create Expense Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_expense0}:
+ close_method: unreconciled
+ code: Expense
+ name: Expense
+ sign: 1
+-
+ I create Cash Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_cash0}:
+ close_method: balance
+ code: Cash
+ name: Cash
+ sign: 1
+-
+ I create Minimal Chart Account.
+-
+ !record {model: account.account, id: account_account_minimalchart0}:
+ code: '0'
+ company_id: base.main_company
+ currency_mode: current
+ name: Minimal Chart
+ parent_left: 1
+ parent_right: 12
+ type: view
+ user_type: account_account_type_view0
+-
+ I create Payable Account.
+-
+ !record {model: account.account, id: account_account_payable1}:
+ code: AP
+ company_id: base.main_company
+ currency_mode: current
+ name: Payable
+ parent_id: account_account_minimalchart0
+ parent_left: 2
+ parent_right: 3
+ reconcile: true
+ type: payable
+ user_type: account_account_type_expense0
+-
+ I create Receivable Account.
+-
+ !record {model: account.account, id: account_account_receivable0}:
+ code: AR
+ company_id: base.main_company
+ currency_mode: current
+ name: Receivable
+ parent_id: account_account_minimalchart0
+ parent_left: 4
+ parent_right: 5
+ reconcile: true
+ type: receivable
+ user_type: account_account_type_income0
+-
+ I create Cash Account.
+-
+ !record {model: account.account, id: account_account_cash0}:
+ code: C
+ company_id: base.main_company
+ currency_mode: current
+ name: Cash
+ parent_id: account_account_minimalchart0
+ parent_left: 6
+ parent_right: 7
+ type: other
+ user_type: account_account_type_cash0
+-
+ I create Purchases Account.
+-
+ !record {model: account.account, id: account_account_purchases0}:
+ code: P
+ company_id: base.main_company
+ currency_mode: current
+ name: Purchases
+ parent_id: account_account_minimalchart0
+ parent_left: 8
+ parent_right: 9
+ type: other
+ user_type: account_account_type_expense0
+-
+ I create Sales Account.
+-
+ !record {model: account.account, id: account_account_sales0}:
+ code: S
+ company_id: base.main_company
+ currency_mode: current
+ name: Sales
+ parent_id: account_account_minimalchart0
+ parent_left: 10
+ parent_right: 11
+ type: other
+ user_type: account_account_type_income0
+-
+ I create Purchase Journal.
+-
+ !record {model: account.journal, id: account_journal_purchasejournal0}:
+ code: PUJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_purchases0
+ default_debit_account_id: account_account_purchases0
+ name: Purchase Journal
+ sequence_id: account.sequence_purchase_journal
+ type: purchase
+ view_id: account.account_journal_view
+-
+ I create Sale Journal.
+-
+ !record {model: account.journal, id: account_journal_salejournal0}:
+ code: SAJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_sales0
+ default_debit_account_id: account_account_sales0
+ name: Sale Journal
+ sequence_id: account.sequence_sale_journal
+ type: sale
+ view_id: account.account_journal_view
+-
+ I create Bank Journal.
+-
+ !record {model: account.journal, id: account_journal_bankjournal0}:
+ code: BNK
+ company_id: base.main_company
+ default_credit_account_id: account_account_cash0
+ default_debit_account_id: account_account_cash0
+ name: Bank Journal
+ sequence_id: account.sequence_journal
+ type: cash
+ view_id: account.account_journal_bank_view
+-
+ I create ir.property for account payable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_payable
+ name: property_account_expense_categ
+ value_reference: account.account,5
+-
+ I create ir.property for account receivable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_receivable
+ name: property_account_income_categ
+ value_reference: account.account,6
+-
+ I create Partner category Customers.
+-
+ !record {model: res.partner.category, id: res_partner_category_customers0}:
+ name: Customers
+-
+ I create Cleartrail Customer.
+-
+ !record {model: res.partner, id: res_partner_cleartrail0}:
+ category_id:
+ - res_partner_category_customers0
+ name: Cleartrail
+-
+ I create contact address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_1}:
+ partner_id: res_partner_cleartrail0
+ street: onam plaza, 14 B palasia A B Road
+ type: contact
+-
+ I create invoice address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_2}:
+ partner_id: res_partner_cleartrail0
+ street: sarda house 24 B palasia, A B Road
+ type: invoice
+-
+ I create delivery address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_3}:
+ partner_id: res_partner_cleartrail0
+ street: sangam house 15 B palasia, A B Road
+ type: delivery
+-
+ Customer Cleartrail has specific instrument requirement regarding the stockable products.
+-
+ I define product category Mobile Products Sellable.
+-
+ !record {model: product.category, id: product_category_allproductssellable0}:
+ name: Mobile Products Sellable
+
+
+-
+ I define product category Mobile Services.
+-
+ !record {model: product.category, id: product_category_services0}:
+ name: Mobile Services
+-
+ I define LG Viewty Smart product template.
+-
+ !record {model: product.template, id: product_template_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ procure_method: make_to_order
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define LG Viewty Smart product.
+-
+ !record {model: product.product, id: product_product_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 160.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 170.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I create a Sale Order for LG Viewty Smart for qty 500 having order_policy prepaid.
+-
+ !record {model: sale.order, id: sale_order_so1}:
+ date_order: '2010-05-03'
+ invoice_quantity: order
+ name: Test_SO001
+ order_line:
+ - name: LG Viewty Smart
+ price_unit: 170.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_lgviewtysmart0
+ product_uos_qty: 500.0
+ th_weight: 0.0
+ type: make_to_order
+ order_policy: prepaid
+ partner_id: sale.res_partner_cleartrail0
+ partner_invoice_id: sale.res_partner_address_2
+ partner_order_id: sale.res_partner_address_1
+ partner_shipping_id: sale.res_partner_address_3
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+
+
+-
+ I confirm the sale order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so1}
+-
+ I will verify whether the invoice has been generated for SO since Shipping policy is 'Payment Before Delivery'
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so1"))
+ assert so.invoice_ids, "Invoices has not been generated for sale_order_so1"
+-
+ I open the Invoice for the SO.
+-
+ !python {model: account.invoice}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
+ import netsvc
+ wf_service = netsvc.LocalService("workflow")
+ invoice_ids = so.invoice_ids
+ for invoice in invoice_ids:
+ wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
+-
+ Creating a account invoice pay entry.
+-
+ !record {model: account.invoice.pay, id: account_invoice_pay_tst1}:
+ amount: 85000.0
+ date: '2010-05-10'
+ journal_id: sale.account_journal_bankjournal0
+ name: tst
+ period_id: account.period_5
+-
+ I pay the invoice.
+-
+ !python {model: account.invoice.pay}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
+ self.wo_check(cr, uid, [ref("account_invoice_pay_tst1")], {"lang": "en_US", "tz":
+ False, "active_model": 'account.invoice', "active_ids": [so.invoice_ids[0].id], "type":
+ "out_invoice", "active_id": so.invoice_ids[0].id, })
+
+
+-
+ Creating an account invoice pay writeoff entry.
+-
+ !record {model: account.invoice.pay.writeoff, id: account_invoice_pay_writeoff_0}:
+ analytic_id: account.analytic_customers
+ comment: Write-Off
+ writeoff_acc_id: account.a_sale
+ writeoff_journal_id: sale.account_journal_bankjournal0
+
+
+-
+ Pay and Reconcile the Invoice.
+-
+ !python {model: account.invoice.pay.writeoff}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
+ self.pay_and_reconcile_writeoff(cr, uid, [ref("account_invoice_pay_writeoff_0")],
+ {"lang": 'en_US', "tz": False, "active_model": 'account.invoice', "active_ids":
+ [so.invoice_ids[0].id], "type": "out_invoice", "active_id": so.invoice_ids[0].id })
+
+
+-
+ I will verify the picking associated with the sale order sale_order_so1
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so1"))
+ assert so.picking_ids,"Picking has not been generated for sale_order_so1"
+-
+ Products are delivered to the Cleartrail Customer.
+-
+ !python {model: stock.picking }: |
+ import time
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
+ picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
+ if picking_id:
+ pick=self.browse(cr,uid,picking_id[0])
+ pick.force_assign(cr, uid)
+ partial_datas = {
+ 'partner_id':pick.address_id.partner_id.id,
+ 'address_id': pick.address_id.id,
+ 'delivery_date' : time.strftime('%Y-%m-%d'),
+ }
+ move = pick.move_lines[0]
+ partial_datas['move%s'%(move.id)]= {
+ 'product_id': move.product_id.id,
+ 'product_qty': move.product_qty,
+ 'product_uom': move.product_uom.id,
+ }
+ self.do_partial(cr, uid, [pick.id],partial_datas)
+-
+ I verify that picking order is in done state.
+-
+ !python {model: stock.picking }: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
+ picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
+
+ if picking_id:
+ pick = self.browse(cr,uid,picking_id[0])
+ assert (pick.state) =='done', "Picking for SO is not in done state."
diff --git a/addons/sale/test/sale_procurement.yml b/addons/sale/test/sale_procurement.yml
new file mode 100644
index 00000000000..c9d26baec9f
--- /dev/null
+++ b/addons/sale/test/sale_procurement.yml
@@ -0,0 +1,91 @@
+-
+ In order to test the sale order working with procurements I will create some
+ products with different supply method and procurement method.
+-
+ I create two products.
+-
+ !record {model: product.product, id: product_product_table0}:
+ categ_id: product.cat1
+ name: Table
+ procure_method: make_to_order
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ !record {model: product.product, id: product_product_wood0}:
+ categ_id: product.cat1
+ name: Wood
+ procure_method: make_to_stock
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_kgm
+ uom_po_id: product.product_uom_kgm
+-
+ I define Minimum stock rule for my stockable product wood
+-
+ !record {model: stock.warehouse.orderpoint, id: stock_warehouse_orderpoint_op0}:
+ company_id: base.main_company
+ location_id: stock.stock_location_stock
+ logic: max
+ product_id: product_product_wood0
+ product_max_qty: 15.0
+ product_min_qty: 10.0
+ product_uom: product.product_uom_kgm
+ qty_multiple: 1
+ warehouse_id: stock.warehouse0
+-
+ Now I make a sale order for table.
+-
+ !record {model: sale.order, id: sale_order_so3}:
+ amount_total: 5.0
+ amount_untaxed: 5.0
+ date_order: '2010-04-30'
+ invoice_quantity: order
+ order_line:
+ - company_id: base.main_company
+ delay: 7.0
+ name: Table
+ price_unit: 1.0
+ product_id: product_product_table0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 5.0
+ product_uos_qty: 5.0
+ state: draft
+ type: make_to_order
+ order_policy: manual
+ partner_id: base.res_partner_agrolait
+ partner_invoice_id: base.res_partner_address_8
+ partner_order_id: base.res_partner_address_8
+ partner_shipping_id: base.res_partner_address_8
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+-
+ I confirm the order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so3}
+-
+ I check that one procurement is generated.
+-
+ !python {model: mrp.procurement}: |
+ from tools.translate import _
+ proc_ids = self.search(cr, uid, [('state','=','confirmed')])
+ assert proc_ids, _('No Procurements!')
+-
+ The scheduler runs.
+-
+ !function {model: mrp.procurement, name: run_scheduler}:
+ - model: mrp.procurement
+ search: "[('state','=','confirmed')]"
+-
+ I check that the procurement for the product table is in exception state.
+ As my product's supply method is produce and mrp module is yet not installed.
+-
+ !python {model: mrp.procurement}: |
+ from tools.translate import _
+ proc_ids = self.search(cr, uid, [('state','=','exception')])
+ assert proc_ids, _('No Procurements are in exception state!')
+
+
+
\ No newline at end of file
diff --git a/addons/sale/test/shipping_manual_sale_order.yml b/addons/sale/test/shipping_manual_sale_order.yml
new file mode 100644
index 00000000000..4bbbbb74dc5
--- /dev/null
+++ b/addons/sale/test/shipping_manual_sale_order.yml
@@ -0,0 +1,384 @@
+-
+ In order to test the sale module in the Open-ERP, I need to configure details regarding product & customer.
+-
+ I am going to sell my Mobile products to the customer with name Cleartrail
+-
+ I create View Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_view0}:
+ close_method: none
+ code: View
+ name: View
+ sign: 1
+-
+ I create Income Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_income0}:
+ close_method: unreconciled
+ code: Income
+ name: Income
+ sign: 1
+-
+ I create Expense Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_expense0}:
+ close_method: unreconciled
+ code: Expense
+ name: Expense
+ sign: 1
+-
+ I create Cash Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_cash0}:
+ close_method: balance
+ code: Cash
+ name: Cash
+ sign: 1
+-
+ I create Minimal Chart Account.
+-
+ !record {model: account.account, id: account_account_minimalchart0}:
+ code: '0'
+ company_id: base.main_company
+ currency_mode: current
+ name: Minimal Chart
+ parent_left: 1
+ parent_right: 12
+ type: view
+ user_type: account_account_type_view0
+-
+ I create Payable Account.
+-
+ !record {model: account.account, id: account_account_payable1}:
+ code: AP
+ company_id: base.main_company
+ currency_mode: current
+ name: Payable
+ parent_id: account_account_minimalchart0
+ parent_left: 2
+ parent_right: 3
+ reconcile: true
+ type: payable
+ user_type: account_account_type_expense0
+-
+ I create Receivable Account.
+-
+ !record {model: account.account, id: account_account_receivable0}:
+ code: AR
+ company_id: base.main_company
+ currency_mode: current
+ name: Receivable
+ parent_id: account_account_minimalchart0
+ parent_left: 4
+ parent_right: 5
+ reconcile: true
+ type: receivable
+ user_type: account_account_type_income0
+-
+ I create Cash Account.
+-
+ !record {model: account.account, id: account_account_cash0}:
+ code: C
+ company_id: base.main_company
+ currency_mode: current
+ name: Cash
+ parent_id: account_account_minimalchart0
+ parent_left: 6
+ parent_right: 7
+ type: other
+ user_type: account_account_type_cash0
+-
+ I create Purchases Account.
+-
+ !record {model: account.account, id: account_account_purchases0}:
+ code: P
+ company_id: base.main_company
+ currency_mode: current
+ name: Purchases
+ parent_id: account_account_minimalchart0
+ parent_left: 8
+ parent_right: 9
+ type: other
+ user_type: account_account_type_expense0
+-
+ I create Sales Account.
+-
+ !record {model: account.account, id: account_account_sales0}:
+ code: S
+ company_id: base.main_company
+ currency_mode: current
+ name: Sales
+ parent_id: account_account_minimalchart0
+ parent_left: 10
+ parent_right: 11
+ type: other
+ user_type: account_account_type_income0
+-
+ I create Purchase Journal.
+-
+ !record {model: account.journal, id: account_journal_purchasejournal0}:
+ code: PUJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_purchases0
+ default_debit_account_id: account_account_purchases0
+ name: Purchase Journal
+ sequence_id: account.sequence_purchase_journal
+ type: purchase
+ view_id: account.account_journal_view
+-
+ I create Sale Journal.
+-
+ !record {model: account.journal, id: account_journal_salejournal0}:
+ code: SAJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_sales0
+ default_debit_account_id: account_account_sales0
+ name: Sale Journal
+ sequence_id: account.sequence_sale_journal
+ type: sale
+ view_id: account.account_journal_view
+-
+ I create Bank Journal.
+-
+ !record {model: account.journal, id: account_journal_bankjournal0}:
+ code: BNK
+ company_id: base.main_company
+ default_credit_account_id: account_account_cash0
+ default_debit_account_id: account_account_cash0
+ name: Bank Journal
+ sequence_id: account.sequence_journal
+ type: cash
+ view_id: account.account_journal_bank_view
+-
+ I create ir.property for account payable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_payable
+ name: property_account_expense_categ
+ value_reference: account.account,5
+-
+ I create ir.property for account receivable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_receivable
+ name: property_account_income_categ
+ value_reference: account.account,6
+-
+ I create Partner category Customers.
+-
+ !record {model: res.partner.category, id: res_partner_category_customers0}:
+ name: Customers
+-
+ I create Cleartrail Customer.
+-
+ !record {model: res.partner, id: res_partner_cleartrail0}:
+ category_id:
+ - res_partner_category_customers0
+ name: Cleartrail
+-
+ I create contact address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_1}:
+ partner_id: res_partner_cleartrail0
+ street: onam plaza, 14 B palasia A B Road
+ type: contact
+-
+ I create invoice address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_2}:
+ partner_id: res_partner_cleartrail0
+ street: sarda house 24 B palasia, A B Road
+ type: invoice
+-
+ I create delivery address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_3}:
+ partner_id: res_partner_cleartrail0
+ street: sangam house 15 B palasia, A B Road
+ type: delivery
+-
+ Customer Cleartrail has specific instrument requirement regarding the stockable products.
+-
+ I define product category Mobile Products Sellable.
+-
+ !record {model: product.category, id: product_category_allproductssellable0}:
+ name: Mobile Products Sellable
+-
+ I define product category Mobile Services.
+-
+ !record {model: product.category, id: product_category_services0}:
+ name: Mobile Services
+-
+ I define LG Viewty Smart product template.
+-
+ !record {model: product.template, id: product_template_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ procure_method: make_to_order
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define LG Viewty Smart product.
+-
+ !record {model: product.product, id: product_product_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 189.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 200.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I create a Sale Order for LG Viewty Smart for qty 500 having order_policy manual.
+-
+ !record {model: sale.order, id: sale_order_so0}:
+ date_order: '2010-05-12'
+ invoice_quantity: order
+ name: Test_SO002
+ order_line:
+ - name: New Chocolate Slider Mobile
+ price_unit: 200.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_newchocolateslidermobile0
+ product_uos_qty: 500.0
+ type: make_to_order
+ order_policy: manual
+ partner_id: sale.res_partner_cleartrail0
+ partner_invoice_id: sale.res_partner_address_2
+ partner_order_id: sale.res_partner_address_1
+ partner_shipping_id: sale.res_partner_address_3
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+-
+ I confirm the Sale Order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so0}
+-
+ I click on Create Invoice button to create the invoice.
+-
+ !workflow {model: sale.order, action: manual_invoice, ref: sale_order_so0}
+-
+ I verify whether the invoice has been generated for SO
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so0"))
+ assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
+-
+ I open the Invoice for the SO.
+-
+ !python {model: account.invoice}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ import netsvc
+ wf_service = netsvc.LocalService("workflow")
+ invoice_ids = so.invoice_ids
+ for invoice in invoice_ids:
+ wf_service.trg_validate(uid, 'account.invoice',invoice.id,'invoice_open', cr)
+-
+ Creating a account invoice pay entry.
+-
+ !record {model: account.invoice.pay, id: account_invoice_pay_tst0}:
+ amount: 100000.0
+ date: '2010-05-10'
+ journal_id: sale.account_journal_bankjournal0
+ name: test
+ period_id: account.period_5
+-
+ I pay the invoice.
+-
+ !python {model: account.invoice.pay}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ self.wo_check(cr, uid, [ref("account_invoice_pay_tst0")], {"lang": "en_US", "tz":
+ False, "active_model": 'account.invoice', "active_ids": [so.invoice_ids[0].id], "type":
+ "out_invoice", "active_id": so.invoice_ids[0].id})
+
+
+-
+ Creating an account invoice pay writeoff entry.
+-
+ !record {model: account.invoice.pay.writeoff, id: account_invoice_pay_writeoff_0}:
+ analytic_id: account.analytic_customers
+ comment: Write-Off
+ writeoff_acc_id: account.a_sale
+ writeoff_journal_id: sale.account_journal_bankjournal0
+
+
+-
+ Pay and Reconcile the Invoice.
+-
+ !python {model: account.invoice.pay.writeoff}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ self.pay_and_reconcile_writeoff(cr, uid, [ref("account_invoice_pay_writeoff_0")],
+ {"lang": 'en_US', "tz": False, "active_model": 'account.invoice', "active_ids":
+ [so.invoice_ids[0].id], "type": "out_invoice", "active_id": so.invoice_ids[0].id, })
+-
+ I verify the invoice are in paid state or not.
+-
+ !python {model: account.invoice}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ invoice_ids = so.invoice_ids
+ for invoice in invoice_ids:
+ assert (invoice.state) =='paid', "Invoice for SO is not in done state."
+-
+ I verify the picking associated with the sale order sale_order_so0.
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so0"))
+ assert so.picking_ids,"Picking has not been generated for sale_order_so0"
+-
+ Products are delivered to the Cleartrail Customer.
+-
+ !python {model: stock.picking }: |
+ import time
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
+ if picking_id:
+ pick=self.browse(cr,uid,picking_id[0])
+ pick.force_assign(cr, uid)
+ partial_datas = {
+ 'partner_id':pick.address_id.partner_id.id,
+ 'address_id': pick.address_id.id,
+ 'delivery_date' : time.strftime('%Y-%m-%d'),
+ }
+ move = pick.move_lines[0]
+ partial_datas['move%s'%(move.id)]= {
+ 'product_id': move.product_id.id,
+ 'product_qty': move.product_qty,
+ 'product_uom': move.product_uom.id,
+ }
+ self.do_partial(cr, uid, [pick.id],partial_datas)
+-
+ I verify that picking order is in done state.
+-
+ !python {model: stock.picking }: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
+ if picking_id:
+ pick = self.browse(cr,uid,picking_id[0])
+ assert (pick.state) =='done', "Picking for SO is not in done state."
diff --git a/addons/sale/wizard/__init__.py b/addons/sale/wizard/__init__.py
index 07c5ceea83d..ba6fd677a3c 100644
--- a/addons/sale/wizard/__init__.py
+++ b/addons/sale/wizard/__init__.py
@@ -19,8 +19,9 @@
#
##############################################################################
-#remaining make_invoice
+import sale_make_invoice
import sale_line_invoice
import sale_make_invoice_advance
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/wizard/make_invoice.py b/addons/sale/wizard/make_invoice.py
deleted file mode 100644
index 7b190c3b2d6..00000000000
--- a/addons/sale/wizard/make_invoice.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#
-##############################################################################
-
-import wizard
-import netsvc
-import pooler
-
-invoice_form = """
-
-"""
-
-invoice_fields = {
- 'grouped' : {'string':'Group the invoices', 'type':'boolean', 'default': lambda x,y,z: False},
- 'invoice_date': {'string': 'Invoiced date', 'type':'date' }
-}
-
-ack_form = """
-"""
-
-ack_fields = {}
-
-def _makeInvoices(self, cr, uid, data, context):
- pool_obj = pooler.get_pool(cr.dbname)
- mod_obj = pool_obj.get('ir.model.data')
- order_obj = pool_obj.get('sale.order')
- newinv = []
-
- order_obj.action_invoice_create(cr, uid, data['ids'], data['form']['grouped'], date_inv = data['form']['invoice_date'])
- for id in data['ids']:
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
-
- for o in order_obj.browse(cr, uid, data['ids'], context):
- for i in o.invoice_ids:
- newinv.append(i.id)
- act_obj = pool_obj.get('ir.actions.act_window')
- xml_id='action_invoice_tree5'
- result = mod_obj._get_id(cr, uid, 'account', xml_id)
- id = mod_obj.read(cr, uid, result, ['res_id'])['res_id']
- result = act_obj.read(cr, uid, id)
- result['domain'] ="[('id','in', ["+','.join(map(str,newinv))+"])]"
- return result
- #return {
- # 'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
- # 'name': 'Invoices',
- # 'view_type': 'form',
- # 'view_mode': 'tree,form',
- # 'res_model': 'account.invoice',
- # 'view_id': False,
- # 'context': "{'type':'out_refund'}",
- # 'type': 'ir.actions.act_window'
- #}
- #return {}
-
-class make_invoice(wizard.interface):
- states = {
- 'init' : {
- 'actions' : [],
- 'result' : {'type' : 'form',
- 'arch' : invoice_form,
- 'fields' : invoice_fields,
- 'state' : [('end', 'Cancel'),('invoice', 'Create invoices') ]}
- },
- 'invoice' : {
- 'actions' : [_makeInvoices],
- 'result' : {'type': 'state', 'state': 'end'}
- },
- }
-make_invoice("sale.order.make_invoice")
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py
index 4bf3074db54..15405f07874 100644
--- a/addons/sale/wizard/sale_line_invoice.py
+++ b/addons/sale/wizard/sale_line_invoice.py
@@ -20,22 +20,11 @@
##############################################################################
from osv import fields, osv
-from service import web_services
-import wizard
-import netsvc
-import ir
-import pooler
+from tools.translate import _
class sale_order_line_make_invoice(osv.osv_memory):
_name = "sale.order.line.make.invoice"
_description = "Sale OrderLine Make_invoice"
- _columns = {
- 'grouped': fields.boolean('Group the invoices'),
- }
- _default = {
- 'grouped' : lambda *a: False
- }
-
def make_invoices(self, cr, uid, ids, context):
"""
To make invoices.
@@ -82,7 +71,7 @@ class sale_order_line_make_invoice(osv.osv_memory):
'currency_id' : order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': pay_term,
- 'fiscal_position': order.partner_id.property_account_position.id
+ 'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,
}
inv_id = self.pool.get('account.invoice').create(cr, uid, inv)
return inv_id
@@ -110,6 +99,8 @@ class sale_order_line_make_invoice(osv.osv_memory):
wf_service.trg_validate(uid, 'sale.order', line.order_id.id, 'all_lines', cr)
sales_order_obj.write(cr,uid,[line.order_id.id],{'state' : 'progress'})
+ if not invoices:
+ raise osv.except_osv(_('Warning'),_('Invoice cannot be created for this Sale Order Line due to one of the following reasons:\n1.The state of this sale order line is either "draft" or "cancel"!\n2.The Sale Order Line is Invoiced!'))
for result in invoices.values():
order = result[0][0].order_id
il = map(lambda x: x[1], result)
diff --git a/addons/sale/wizard/sale_line_invoice.xml b/addons/sale/wizard/sale_line_invoice.xml
index 90bdf2a6828..436fabc91fc 100644
--- a/addons/sale/wizard/sale_line_invoice.xml
+++ b/addons/sale/wizard/sale_line_invoice.xml
@@ -8,8 +8,6 @@
diff --git a/addons/sale/wizard/sale_make_invoice.py b/addons/sale/wizard/sale_make_invoice.py
new file mode 100644
index 00000000000..5ea01b1db6c
--- /dev/null
+++ b/addons/sale/wizard/sale_make_invoice.py
@@ -0,0 +1,74 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields, osv
+from service import web_services
+from tools.translate import _
+import ir
+import netsvc
+
+class sale_make_invoice(osv.osv_memory):
+ _name = "sale.make.invoice"
+ _description = "Sale Make Invoice"
+ _columns = {
+ 'grouped': fields.boolean('Group the invoices'),
+ 'invoice_date':fields.date('Invoice Date'),
+ }
+ _default = {
+ 'grouped' : lambda *a: False
+ }
+ def view_init(self, cr, uid, fields_list, context=None):
+ record_id = context and context.get('active_id', False)
+ order = self.pool.get('sale.order').browse(cr, uid, record_id)
+ if order.state=='draft':
+ raise osv.except_osv(_('Warning !'),'You can not create invoice when sale order is not confirmed.')
+ return False
+ def make_invoices(self, cr, uid, ids, context={}):
+ order_obj = self.pool.get('sale.order')
+ newinv = []
+ data=self.read(cr,uid,ids)[0]
+ order_obj.action_invoice_create(cr, uid, context.get(('active_ids'),[]), data['grouped'],date_inv = data['invoice_date'])
+ wf_service = netsvc.LocalService("workflow")
+ for id in context.get(('active_ids'),[]):
+ wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
+
+ for o in order_obj.browse(cr, uid, context.get(('active_ids'),[]), context):
+ for i in o.invoice_ids:
+ newinv.append(i.id)
+
+ mod_obj =self.pool.get('ir.model.data')
+ result = mod_obj._get_id(cr, uid, 'account', 'view_account_invoice_filter')
+
+ id = mod_obj.read(cr, uid, result, ['res_id'])
+ return {
+ 'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
+ 'name': 'Invoices',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'account.invoice',
+ 'view_id': False,
+ 'context': "{'type':'out_refund'}",
+ 'type': 'ir.actions.act_window',
+ 'search_view_id': id['id']
+ }
+
+sale_make_invoice()
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/sale/wizard/sale_make_invoice.xml b/addons/sale/wizard/sale_make_invoice.xml
new file mode 100644
index 00000000000..ade720be1f4
--- /dev/null
+++ b/addons/sale/wizard/sale_make_invoice.xml
@@ -0,0 +1,29 @@
+
+
+
+
+ Create invoices
+ sale.make.invoice
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index 6c9ca17b836..2861a046205 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -22,10 +22,6 @@ from osv import fields, osv
from service import web_services
from tools.translate import _
import ir
-import netsvc
-import pooler
-import wizard
-
class sale_advance_payment_inv(osv.osv_memory):
_name = "sale.advance.payment.inv"
@@ -95,7 +91,7 @@ class sale_advance_payment_inv(osv.osv_memory):
'currency_id' :sale.pricelist_id.currency_id.id,
'comment': '',
'payment_term':sale.payment_term.id,
- 'fiscal_position': sale.partner_id.property_account_position.id
+ 'fiscal_position': sale.fiscal_position.id or sale.partner_id.property_account_position.id
}
inv_id = inv_obj.create(cr, uid, inv)
diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py
index 613d8af7b7a..14c1a07e336 100644
--- a/addons/sale_crm/sale_crm.py
+++ b/addons/sale_crm/sale_crm.py
@@ -23,7 +23,6 @@ from osv import osv,fields
class sale_order(osv.osv):
_inherit = 'sale.order'
- _description = 'Sale orders'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml
index 7660dcc5cd2..7a8cd419718 100644
--- a/addons/sale_crm/sale_crm_view.xml
+++ b/addons/sale_crm/sale_crm_view.xml
@@ -22,7 +22,7 @@
-
+
@@ -34,7 +34,7 @@
-
+
[[line.product_id.code ]] [[ line.product_id and line.product_id.name or '']]
- [[ (line.prodlot_id and (line.prodlot_id.name + '/' + line.prodlot_id.ref)) or ' ' ]]
+ [[ (line.prodlot_id and (line.prodlot_id.name + (line.prodlot_id.ref and ('/' + line.prodlot_id.ref) or ''))) or ' ' ]]
[[ formatLang(line.product_qty) ]]
diff --git a/addons/sale_journal/picking_journal_view.xml b/addons/sale_journal/picking_journal_view.xml
index 7d2d657b7de..f6b59668150 100644
--- a/addons/sale_journal/picking_journal_view.xml
+++ b/addons/sale_journal/picking_journal_view.xml
@@ -10,12 +10,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -41,10 +41,10 @@
tree
-
-
-
-
+
+
+
+
@@ -57,13 +57,12 @@
-
-
-
-
-
+
+
+
+
@@ -73,6 +72,7 @@
sale_journal.picking.journal
form
tree,form
+ {"search_default_user_id":uid}
diff --git a/addons/sale_journal/picking_journal_view_report.xml b/addons/sale_journal/picking_journal_view_report.xml
index d2940fa3d2b..62c8d0a9ca1 100644
--- a/addons/sale_journal/picking_journal_view_report.xml
+++ b/addons/sale_journal/picking_journal_view_report.xml
@@ -11,11 +11,11 @@
form
@@ -91,10 +91,10 @@
form
diff --git a/addons/sale_journal/sale_journal.py b/addons/sale_journal/sale_journal.py
index c041a934274..8b636241285 100644
--- a/addons/sale_journal/sale_journal.py
+++ b/addons/sale_journal/sale_journal.py
@@ -25,7 +25,7 @@ import time
class sale_journal_invoice_type(osv.osv):
_name = 'sale_journal.invoice.type'
- _description = 'Invoice Types'
+ _description = 'Invoice Type'
_columns = {
'name': fields.char('Invoice Type', size=64, required=True),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the invoice type without removing it."),
diff --git a/addons/sale_journal/sale_journal_view.xml b/addons/sale_journal/sale_journal_view.xml
index 7783f646292..c1e415b8833 100644
--- a/addons/sale_journal/sale_journal_view.xml
+++ b/addons/sale_journal/sale_journal_view.xml
@@ -42,12 +42,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -83,10 +83,10 @@
tree
-
-
-
-
+
+
+
+
@@ -99,13 +99,12 @@
-
-
-
-
-
+
+
+
+
@@ -115,6 +114,7 @@
sale_journal.sale.journal
form
tree,form
+ {"search_default_user_id":uid}
@@ -285,9 +285,9 @@
form
diff --git a/addons/scrum/scrum_view.xml b/addons/scrum/scrum_view.xml
index 379dc66a4fd..394ea4c4219 100644
--- a/addons/scrum/scrum_view.xml
+++ b/addons/scrum/scrum_view.xml
@@ -44,11 +44,9 @@
-
+
-
-
@@ -149,13 +147,7 @@
domain="[('sprint_id','=',False)]"
help="Backlogs Not Assigned To Sprints."/>
-
-
-
+
@@ -173,6 +165,7 @@
Product Backlogs
scrum.product.backlog
form
+ {"search_default_user_id":uid}
-
+
-
-
-
+
@@ -298,7 +287,9 @@
scrum.sprint
form
tree,form
+ {'search_default_filter_current': 1}
+ {"search_default_scrum_master_id":uid}
\n"
+"PO-Revision-Date: 2010-05-20 06:22+0000\n"
+"Last-Translator: Olivier (Open ERP) \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 03:56+0000\n"
+"X-Launchpad-Export-Date: 2010-05-21 03:37+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: stock
@@ -677,7 +677,7 @@ msgstr "Date d'envoi prévue"
#. module: stock
#: rml:stock.picking.list:0
msgid "Shipping Address :"
-msgstr ""
+msgstr "Adresse de livraison"
#. module: stock
#: view:stock.tracking:0
@@ -1703,7 +1703,7 @@ msgstr "Magasin"
#: selection:stock.move,state:0
#: selection:stock.picking,state:0
msgid "Done"
-msgstr "Terminer"
+msgstr "Terminé"
#. module: stock
#: model:stock.location,name:stock.stock_location_locations_virtual
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 46f4ca6e8e2..02c60968e04 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -8,8 +8,8 @@
search
-
-
+
+
diff --git a/addons/stock/report/report_stock.py b/addons/stock/report/report_stock.py
index da1dd27ff14..3e7fe147c73 100644
--- a/addons/stock/report/report_stock.py
+++ b/addons/stock/report/report_stock.py
@@ -22,6 +22,7 @@
from osv import osv, fields
from tools.translate import _
import tools
+from tools.sql import drop_view_if_exists
#
# Check if it works with UoM ???
@@ -38,7 +39,7 @@ class stock_report_prodlots(osv.osv):
}
def init(self, cr):
- tools.drop_view_if_exists(cr, 'stock_report_prodlots')
+ drop_view_if_exists(cr, 'stock_report_prodlots')
cr.execute("""
create or replace view stock_report_prodlots as (
select max(id) as id,
@@ -94,7 +95,7 @@ class stock_report_tracklots(osv.osv):
}
def init(self, cr):
- tools.drop_view_if_exists(cr, 'stock_report_tracklots')
+ drop_view_if_exists(cr, 'stock_report_prodlots')
cr.execute("""
create or replace view stock_report_tracklots as (
@@ -149,7 +150,7 @@ class report_stock_lines_date(osv.osv):
'date': fields.datetime('Latest Inventory Date'),
}
def init(self, cr):
- tools.drop_view_if_exists(cr, 'report_stock_lines_date')
+ drop_view_if_exists(cr, 'stock_report_prodlots')
cr.execute("""
create or replace view report_stock_lines_date as (
select
diff --git a/addons/stock/report/report_stock_move.py b/addons/stock/report/report_stock_move.py
index b5388b336e6..8d905a4c4d7 100755
--- a/addons/stock/report/report_stock_move.py
+++ b/addons/stock/report/report_stock_move.py
@@ -28,35 +28,48 @@ class report_stock_move(osv.osv):
_description = "Stock Statistics"
_auto = False
_columns = {
- 'date': fields.date('Date', readonly=True),
+ 'date_planned': fields.date('Date', readonly=True),
'year': fields.char('Year', size=4, readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
+ 'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
- 'location_id':fields.many2one('stock.location', 'Location', readonly=True),
+ 'location_id': fields.many2one('stock.location', 'Source Location', readonly=True, select=True, help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
+ 'location_dest_id': fields.many2one('stock.location', 'Dest. Location', readonly=True, select=True, help="Location where the system will stock the finished products."),
'product_qty':fields.integer('Qty',readonly=True),
+ 'value' : fields.float('Total Value', required=True),
+ 'product_uom': fields.many2one('product.uom', 'Product UOM', readonly=True),
'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True,
help='When the stock move is created it is in the \'Draft\' state.\n After that it is set to \'Confirmed\' state.\n If stock is available state is set to \'Avaiable\'.\n When the picking it done the state is \'Done\'.\
\nThe state is \'Waiting\' if the move is waiting for another one.'),
-
+ 'day_diff':fields.integer('Expected Performance',readonly=True),
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_stock_move')
cr.execute("""
create or replace view report_stock_move as (
- select min(m.id) as id,
- m.date as date,
- to_char(date_trunc('day',m.date), 'YYYY') as year,
- to_char(date_trunc('day',m.date), 'MM') as month,
- to_char(date_trunc('day',m.date), 'YYYY-MM-DD') as day,
- m.location_id as location_id,
- m.product_id as product_id,
- m.state as state,
- sum(m.product_qty) as product_qty
- from stock_move as m group by m.product_id, m.location_id, m.id, m.date, m.state
- )
+ select min(m.id) as id,
+ m.date_planned as date_planned,
+ to_char(date_trunc('day',m.date_planned), 'YYYY') as year,
+ to_char(date_trunc('day',m.date_planned), 'MM') as month,
+ to_char(date_trunc('day',m.date_planned), 'YYYY-MM-DD') as day,
+ (date(m.date_planned)-date(m.date_expected)) as day_diff,
+ m.address_id as partner_id,
+ m.location_id as location_id,
+ m.location_dest_id as location_dest_id,
+ m.product_id as product_id,
+ m.state as state,
+ m.product_uom as product_uom,
+ sum(m.product_qty) as product_qty,
+ pt.standard_price * sum(m.product_qty) as value
+ from stock_move m ,product_product pp,product_template pt
+ where
+ m.product_id=pp.id and pp.product_tmpl_id=pt.id
+ group by
+ m.id, m.product_id,m.address_id, m.location_id, m.location_dest_id,
+ m.date_planned, m.state, m.product_uom,pt.standard_price,m.date_expected )
""")
report_stock_move()
diff --git a/addons/stock/report/report_stock_move_view.xml b/addons/stock/report/report_stock_move_view.xml
index 79657da0fc7..3a7b233504a 100755
--- a/addons/stock/report/report_stock_move_view.xml
+++ b/addons/stock/report/report_stock_move_view.xml
@@ -7,14 +7,20 @@
tree
-
+
+
+
+
+
-
+
+
+
@@ -43,13 +49,14 @@
domain="[('year','=',time.strftime('%%Y'))]"
help="Stock Moves of the year"/>
@@ -64,22 +71,35 @@
help = "Available Stock-Moves"/>
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
+
+
+
+
+
-
+
@@ -92,7 +112,7 @@
form
tree,graph
-
+ {'search_default_product':1, 'search_default_src_location':1,'search_default_done':1,'group_by':[]}
-
+
-
-
+
+
@@ -73,7 +73,7 @@
stock.report.prodlots
form
tree,form
- {'full':'1'}
+ {'full':'1','search_default_internal_locations':1}
@@ -155,8 +155,7 @@
search
-
@@ -164,8 +163,8 @@
-
-
+
+
@@ -187,6 +186,7 @@
Dates of Latest Inventories by Product
report.stock.lines.date
form
+ {'search_default_stockable':1}
tree,form
diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv
index 91941341ccf..ca36c8460a7 100644
--- a/addons/stock/security/ir.model.access.csv
+++ b/addons/stock/security/ir.model.access.csv
@@ -37,7 +37,6 @@
"access_stock_location_product","stock.location.product","model_stock_location_product","stock.group_stock_user",1,0,0,0
"access_report_stock_picking","report.stock.picking","model_report_stock_picking","stock.group_stock_user",1,0,0,0
"access_stock_delivery","stock.delivery","model_stock_delivery","stock.group_stock_user",1,0,0,0
-
"access_stock_traceability_upstream","stock.traceability.upstream","model_stock_traceability_upstream","stock.group_stock_user",1,0,0,0
"access_stock_traceability_downstream","stock.traceability.downstream","model_stock_traceability_downstream","stock.group_stock_user",1,0,0,0
"access_stock_traceability_lot_upstream","stock.traceability.lot.upstream","model_stock_traceability_lot_upstream","stock.group_stock_user",1,0,0,0
@@ -45,4 +44,5 @@
"access_stock_partial_picking",stock.partial.picking","model_stock_partial_picking","stock.group_stock_user",1,0,0,0
"access_stock_partial_move","stock.partial.move","model_stock_partial_move","stock.group_stock_user",1,0,0,0
"access_stock_inventory_merge","stock.inventory.merge","model_stock_inventory_merge","stock.group_stock_user",1,0,0,0
-"access_stock_change_standard_price","stock.change.standard.price","model_stock_change_standard_price","stock.group_stock_user",1,0,0,0
\ No newline at end of file
+"access_stock_change_standard_price","stock.change.standard.price","model_stock_change_standard_price","stock.group_stock_user",1,0,0,0
+"access_action_traceability","action.traceability","model_action_traceability","stock.group_stock_user",1,0,0,0
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index a569a9dcbea..27930c8a3e7 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -350,7 +350,19 @@ stock_location()
class stock_tracking(osv.osv):
_name = "stock.tracking"
_description = "Stock Tracking Lots"
-
+
+ def get_create_tracking_lot(self, cr, uid, ids, tracking_lot):
+ tracking_lot_list = self.search(cr, uid, [('name', '=', tracking_lot)],
+ limit=1)
+ if tracking_lot_list:
+ tracking_lot = tracking_lot_list[0]
+ tracking_obj = self.browse(cr, uid, tracking_lot)
+ if not tracking_obj:
+ tracking_lot_vals = {
+ 'name': tracking_lot
+ }
+ tracking_lot = self.create(cr, uid, tracking_lot_vals)
+ return tracking_lot
def checksum(sscc):
salt = '31' * 8 + '3'
sum = 0
@@ -459,7 +471,15 @@ class stock_picking(osv.osv):
def create(self, cr, user, vals, context=None):
if ('name' not in vals) or (vals.get('name')=='/'):
vals['name'] = self.pool.get('ir.sequence').get(cr, user, 'stock.picking')
-
+ type_list = {
+ 'out':_('Packing List'),
+ 'in':_('Reception'),
+ 'internal': _('Internal picking'),
+ 'delivery': _('Delivery order')
+ }
+ if not vals.get('auto_picking', False):
+ message = type_list.get(vals.get('type',_('Picking'))) + " '" + vals['name'] + "' "+ _("created.")
+ self.log(cr, user, id, message)
return super(stock_picking, self).create(cr, user, vals, context)
_columns = {
@@ -532,7 +552,7 @@ class stock_picking(osv.osv):
def action_confirm(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, {'state': 'confirmed'})
todo = []
- for picking in self.browse(cr, uid, ids):
+ for picking in self.browse(cr, uid, ids, context=context):
for r in picking.move_lines:
if r.state == 'draft':
todo.append(r.id)
@@ -599,7 +619,16 @@ class stock_picking(osv.osv):
wf_service.trg_write(uid, 'stock.picking', pick.id, cr)
return True
- def action_assign_wkf(self, cr, uid, ids):
+ def action_assign_wkf(self, cr, uid, ids, context=None):
+ for pick in self.browse(cr, uid, ids, context=context):
+ type_list = {
+ 'out':'Packing List',
+ 'in':'Reception',
+ 'internal': 'Internal picking',
+ 'delivery': 'Delivery order'
+ }
+ message = type_list.get(pick.type, _('Document')) + " '" + pick.name + "' "+ _("is ready to be processed.")
+ self.log(cr, uid, id, message)
self.write(cr, uid, ids, {'state': 'assigned'})
return True
@@ -861,15 +890,23 @@ class stock_picking(osv.osv):
return True
def unlink(self, cr, uid, ids, context=None):
+ move_obj = self.pool.get('stock.move')
+ if not context:
+ context = {}
+
for pick in self.browse(cr, uid, ids, context=context):
if pick.state in ['done','cancel']:
raise osv.except_osv(_('Error'), _('You cannot remove the picking which is in %s state !')%(pick.state,))
- elif pick.state in ['confirmed','assigned']:
+ elif pick.state in ['confirmed','assigned', 'draft']:
ids2 = [move.id for move in pick.move_lines]
- context.update({'call_unlink':True})
- self.pool.get('stock.move').action_cancel(cr, uid, ids2, context)
- else:
- continue
+ ctx = context.copy()
+ ctx.update({'call_unlink':True})
+ if pick.state != 'draft':
+ #Cancelling the move in order to affect Virtual stock of product
+ move_obj.action_cancel(cr, uid, ids2, ctx)
+ #Removing the move
+ move_obj.unlink(cr, uid, ids2, ctx)
+
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
def do_partial(self, cr, uid, ids, partial_datas, context={}):
@@ -1006,7 +1043,7 @@ class stock_picking(osv.osv):
delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
delivery_id = delivery_obj.create(cr, uid, {
- 'name': delivered_pack.name,
+ 'name': delivered_pack.name or move.name,
'partner_id': partner_id,
'address_id': address_id,
'date': delivery_date,
@@ -1145,6 +1182,7 @@ class stock_move(osv.osv):
return (res and res[0]) or False
_name = "stock.move"
_description = "Stock Move"
+ _log_create = False
def name_get(self, cr, uid, ids, context={}):
res = []
@@ -1177,7 +1215,7 @@ class stock_move(osv.osv):
'date': fields.datetime('Created Date'),
'date_planned': fields.datetime('Date', required=True, help="Scheduled date for the movement of the products or real date if the move is done."),
-
+ 'date_expected': fields.datetime('Date Expected', readonly=True,required=True, help="Scheduled date for the movement of the products"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
'product_qty': fields.float('Quantity', required=True),
@@ -1255,7 +1293,8 @@ class stock_move(osv.osv):
'scraped' : lambda *a: False,
'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
- 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.move', context=c)
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.move', context=c),
+ 'date_expected': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
}
def copy(self, cr, uid, id, default=None, context={}):
@@ -1268,6 +1307,11 @@ class stock_move(osv.osv):
def create(self, cr, user, vals, context=None):
if vals.get('move_stock_return_history',False):
vals['move_stock_return_history'] = []
+ # Check that the stock.move is in draft state at creation to force
+ # passing through button_confirm
+ if vals.get('state','draft') not in ('draft','done','waiting'):
+ logger = netsvc.Logger()
+ logger.notifyChannel("code", netsvc.LOG_WARNING, "All new stock.move must be in state draft at the creation !")
return super(stock_move, self).create(cr, user, vals, context)
def _auto_init(self, cursor, context):
@@ -1494,9 +1538,12 @@ class stock_move(osv.osv):
#self.action_cancel(cr,uid, ids2, context)
return True
- def action_done(self, cr, uid, ids, context=None):
+ def action_done(self, cr, uid, ids, context={}):
track_flag = False
picking_ids = []
+ product_uom_obj = self.pool.get('product.uom')
+ price_type_obj = self.pool.get('product.price.type')
+ move_obj = self.pool.get('account.move')
for move in self.browse(cr, uid, ids):
if move.picking_id: picking_ids.append(move.picking_id.id)
if move.move_dest_id.id and (move.state != 'done'):
@@ -1558,7 +1605,6 @@ class stock_move(osv.osv):
journal_id = move.product_id.categ_id.property_stock_journal.id
if acc_src != acc_dest:
ref = move.picking_id and move.picking_id.name or False
- product_uom_obj = self.pool.get('product.uom')
default_uom = move.product_id.uom_id.id
date = time.strftime('%Y-%m-%d')
q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
@@ -1566,11 +1612,11 @@ class stock_move(osv.osv):
amount = q * move.price_unit
# Base computation on valuation price type
else:
- company_id=move.company_id.id
- context['currency_id']=move.company_id.currency_id.id
- pricetype=self.pool.get('product.price.type').browse(cr,uid,move.company_id.property_valuation_price_type.id)
- amount_unit=move.product_id.price_get(pricetype.field, context)[move.product_id.id]
- amount=amount_unit * q or 1.0
+ company_id = move.company_id.id
+ context['currency_id'] = move.company_id.currency_id.id
+ pricetype = price_type_obj.browse(cr,uid,move.company_id.property_valuation_price_type.id)
+ amount_unit = move.product_id.price_get(pricetype.field, context)[move.product_id.id]
+ amount = amount_unit * q or 1.0
# amount = q * move.product_id.standard_price
partner_id = False
@@ -1596,16 +1642,25 @@ class stock_move(osv.osv):
'date': date,
'partner_id': partner_id})
]
- self.pool.get('account.move').create(cr, uid, {
+ move_obj.create(cr, uid, {
'name': move.name,
'journal_id': journal_id,
'line_id': lines,
'ref': ref,
})
- self.write(cr, uid, ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S')})
- for pick in self.pool.get('stock.picking').browse(cr, uid, picking_ids):
+ tracking_lot = False
+ if context:
+ tracking_lot = context.get('tracking_lot', False)
+ if tracking_lot:
+ rec_id = context and context.get('active_id', False)
+ tracking = self.pool.get('stock.tracking')
+ tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
+
+ self.write(cr, uid, ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S'), 'tracking_id': tracking_lot or False})
+ picking_obj = self.pool.get('stock.picking')
+ for pick in picking_obj.browse(cr, uid, picking_ids):
if all(move.state == 'done' for move in pick.move_lines):
- self.pool.get('stock.picking').action_done(cr, uid, [pick.id])
+ picking_obj.action_done(cr, uid, [pick.id])
wf_service = netsvc.LocalService("workflow")
for id in ids:
@@ -1613,6 +1668,8 @@ class stock_move(osv.osv):
return True
def unlink(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
for move in self.browse(cr, uid, ids, context=context):
if move.state != 'draft':
raise osv.except_osv(_('UserError'),
@@ -1743,7 +1800,7 @@ class stock_move(osv.osv):
@ return: Consumed lines
'''
- if not context:
+ if context is None:
context = {}
if quantity <= 0:
@@ -1819,7 +1876,8 @@ class stock_move(osv.osv):
partner_id = partial_datas.get('partner_id', False)
address_id = partial_datas.get('address_id', False)
delivery_date = partial_datas.get('delivery_date', False)
-
+ tracking_lot = context.get('tracking_lot', False)
+
new_moves = []
complete, too_many, too_few = [], [], []
@@ -1835,6 +1893,10 @@ class stock_move(osv.osv):
product_price = partial_data.get('product_price',0.0)
product_currency = partial_data.get('product_currency',False)
if move.product_qty == product_qty:
+ self.write(cr, uid, move.id,
+ {
+ 'tracking_id': tracking_lot
+ })
complete.append(move)
elif move.product_qty > product_qty:
too_few.append(move)
@@ -1879,6 +1941,7 @@ class stock_move(osv.osv):
'state': 'assigned',
'move_dest_id': False,
'price_unit': move.price_unit,
+ 'tracking_id': tracking_lot,
})
complete.append(self.browse(cr, uid, new_move))
self.write(cr, uid, move.id,
@@ -1891,13 +1954,14 @@ class stock_move(osv.osv):
for move in too_many:
self.write(cr, uid, move.id,
{
- 'product_qty': product_qty,
- 'product_uos_qty': product_qty
+ 'product_qty': move.product_qty,
+ 'product_uos_qty': move.product_qty,
+ 'tracking_id': tracking_lot
})
complete.append(move)
for move in complete:
- self.action_done(cr, uid, [move.id])
+ self.action_done(cr, uid, [move.id], context)
# TOCHECK : Done picking if all moves are done
cr.execute("""
@@ -2017,7 +2081,7 @@ stock_inventory()
class stock_inventory_line(osv.osv):
_name = "stock.inventory.line"
- _description = "Inventory line"
+ _description = "Inventory Line"
_columns = {
'inventory_id': fields.many2one('stock.inventory', 'Inventory', ondelete='cascade', select=True),
'location_id': fields.many2one('stock.location', 'Location', required=True),
@@ -2053,9 +2117,9 @@ class stock_warehouse(osv.osv):
# 'partner_id': fields.many2one('res.partner', 'Owner'),
'company_id': fields.many2one('res.company','Company',required=True,select=1),
'partner_address_id': fields.many2one('res.partner.address', 'Owner Address'),
- 'lot_input_id': fields.many2one('stock.location', 'Location Input', required=True),
- 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True),
- 'lot_output_id': fields.many2one('stock.location', 'Location Output', required=True),
+ 'lot_input_id': fields.many2one('stock.location', 'Location Input', required=True, domain=[('usage','<>','view')]),
+ 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage','<>','view')]),
+ 'lot_output_id': fields.many2one('stock.location', 'Location Output', required=True, domain=[('usage','<>','view')]),
}
_defaults = {
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c),
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index b7a865e3d8f..5cb543b748e 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -50,9 +50,9 @@
-
-
-
+
+
+
@@ -69,7 +69,7 @@
stock.inventory
tree
-
+
@@ -83,28 +83,28 @@
form
-
+
Create Stock and Sales Forecasts
@@ -120,9 +120,9 @@
new
-
+
-
+
@@ -133,19 +133,19 @@
-
-
-
-
+
+
+
-
-
+
@@ -156,7 +156,7 @@
-
+
@@ -166,7 +166,7 @@
-
+
@@ -194,30 +194,30 @@
-
-
+
stock.sale.forecast.tree
stock.sale.forecast
tree
-
+
-
+
-
+
stock.sale.forecast.graph
stock.sale.forecast
@@ -244,28 +244,27 @@
-
-
-
+
-
+
Stock and Sales Forecast
stock.sale.forecast
form
tree,form,graph
+ {"search_default_create_uid":uid}
-
-
-
+
@@ -275,7 +274,7 @@
stock.planning.createlines
form
-
+
@@ -290,10 +289,10 @@
-
+
-
+
Create Stock Planning Lines
@@ -305,7 +304,7 @@
@@ -322,14 +321,14 @@
-
-
-
+
+
-
@@ -353,7 +352,7 @@
-
+
@@ -362,13 +361,13 @@
-
+
-
+
-
-
+
+
@@ -386,10 +385,10 @@
-
-
-
-
+
+
+
+
@@ -424,9 +423,9 @@
-
+
diff --git a/addons/subscription/subscription.py b/addons/subscription/subscription.py
index e9899156326..b05bf099d09 100644
--- a/addons/subscription/subscription.py
+++ b/addons/subscription/subscription.py
@@ -29,7 +29,7 @@ from tools.translate import _
class subscription_document(osv.osv):
_name = "subscription.document"
- _description = "Subscription document"
+ _description = "Subscription Document"
_columns = {
'name': fields.char('Name', size=60, required=True),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the subscription document without removing it."),
@@ -49,7 +49,7 @@ subscription_document()
class subscription_document_fields(osv.osv):
_name = "subscription.document.fields"
- _description = "Subscription document fields"
+ _description = "Subscription Document Fields"
_rec_name = 'field'
_columns = {
'field': fields.many2one('ir.model.fields', 'Field', domain="[('model_id', '=', parent.model)]", required=True),
diff --git a/addons/warning/warning.py b/addons/warning/warning.py
index 466283702c6..0aec93f1c90 100644
--- a/addons/warning/warning.py
+++ b/addons/warning/warning.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL ().
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
#
##############################################################################
@@ -49,7 +49,7 @@ class res_partner(osv.osv):
'picking_warn' : lambda *a: 'no-message',
'invoice_warn' : lambda *a: 'no-message',
}
-
+
res_partner()
@@ -73,11 +73,11 @@ class sale_order(osv.osv):
}
result = super(sale_order, self).onchange_partner_id(cr, uid, ids, part)
-
+
if result.get('warning',False):
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
warning['message'] = message and message + ' ' + result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
sale_order()
@@ -101,21 +101,20 @@ class purchase_order(osv.osv):
'message': message
}
result = super(purchase_order, self).onchange_partner_id(cr, uid, ids, part)
-
+
if result.get('warning',False):
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
warning['message'] = message and message + ' ' + result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
-
+
purchase_order()
class account_invoice(osv.osv):
_inherit = 'account.invoice'
def onchange_partner_id(self, cr, uid, ids, type, partner_id,
- date_invoice=False, payment_term=False, partner_bank_id=False):
-
+ date_invoice=False, payment_term=False, partner_bank=False, company_id=False):
if not partner_id:
return {'value': {
'address_contact_id': False ,
@@ -131,7 +130,7 @@ class account_invoice(osv.osv):
if partner.invoice_warn != 'no-message':
if partner.invoice_warn == 'block':
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.invoice_warn_msg)
-
+
title = _("Warning for %s") % partner.name
message = partner.invoice_warn_msg
warning = {
@@ -139,19 +138,19 @@ class account_invoice(osv.osv):
'message': message
}
result = super(account_invoice, self).onchange_partner_id(cr, uid, ids, type, partner_id,
- date_invoice=False, payment_term=False, partner_bank_id=False)
-
+ date_invoice=False, payment_term=False, partner_bank=False)
+
if result.get('warning',False):
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
warning['message'] = message and message + ' ' + result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
-
+
account_invoice()
class stock_picking(osv.osv):
_inherit = 'stock.picking'
-
+
def onchange_partner_in(self, cr, uid, context, partner_id=None):
if not partner_id:
return {}
@@ -172,9 +171,9 @@ class stock_picking(osv.osv):
if result.get('warning',False):
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
warning['message'] = message and message + ' ' + result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
-
+
stock_picking()
class product_product(osv.osv):
@@ -185,12 +184,12 @@ class product_product(osv.osv):
'purchase_line_warn' : fields.selection(WARNING_MESSAGE,'Purchase Order Line', help=WARNING_HELP),
'purchase_line_warn_msg' : fields.text('Message for Purchase Order Line'),
}
-
+
_defaults = {
'sale_line_warn' : lambda *a: 'no-message',
'purchase_line_warn' : lambda *a: 'no-message',
}
-
+
product_product()
class sale_order_line(osv.osv):
@@ -204,11 +203,11 @@ class sale_order_line(osv.osv):
return {'value': {'th_weight' : 0, 'product_packaging': False,
'product_uos_qty': qty}, 'domain': {'product_uom': [],
'product_uos': []}}
- product_obj = self.pool.get('product.product')
+ product_obj = self.pool.get('product.product')
product_info = product_obj.browse(cr, uid, product)
title = False
message = False
-
+
if product_info.sale_line_warn != 'no-message':
if product_info.sale_line_warn == 'block':
raise osv.except_osv(_('Alert for %s !') % (product_info.name), product_info.sale_line_warn_msg)
@@ -216,7 +215,7 @@ class sale_order_line(osv.osv):
message = product_info.sale_line_warn_msg
warning['title'] = title
warning['message'] = message
-
+
result = super(sale_order_line, self).product_id_change( cr, uid, ids, pricelist, product, qty,
uom, qty_uos, uos, name, partner_id,
lang, update_tax, date_order, packaging, fiscal_position, flag)
@@ -227,9 +226,9 @@ class sale_order_line(osv.osv):
if result.get('warning',False):
warning['title'] = title and title +' & '+result['warning']['title'] or result['warning']['title']
warning['message'] = message and message +'\n\n'+result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
-
+
sale_order_line()
class purchase_order_line(osv.osv):
@@ -239,11 +238,11 @@ class purchase_order_line(osv.osv):
warning = {}
if not product:
return {'value': {'price_unit': 0.0, 'name':'','notes':'', 'product_uom' : False}, 'domain':{'product_uom':[]}}
- product_obj = self.pool.get('product.product')
+ product_obj = self.pool.get('product.product')
product_info = product_obj.browse(cr, uid, product)
title = False
message = False
-
+
if product_info.purchase_line_warn != 'no-message':
if product_info.purchase_line_warn == 'block':
raise osv.except_osv(_('Alert for %s !') % (product_info.name), product_info.purchase_line_warn_msg)
@@ -251,16 +250,16 @@ class purchase_order_line(osv.osv):
message = product_info.purchase_line_warn_msg
warning['title'] = title
warning['message'] = message
-
+
result = super(purchase_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty, uom,
partner_id, date_order, fiscal_position)
if result.get('warning',False):
warning['title'] = title and title +' & '+result['warning']['title'] or result['warning']['title']
warning['message'] = message and message +'\n\n'+result['warning']['message'] or result['warning']['message']
-
+
return {'value': result.get('value',{}), 'warning':warning}
-
+
purchase_order_line()
diff --git a/addons/wiki/wiki_view.xml b/addons/wiki/wiki_view.xml
index 4675cea75f9..93f0df72361 100644
--- a/addons/wiki/wiki_view.xml
+++ b/addons/wiki/wiki_view.xml
@@ -155,12 +155,12 @@
-
+
@@ -174,7 +174,7 @@
form
tree,form
- {'section':'1'}
+ {'section':'1','search_default_create_uid':uid}