[IMP]: MOVE PROCUREMENT CHANGES INTO PROCUREMENT..

bzr revid: atp@tinyerp.com-20120909101156-9pna66qbx28px2ii
This commit is contained in:
Atul Patel (OpenERP) 2012-09-09 15:41:56 +05:30
parent 9c9ba99596
commit eb28892a3a
37 changed files with 390 additions and 332 deletions

View File

@ -26,8 +26,9 @@
"author" : "OpenERP SA", "author" : "OpenERP SA",
"website" : "http://www.openerp.com", "website" : "http://www.openerp.com",
"category" : "Hidden/Dependency", "category" : "Hidden/Dependency",
"depends" : ["base","process", "product", "stock"], "depends" : ["process", "product", "stock"],
"description": """ "description": """
This is the module for computing Procurements. This is the module for computing Procurements.
============================================== ==============================================
@ -43,8 +44,7 @@ for the product which needs replenishment. This procurement will start a
task, either a purchase order form for the supplier, or a production order task, either a purchase order form for the supplier, or a production order
depending on the product's configuration. depending on the product's configuration.
""", """,
'init_xml': [], 'data': [
'update_xml': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/procurement_security.xml', 'security/procurement_security.xml',
'procurement_data.xml', 'procurement_data.xml',
@ -55,13 +55,13 @@ depending on the product's configuration.
'procurement_view.xml', 'procurement_view.xml',
'procurement_workflow.xml', 'procurement_workflow.xml',
'process/procurement_process.xml', 'process/procurement_process.xml',
"company_view.xml", 'company_view.xml',
'board_mrp_procurement_view.xml', 'board_mrp_procurement_view.xml',
], ],
'demo_xml': ['stock_orderpoint.xml'], 'demo': ['stock_orderpoint.xml'],
'test': ['test/procurement.yml'], 'test': ['test/procurement.yml'],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': True,
'certificate': '00954248826881074509', 'certificate': '00954248826881074509',
'images': ['images/compute_schedulers.jpeg','images/config_companies_sched.jpeg', 'images/minimum_stock_rules.jpeg'], 'images': ['images/compute_schedulers.jpeg','images/config_companies_sched.jpeg', 'images/minimum_stock_rules.jpeg'],
} }

View File

@ -23,15 +23,15 @@
'name': 'Sales Management', 'name': 'Sales Management',
'version': '1.0', 'version': '1.0',
'category': 'Sales Management', 'category': 'Sales Management',
"sequence": 14, 'sequence': 14,
"summary": "Quotations, Sale Orders, Invoicing", 'summary': 'Quotations, Sale Orders, Invoicing',
'description': """ 'description': """
The base module to manage quotations and sales orders. The base module to manage quotations and sales orders.
====================================================== ======================================================
Workflow with validation steps: Workflow with validation steps:
------------------------------- -------------------------------
* Quotation -> Sales order -> Invoice * **Quotation** -> **Sales order** -> **Invoice**
Create Invoice: Create Invoice:
--------------- ---------------
@ -51,9 +51,11 @@ Dashboard for Sales Manager that includes:
'author': 'OpenERP SA', 'author': 'OpenERP SA',
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ['images/deliveries_to_invoice.jpeg','images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'], 'images': ['images/deliveries_to_invoice.jpeg','images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'],
'depends': ['board', 'account_voucher'], 'depends': ['account_voucher'],
'init_xml': [], 'data': [
'update_xml': ['wizard/sale_line_invoice.xml', 'wizard/sale_make_invoice_advance.xml',
'wizard/sale_line_invoice.xml',
'wizard/sale_make_invoice.xml',
'security/sale_security.xml', 'security/sale_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'sale_workflow.xml', 'sale_workflow.xml',
@ -68,10 +70,10 @@ Dashboard for Sales Manager that includes:
'edi/sale_order_action_data.xml', 'edi/sale_order_action_data.xml',
'res_config_view.xml', 'res_config_view.xml',
], ],
'demo_xml': ['sale_demo.xml'], 'demo': ['sale_demo.xml'],
'test': [ 'test': [
'test/sale_order_demo.yml', 'test/sale_order_demo.yml',
'test/prepaid_order_policy.yml', 'test/manual_order_policy.yml',
'test/cancel_order.yml', 'test/cancel_order.yml',
'test/delete_order.yml', 'test/delete_order.yml',
'test/edi_sale_order.yml', 'test/edi_sale_order.yml',

View File

@ -79,7 +79,7 @@ class sale_report(osv.osv):
s.partner_id as partner_id, s.partner_id as partner_id,
s.user_id as user_id, s.user_id as user_id,
s.shop_id as shop_id, s.shop_id as shop_id,
s.company_id as company_id, s.company_id as company_id,
extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay, extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
s.state, s.state,
t.categ_id as categ_id, t.categ_id as categ_id,
@ -103,7 +103,7 @@ class sale_report(osv.osv):
s.partner_id, s.partner_id,
s.user_id, s.user_id,
s.shop_id, s.shop_id,
s.company_id, s.company_id,
s.state, s.state,
s.pricelist_id, s.pricelist_id,
s.project_id s.project_id

View File

@ -27,9 +27,6 @@ class sale_configuration(osv.osv_memory):
_inherit = 'sale.config.settings' _inherit = 'sale.config.settings'
_columns = { _columns = {
'group_invoice_so_lines': fields.boolean('generate invoices based on the sale order',
implied_group='sale.group_invoice_so_lines',
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
'timesheet': fields.boolean('prepare invoices based on timesheets', 'timesheet': fields.boolean('prepare invoices based on timesheets',
help = """For modifying account analytic view to show important data to project manager of services companies. help = """For modifying account analytic view to show important data to project manager of services companies.
You can also view the report of account analytic summary user-wise as well as month wise. You can also view the report of account analytic summary user-wise as well as month wise.
@ -40,11 +37,7 @@ class sale_configuration(osv.osv_memory):
(650/day for a developer), the duration (one year support contract). (650/day for a developer), the duration (one year support contract).
You will be able to follow the progress of the contract and invoice automatically. You will be able to follow the progress of the contract and invoice automatically.
It installs the account_analytic_analysis module."""), It installs the account_analytic_analysis module."""),
'default_order_policy': fields.selection( 'time_unit': fields.many2one('product.uom', 'the default working time unit for services is'),
[('manual', 'Invoice Based on Sales Orders')],
'The default invoicing method is', default_model='sale.order',
help="You can generate invoices based on sales orders."),
'time_unit': fields.many2one('product.uom', 'The default working time unit for services is'),
'group_sale_pricelist':fields.boolean("use pricelists to adapt your price per customers", 'group_sale_pricelist':fields.boolean("use pricelists to adapt your price per customers",
implied_group='product.group_sale_pricelist', implied_group='product.group_sale_pricelist',
help="""Allows to manage different prices based on rules per category of customers. help="""Allows to manage different prices based on rules per category of customers.
@ -76,6 +69,8 @@ class sale_configuration(osv.osv_memory):
But the possibility to change these values is still available. But the possibility to change these values is still available.
This installs the module analytic_user_function."""), This installs the module analytic_user_function."""),
'module_project': fields.boolean("Project"), 'module_project': fields.boolean("Project"),
'module_sale_stock': fields.boolean("Sale and Warehouse Management",
help="""Allows you to Make Quotation, Sale Order using different Order policy and Manage Related Stock """),
} }
def default_get(self, cr, uid, fields, context=None): def default_get(self, cr, uid, fields, context=None):
@ -94,11 +89,9 @@ class sale_configuration(osv.osv_memory):
return ids and ids[0] or False return ids and ids[0] or False
_defaults = { _defaults = {
'default_order_policy': 'manual',
'time_unit': _get_default_time_unit, 'time_unit': _get_default_time_unit,
} }
def set_sale_defaults(self, cr, uid, ids, context=None): def set_sale_defaults(self, cr, uid, ids, context=None):
ir_model_data = self.pool.get('ir.model.data') ir_model_data = self.pool.get('ir.model.data')
wizard = self.browse(cr, uid, ids)[0] wizard = self.browse(cr, uid, ids)[0]
@ -110,12 +103,7 @@ class sale_configuration(osv.osv_memory):
if wizard.module_project and wizard.time_unit: if wizard.module_project and wizard.time_unit:
user = self.pool.get('res.users').browse(cr, uid, uid, context) user = self.pool.get('res.users').browse(cr, uid, uid, context)
user.company_id.write({'project_time_mode_id': wizard.time_unit.id}) user.company_id.write({'project_time_mode_id': wizard.time_unit.id})
return {}
def onchange_invoice_methods(self, cr, uid, ids, group_invoice_so_lines, context=None):
if group_invoice_so_lines:
return {'value': {'default_order_policy': 'manual'}}
return {} return {}
def onchange_task_work(self, cr, uid, ids, task_work, context=None): def onchange_task_work(self, cr, uid, ids, task_work, context=None):

View File

@ -11,23 +11,15 @@
<group> <group>
<label for="id" string="Invoicing Process"/> <label for="id" string="Invoicing Process"/>
<div> <div>
<div name="invoice_so_lines"> <div name="timesheet">
<field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines)" class="oe_inline"/>
<label for="group_invoice_so_lines"/>
</div>
<div>
<field name="timesheet" class="oe_inline" on_change="onchange_timesheet(timesheet)"/> <field name="timesheet" class="oe_inline" on_change="onchange_timesheet(timesheet)"/>
<label for="timesheet"/> <label for="timesheet"/>
</div> </div>
</div> </div>
</group> </group>
<group name='default_options'> <group name='default_options'>
<label for="id" string="Default Options" attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('module_account_analytic_analysis','=',False)]}"/> <label for="id" string="Default Options" attrs="{'invisible':[('module_account_analytic_analysis','=',False)]}"/>
<div> <div>
<div name='default_order_policy' attrs="{'invisible':[('group_invoice_so_lines','=',False)],'required': [('group_invoice_so_lines','=',True)]}">
<label for="default_order_policy"/>
<field name="default_order_policy" class="oe_inline"/>
</div>
<div name='time_unit' attrs="{'invisible': [('module_account_analytic_analysis','=',False)],'required':[('module_account_analytic_analysis','=',True)]}"> <div name='time_unit' attrs="{'invisible': [('module_account_analytic_analysis','=',False)],'required':[('module_account_analytic_analysis','=',True)]}">
<label for="time_unit"/> <label for="time_unit"/>
<field name="time_unit" domain="[('category_id.name','=','Working Time')]" class="oe_inline"/> <field name="time_unit" domain="[('category_id.name','=','Working Time')]" class="oe_inline"/>
@ -53,6 +45,10 @@
<group> <group>
<label for="id" string="Warehouse Features"/> <label for="id" string="Warehouse Features"/>
<div name="warehouse_features"> <div name="warehouse_features">
<div name='module_sale_stock'>
<field name="module_sale_stock" class="oe_inline"/>
<label for="module_sale_stock"/>
</div>
<div name='module_sale_journal'> <div name='module_sale_journal'>
<field name="module_sale_journal" class="oe_inline"/> <field name="module_sale_journal" class="oe_inline"/>
<label for="module_sale_journal"/> <label for="module_sale_journal"/>

View File

@ -47,7 +47,7 @@ sale_shop()
class sale_order(osv.osv): class sale_order(osv.osv):
_name = "sale.order" _name = "sale.order"
_inherit = ['ir.needaction_mixin', 'mail.thread'] _inherit = ['mail.thread', 'ir.needaction_mixin']
_description = "Sales Order" _description = "Sales Order"
def copy(self, cr, uid, id, default=None, context=None): def copy(self, cr, uid, id, default=None, context=None):
@ -157,8 +157,9 @@ class sale_order(osv.osv):
_columns = { _columns = {
'name': fields.char('Order Reference', size=64, required=True, 'name': fields.char('Order Reference', size=64, required=True,
readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, select=True), readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, select=True),
'shop_id': fields.many2one('sale.shop', 'Shop', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}), 'shop_id': fields.many2one('sale.shop', 'Shop', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
'origin': fields.char('Source Document', size=64, help="Reference of the document that generated this sales order request."), 'origin': fields.char('Source Document', size=64, help="Reference of the document that generated this sales order request."),
'client_order_ref': fields.char('Customer Reference', size=64), 'client_order_ref': fields.char('Customer Reference', size=64),
'state': fields.selection([ 'state': fields.selection([
('draft', 'Draft Quotation'), ('draft', 'Draft Quotation'),
@ -166,6 +167,7 @@ class sale_order(osv.osv):
('cancel', 'Cancelled'), ('cancel', 'Cancelled'),
('waiting_date', 'Waiting Schedule'), ('waiting_date', 'Waiting Schedule'),
('progress', 'Sale Order'), ('progress', 'Sale Order'),
('manual', 'Sale to Invoice'),
('invoice_except', 'Invoice Exception'), ('invoice_except', 'Invoice Exception'),
('done', 'Done'), ('done', 'Done'),
], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True), ], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
@ -177,7 +179,7 @@ class sale_order(osv.osv):
'partner_invoice_id': fields.many2one('res.partner', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order."), 'partner_invoice_id': fields.many2one('res.partner', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order."),
'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Shipping address for current sales order."), 'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Shipping address for current sales order."),
'order_policy': fields.selection([ 'order_policy': fields.selection([
('prepaid', 'Before Delivery'), ('manual', 'On Demand'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, ], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
help="""This field controls how invoice and delivery operations are synchronized. help="""This field controls how invoice and delivery operations are synchronized.
- With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""), - With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
@ -217,7 +219,7 @@ class sale_order(osv.osv):
} }
_defaults = { _defaults = {
'date_order': fields.date.context_today, 'date_order': fields.date.context_today,
'order_policy': 'prepaid', 'order_policy': 'manual',
'state': 'draft', 'state': 'draft',
'user_id': lambda obj, cr, uid, context: uid, 'user_id': lambda obj, cr, uid, context: uid,
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'sale.order'), 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'sale.order'),
@ -242,17 +244,6 @@ class sale_order(osv.osv):
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
def onchange_shop_id(self, cr, uid, ids, shop_id):
v = {}
if shop_id:
shop = self.pool.get('sale.shop').browse(cr, uid, shop_id)
v['project_id'] = shop.project_id.id
# Que faire si le client a une pricelist a lui ?
if shop.pricelist_id.id:
v['pricelist_id'] = shop.pricelist_id.id
return {'value': v}
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}): def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}):
if (not pricelist_id) or (not order_lines): if (not pricelist_id) or (not order_lines):
return {} return {}
@ -317,7 +308,6 @@ class sale_order(osv.osv):
if not journal_ids: if not journal_ids:
raise osv.except_osv(_('Error!'), raise osv.except_osv(_('Error!'),
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id)) _('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
invoice_vals = { invoice_vals = {
'name': order.client_order_ref or '', 'name': order.client_order_ref or '',
'origin': order.name, 'origin': order.name,
@ -333,12 +323,12 @@ class sale_order(osv.osv):
'fiscal_position': order.fiscal_position.id or 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), 'date_invoice': context.get('date_invoice', False),
'company_id': order.company_id.id, 'company_id': order.company_id.id,
'user_id': order.user_id and order.user_id.id or False 'user_id': order.user_id and order.user_id.id or False,
} }
# Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1 # Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1
invoice_vals.update(self._inv_get(cr, uid, order, context=context)) invoice_vals.update(self._inv_get(cr, uid, order, context=context))
return invoice_vals return invoice_vals
def _make_invoice(self, cr, uid, order, lines, context=None): def _make_invoice(self, cr, uid, order, lines, context=None):
@ -414,6 +404,37 @@ class sale_order(osv.osv):
result.update(view_id = res and res[1] or False) result.update(view_id = res and res[1] or False)
return result return result
def manual_invoice(self, cr, uid, ids, context=None):
""" create invoices for the given sale orders (ids), and open the form
view of one of the newly created invoices
"""
mod_obj = self.pool.get('ir.model.data')
wf_service = netsvc.LocalService("workflow")
# create invoices through the sale orders' workflow
inv_ids0 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
for id in ids:
wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
inv_ids1 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
# determine newly created invoices
new_inv_ids = list(inv_ids1 - inv_ids0)
res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
res_id = res and res[1] or False,
return {
'name': _('Customer Invoices'),
'view_type': 'form',
'view_mode': 'form',
'view_id': [res_id],
'res_model': 'account.invoice',
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
'nodestroy': True,
'target': 'current',
'res_id': new_inv_ids and new_inv_ids[0] or False,
}
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None): def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
res = False res = False
invoices = {} invoices = {}
@ -517,6 +538,7 @@ class sale_order(osv.osv):
# #
if order.state == 'invoice_except': if order.state == 'invoice_except':
self.write(cr, uid, [order.id], {'state': 'progress'}, context=context) self.write(cr, uid, [order.id], {'state': 'progress'}, context=context)
self.invoice_paid_send_note(cr, uid, [order.id], context=context)
return True return True
def action_cancel(self, cr, uid, ids, context=None): def action_cancel(self, cr, uid, ids, context=None):
@ -563,7 +585,7 @@ class sale_order(osv.osv):
for o in self.browse(cr, uid, ids): for o in self.browse(cr, uid, ids):
if not o.order_line: if not o.order_line:
raise osv.except_osv(_('Error !'),_('You cannot confirm a sale order which has no line.')) raise osv.except_osv(_('Error !'),_('You cannot confirm a sale order which has no line.'))
self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)}) self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line]) self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
self.confirm_send_note(cr, uid, ids, context) self.confirm_send_note(cr, uid, ids, context)
return True return True
@ -591,37 +613,42 @@ class sale_order(osv.osv):
'context': ctx, 'context': ctx,
'nodestroy': True, 'nodestroy': True,
} }
def action_done(self, cr, uid, ids, context=None):
self.done_send_note(cr, uid, ids, context=context)
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
# ------------------------------------------------ # ------------------------------------------------
# OpenChatter methods and notifications # OpenChatter methods and notifications
# ------------------------------------------------ # ------------------------------------------------
def get_needaction_user_ids(self, cr, uid, ids, context=None): def needaction_domain_get(self, cr, uid, ids, context=None):
result = super(sale_order, self).get_needaction_user_ids(cr, uid, ids, context=context) return [('state', '=', 'draft'), ('user_id','=',uid)]
for obj in self.browse(cr, uid, ids, context=context):
if (obj.state == 'progress'):
result[obj.id].append(obj.user_id.id)
return result
def create_send_note(self, cr, uid, ids, context=None): def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context): for obj in self.browse(cr, uid, ids, context=context):
self.message_append_note(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> has been <b>created</b>.") % (obj.partner_id.name), context=context) self.message_post(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> <b>created</b>.") % (obj.partner_id.name), context=context)
def confirm_send_note(self, cr, uid, ids, context=None): def confirm_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context): for obj in self.browse(cr, uid, ids, context=context):
self.message_append_note(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> <b>converted</b> to Sale Order of %s %s.") % (obj.partner_id.name, obj.amount_total, obj.pricelist_id.currency_id.symbol), context=context) self.message_post(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> <b>converted</b> to Sale Order of %s %s.") % (obj.partner_id.name, obj.amount_total, obj.pricelist_id.currency_id.symbol), context=context)
def cancel_send_note(self, cr, uid, ids, context=None): def cancel_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context): for obj in self.browse(cr, uid, ids, context=context):
self.message_append_note(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> <b>cancelled</b>.") % (obj.partner_id.name), context=context) self.message_append_note(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> <b>cancelled</b>.") % (obj.partner_id.name), context=context)
def done_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
self.message_append_note(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> has been <b>done</b>") % (obj.partner_id.name), context=context)
def invoice_paid_send_note(self, cr, uid, ids, context=None): def invoice_paid_send_note(self, cr, uid, ids, context=None):
self.message_append_note(cr, uid, ids, body=_("Invoice <b>paid</b>."), context=context) self.message_append_note(cr, uid, ids, body=_("Invoice has been <b>paid</b>."), context=context)
def invoice_send_note(self, cr, uid, ids, invoice_id, context=None): def invoice_send_note(self, cr, uid, ids, invoice_id, context=None):
for order in self.browse(cr, uid, ids, context=context): for order in self.browse(cr, uid, ids, context=context):
for invoice in (inv for inv in order.invoice_ids if inv.id == invoice_id): for invoice in (inv for inv in order.invoice_ids if inv.id == invoice_id):
self.message_append_note(cr, uid, [order.id], body=_("Draft Invoice of %s %s <b>waiting for validation</b>.") % (invoice.amount_total, invoice.currency_id.symbol), context=context) self.message_append_note(cr, uid, [order.id], body=_("Draft Invoice of %s %s <b>waiting for validation</b>.") % (invoice.amount_total, invoice.currency_id.symbol), context=context)
sale_order() sale_order()
# TODO add a field price_unit_uos # TODO add a field price_unit_uos
@ -642,8 +669,6 @@ class sale_order_line(osv.osv):
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total']) res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
return res return res
def _get_uom_id(self, cr, uid, *args): def _get_uom_id(self, cr, uid, *args):
try: try:
proxy = self.pool.get('ir.model.data') proxy = self.pool.get('ir.model.data')
@ -679,7 +704,8 @@ class sale_order_line(osv.osv):
\n* The \'Cancelled\' state is set when a user cancel the sales order related.'), \n* The \'Cancelled\' state is set when a user cancel the sales order related.'),
'order_partner_id': fields.related('order_id', 'partner_id', type='many2one', relation='res.partner', store=True, string='Customer'), 'order_partner_id': fields.related('order_id', 'partner_id', type='many2one', relation='res.partner', store=True, string='Customer'),
'salesman_id':fields.related('order_id', 'user_id', type='many2one', relation='res.users', store=True, string='Salesperson'), 'salesman_id':fields.related('order_id', 'user_id', type='many2one', relation='res.users', store=True, string='Salesperson'),
'company_id': fields.related('order_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), 'company_id': fields.related('order_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
} }
_order = 'sequence, id' _order = 'sequence, id'
_defaults = { _defaults = {
@ -704,7 +730,7 @@ class sale_order_line(osv.osv):
(this is used for returning products including service) (this is used for returning products including service)
:return: dict of values to create() the invoice line :return: dict of values to create() the invoice line
""" """
res = {}
def _get_line_qty(line): def _get_line_qty(line):
if (line.order_id.invoice_quantity=='order'): if (line.order_id.invoice_quantity=='order'):
if line.product_uos: if line.product_uos:
@ -716,7 +742,6 @@ class sale_order_line(osv.osv):
if line.product_uos: if line.product_uos:
return line.product_uos.id return line.product_uos.id
return line.product_uom.id return line.product_uom.id
if not line.invoiced: if not line.invoiced:
if not account_id: if not account_id:
if line.product_id: if line.product_id:
@ -743,7 +768,7 @@ class sale_order_line(osv.osv):
if not account_id: if not account_id:
raise osv.except_osv(_('Error!'), raise osv.except_osv(_('Error!'),
_('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.')) _('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.'))
return { res = {
'name': line.name, 'name': line.name,
'origin': line.order_id.name, 'origin': line.order_id.name,
'account_id': account_id, 'account_id': account_id,
@ -756,7 +781,7 @@ class sale_order_line(osv.osv):
'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False, 'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False,
} }
return False return res
def invoice_line_create(self, cr, uid, ids, context=None): def invoice_line_create(self, cr, uid, ids, context=None):
if context is None: if context is None:
@ -842,10 +867,9 @@ class sale_order_line(osv.osv):
'product_uos': []}} 'product_uos': []}}
if not date_order: if not date_order:
date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT) date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
#
res = {} result = {}
result = res warning_msgs = {}
warning_msgs = res.get('warning') and res['warning']['message'] or ''
product_obj = product_obj.browse(cr, uid, product, context=context) product_obj = product_obj.browse(cr, uid, product, context=context)
uom2 = False uom2 = False

View File

@ -39,14 +39,16 @@
<function eval="('default',False,'shop_id', [('sale.order', False)], sale_shop_1, True, False, False, False, True)" id="sale_default_set" model="ir.values" name="set"/> <function eval="('default',False,'shop_id', [('sale.order', False)], sale_shop_1, True, False, False, False, True)" id="sale_default_set" model="ir.values" name="set"/>
<!-- notify all employees of module installation -->
<function model="mail.group" name="message_append_note">
<!-- ids, subject, body, parent_id=False, type='notification', content_subtype='html' -->
<value eval="[ref('mail.group_all_employees')]"/>
<value>The Sales Management application has been installed.</value>
<value>This modules allows you to create and send easily quotations and process your sales orders; from the delivery to the invoicing.
If you need to manage your sales pipeline (leads, opportunities, phonecalls), you can install the module &lt;i&gt;CRM&lt;/i&gt; from the top menu Settings.</value> <!-- notify all employees of module installation -->
</function> <record model="mail.message" id="module_install_notification">
<field name="model">mail.group</field>
<field name="res_id" ref="mail.group_all_employees"/>
<field name="type">notification</field>
<field name="subject">Sales Management application installed!</field>
<field name="body">This application lets you create and send quotations and process your sales orders; from delivery to invoicing.
If you need to manage your sales pipeline (leads, opportunities, phonecalls), the &lt;i&gt;CRM&lt;/i&gt; application may be useful. Use the Settings menu to install it.</field>
</record>
</data> </data>
</openerp> </openerp>

View File

@ -9,7 +9,6 @@
<field name="shop_id" ref="sale_shop_1"/> <field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/> <field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">prepaid</field>
</record> </record>
<record id="sale_order_line_1" model="sale.order.line"> <record id="sale_order_line_1" model="sale.order.line">
@ -49,6 +48,7 @@
<field name="shop_id" ref="sale_shop_1"/> <field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record> </record>
<record id="sale_order_line_4" model="sale.order.line"> <record id="sale_order_line_4" model="sale.order.line">
@ -78,6 +78,7 @@
<field name="shop_id" ref="sale_shop_1"/> <field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record> </record>
<record id="sale_order_line_6" model="sale.order.line"> <record id="sale_order_line_6" model="sale.order.line">
@ -107,7 +108,6 @@
<field name="shop_id" ref="sale_shop_1"/> <field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">prepaid</field>
</record> </record>
<record id="sale_order_line_8" model="sale.order.line"> <record id="sale_order_line_8" model="sale.order.line">
@ -212,9 +212,9 @@
<field name="partner_id" ref="base.res_partner_11"/> <field name="partner_id" ref="base.res_partner_11"/>
<field name="partner_invoice_id" ref="base.res_partner_address_20"/> <field name="partner_invoice_id" ref="base.res_partner_address_20"/>
<field name="partner_shipping_id" ref="base.res_partner_address_20"/> <field name="partner_shipping_id" ref="base.res_partner_address_20"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record> </record>
<record id="sale_order_line_16" model="sale.order.line"> <record id="sale_order_line_16" model="sale.order.line">
@ -264,6 +264,7 @@
<field name="shop_id" ref="sale_shop_1"/> <field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/> <field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/> <field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record> </record>
<record id="sale_order_line_20" model="sale.order.line"> <record id="sale_order_line_20" model="sale.order.line">
@ -285,10 +286,41 @@
<field name="product_uom" ref="product.product_uom_unit"/> <field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">12.50</field> <field name="price_unit">12.50</field>
</record> </record>
<!-- Confirm some Sale Orders--> <!-- Confirm some Sale Orders-->
<workflow action="order_confirm" model="sale.order" ref="sale_order_1"/> <workflow action="order_confirm" model="sale.order" ref="sale_order_7"/>
<record id="message_sale_1" model="mail.message">
<field name="model">sale.order</field>
<field name="res_id" ref="sale_order_2"/>
<field name="body">Hi,
I have a confusion for pricing of Services, I have heard there is a discount above 25 hours.
Can you clarify please?</field>
<field name="type">comment</field>
<field name="author_id" ref="base.partner_demo"/>
</record>
<record id="message_sale_2" model="mail.message">
<field name="model">sale.order</field>
<field name="res_id" ref="sale_order_2"/>
<field name="parent_id" ref="message_sale_1"/>
<field name="body">Hello,
Sorry but that scheme is not available for now,
We would like to know if you confirm the quotation with pricing we sent to you.
Thanks,
Sales Department</field>
<field name="type">comment</field>
<field name="author_id" ref="base.partner_root"/>
</record>
<record id="message_sale_3" model="mail.message">
<field name="model">sale.order</field>
<field name="res_id" ref="sale_order_2"/>
<field name="parent_id" ref="message_sale_2"/>
<field name="body">Ok, fine, we will intimate you after discussing with our team.</field>
<field name="type">comment</field>
<field name="author_id" ref="base.partner_demo"/>
</record>
<!-- sale advance demo.. --> <!-- sale advance demo.. -->
<!-- Demo Data for Product --> <!-- Demo Data for Product -->

View File

@ -13,7 +13,7 @@
<!-- Resource: sale.order.line --> <!-- Resource: sale.order.line -->
<record id="test_order_1_line_1" model="sale.order.line"> <record id="test_order_1_line_1" model="sale.order.line">
<field name="order_id" ref="test_order_1"/> <field name="order_id" ref="test_order_1"/>
<field name="name">[PC1] Basic PC</field> <field name="name">[PCSC234] PC Assemble SC234</field>
<field name="product_id" ref="product.product_product_3"/> <field name="product_id" ref="product.product_product_3"/>
<field name="product_uom" ref="product.product_uom_unit"/> <field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">450</field> <field name="price_unit">450</field>
@ -23,7 +23,7 @@
</record> </record>
<record id="test_order_1_line_3" model="sale.order.line"> <record id="test_order_1_line_3" model="sale.order.line">
<field name="order_id" ref="test_order_1"/> <field name="order_id" ref="test_order_1"/>
<field name="name">[RAM512] DDR 512MB PC400</field> <field name="name">[HDD-SH2] HDD SH-2</field>
<field name="product_id" ref="product.product_product_18"/> <field name="product_id" ref="product.product_product_18"/>
<field name="product_uom" ref="product.product_uom_unit"/> <field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">90</field> <field name="price_unit">90</field>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data> <data>
<!-- Top menu item --> <!-- Top menu item -->
<!-- <!--
This menu item's purpose is to overwrite another one defined in This menu item's purpose is to overwrite another one defined in
@ -32,7 +31,7 @@
</group> </group>
</group> </group>
</form> </form>
</field> </field>
</record> </record>
<record id="view_shop_tree" model="ir.ui.view"> <record id="view_shop_tree" model="ir.ui.view">
@ -65,7 +64,6 @@
</field> </field>
</record> </record>
<menuitem action="action_shop_form" id="menu_action_shop_form" parent="base.menu_base_config" sequence="35"/>
<!-- Sale order Read/Unread actions --> <!-- Sale order Read/Unread actions -->
<record id="actions_server_sale_order_unread" model="ir.actions.server"> <record id="actions_server_sale_order_unread" model="ir.actions.server">
@ -130,8 +128,8 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="priority">2</field> <field name="priority">2</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Sales Orders" fonts="bold:needaction_pending==True" colors="grey:state=='cancel';blue:state in ('waiting_date','manual');red:state in ('invoice_except','shipping_except')"> <tree string="Sales Orders" fonts="bold:message_unread==True" colors="grey:state=='cancel';blue:state in ('waiting_date','manual');red:state in ('invoice_except','shipping_except')">
<field name="needaction_pending" invisible="1"/> <field name="message_unread" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="date_order"/> <field name="date_order"/>
<field name="partner_id"/> <field name="partner_id"/>
@ -152,18 +150,21 @@
<span groups="base.group_user"> <span groups="base.group_user">
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/> <button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/>
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception"/> <button name="invoice_corrected" states="invoice_except" string="Ignore Exception"/>
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft,sent"/> <button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight"/>
<button name="print_quotation" string="Send by Post" type="object" states="draft,sent"/> <button name="action_quotation_send" string="Send by Mail" type="object" states="sent"/>
<button name="action_button_confirm" states="draft" string="Confirm" type="object" class="oe_highlight"/> <button name="print_quotation" string="Send by Post" type="object" states="draft" class="oe_highlight"/>
<button name="print_quotation" string="Send by Post" type="object" states="sent"/>
<button name="action_button_confirm" states="draft" string="Confirm" type="object"/>
<button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/> <button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/>
<button name="action_view_invoice" string="Open Invoice" type="object" class="oe_highlight"
attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True)]}"/> <button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
type="action" states="manual" class="oe_highlight"/>
<button name="cancel" states="draft,sent" string="Cancel"/> <button name="cancel" states="draft,sent" string="Cancel"/>
<button name="action_cancel" states="manual,progress" string="Cancel" type="object"/> <button name="action_cancel" states="manual,progress" string="Cancel" type="object"/>
<button name="invoice_cancel" states="invoice_except" string="Cancel"/> <button name="invoice_cancel" states="invoice_except" string="Cancel"/>
</span> </span>
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/> <field name="state" widget="statusbar" statusbar_visible="draft,sent,invoiced,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
</header> </header>
<sheet> <sheet>
<h1> <h1>
@ -180,7 +181,7 @@
</group> </group>
<group> <group>
<field name="date_order"/> <field name="date_order"/>
<field name="shop_id" on_change="onchange_shop_id(shop_id)" widget="selection"/> <field name="shop_id" invisible="1"/>
<field name="client_order_ref"/> <field name="client_order_ref"/>
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/> <field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/>
</group> </group>
@ -237,25 +238,26 @@
</div> </div>
</form> </form>
<tree string="Sales Order Lines" editable="bottom"> <tree string="Sales Order Lines" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="state" invisible="1"/> <field name="state" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="tax_id" invisible="1"/>
<field name="th_weight" invisible="1"/> <field name="th_weight" invisible="1"/>
<field name="product_id" <field name="product_id"
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
groups="base.group_user" groups="base.group_user"
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/> on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
<field name="name"/> <field name="name"/>
<field name="type" invisible="1"/>
<field name="product_uom_qty" <field name="product_uom_qty"
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/> on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/>
<field name="product_uom" <field name="product_uom"
on_change="product_uom_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, context)" on_change="product_uom_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, context)"
groups="product.group_uom" options='{"no_open": true}'/> groups="product.group_uom" options='{"no_open": true}'/>
<field name="product_uos_qty" groups="product.group_uos"/> <field name="product_uos_qty" groups="product.group_uos" invisible="1"/>
<field name="product_uos" string="UoS" groups="product.group_uos"/> <field name="product_uos" string="UoS" groups="product.group_uos" invisible="1"/>
<field name="discount" groups="sale.group_discount_per_so_line"/> <field name="tax_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','&lt;&gt;','purchase')]"/>
<field name="price_unit"/> <field name="price_unit"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="price_subtotal"/> <field name="price_subtotal"/>
</tree> </tree>
</field> </field>
@ -278,7 +280,7 @@
<page string="Other Information" groups="base.group_user"> <page string="Other Information" groups="base.group_user">
<group> <group>
<group name="logistics"> <group name="logistics">
<field name="order_policy"/> <field name="order_policy" readonly="1"/>
<field name="invoice_quantity" invisible="True"/> <field name="invoice_quantity" invisible="True"/>
</group> </group>
<group groups="base.group_user"> <group groups="base.group_user">
@ -319,13 +321,27 @@
</field> </field>
</record> </record>
<!-- inherited view to make the order lines list in the form non-editable
for the members of some usability groups -->
<record id="view_order_form_editable_list" model="ir.ui.view">
<field name="name">sale.order.form.editable.list</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="groups_id" eval="[(6, 0, [ref('product.group_uos'), ref('product.group_stock_packaging'), ref('sale.group_mrp_properties')])]"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree" position="attributes">
<attribute name="editable"/>
</xpath>
</field>
</record>
<record id="view_sales_order_filter" model="ir.ui.view"> <record id="view_sales_order_filter" model="ir.ui.view">
<field name="name">sale.order.list.select</field> <field name="name">sale.order.list.select</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Search Sales Order"> <search string="Search Sales Order">
<field name="name" string="Sales Order" filter_domain="['|',('name','ilike',self),('client_order_ref','ilike',self)]"/> <field name="name" string="Sales Order" filter_domain="['|',('name','ilike',self),('client_order_ref','ilike',self)]"/>
<filter icon="terp-mail-message-new" string="Inbox" help="Unread messages" name="needaction_pending" domain="[('needaction_pending','=',True)]"/> <filter icon="terp-mail-message-new" string="Inbox" help="Unread messages" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator/> <separator/>
<filter icon="terp-document-new" string="Quotations" name="draft" domain="[('state','in',('draft','sent'))]" help="Sales Order that haven't yet been confirmed"/> <filter icon="terp-document-new" string="Quotations" name="draft" domain="[('state','in',('draft','sent'))]" help="Sales Order that haven't yet been confirmed"/>
<filter icon="terp-check" string="Sales" name="sales" domain="[('state','in',('manual','progress'))]"/> <filter icon="terp-check" string="Sales" name="sales" domain="[('state','in',('manual','progress'))]"/>

View File

@ -39,7 +39,7 @@
<field name="name">done</field> <field name="name">done</field>
<field name="flow_stop">True</field> <field name="flow_stop">True</field>
<field name="kind">function</field> <field name="kind">function</field>
<field name="action">write({'state':'done'})</field> <field name="action">action_done()</field>
<field name="join_mode">AND</field> <field name="join_mode">AND</field>
</record> </record>
@ -135,10 +135,10 @@
<field name="signal">cancel</field> <field name="signal">cancel</field>
</record> </record>
<record id="trans_wait_invoice_invoice" model="workflow.transition"> <record id="trans_wait_invoice_invoice_manual" model="workflow.transition">
<field name="act_from" ref="act_wait_invoice"/> <field name="act_from" ref="act_wait_invoice"/>
<field name="act_to" ref="act_invoice"/> <field name="act_to" ref="act_invoice"/>
<field name="condition">(order_policy=='prepaid')</field> <field name="signal">manual_invoice</field>
</record> </record>
<record id="trans_invoice_invoice_end" model="workflow.transition"> <record id="trans_invoice_invoice_end" model="workflow.transition">
@ -146,6 +146,7 @@
<field name="act_to" ref="act_invoice_end"/> <field name="act_to" ref="act_invoice_end"/>
<field name="signal">subflow.paid</field> <field name="signal">subflow.paid</field>
</record> </record>
<record id="trans_invoice_invoice_except" model="workflow.transition"> <record id="trans_invoice_invoice_except" model="workflow.transition">
<field name="act_from" ref="act_invoice"/> <field name="act_from" ref="act_invoice"/>
<field name="act_to" ref="act_invoice_except"/> <field name="act_to" ref="act_invoice_except"/>

View File

@ -1,6 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_shop,sale.shop,model_sale_shop,base.group_user,1,0,0,0
access_sale_order,sale.order,model_sale_order,base.group_sale_salesman,1,1,1,0 access_sale_order,sale.order,model_sale_order,base.group_sale_salesman,1,1,1,0
access_sale_shop,sale.shop,model_sale_shop,base.group_user,1,0,0,0
access_sale_order_line,sale.order.line,model_sale_order_line,base.group_sale_salesman,1,1,1,1 access_sale_order_line,sale.order.line,model_sale_order_line,base.group_sale_salesman,1,1,1,1
access_sale_order_line_accountant,sale.order.line accountant,model_sale_order_line,account.group_account_user,1,1,0,0 access_sale_order_line_accountant,sale.order.line accountant,model_sale_order_line,account.group_account_user,1,1,0,0
access_account_invoice_tax_salesman,account_invoice_tax salesman,account.model_account_invoice_tax,base.group_sale_salesman,1,1,1,0 access_account_invoice_tax_salesman,account_invoice_tax salesman,account.model_account_invoice_tax,base.group_sale_salesman,1,1,1,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
access_sale_shop sale.shop model_sale_shop base.group_user 1 0 0 0
2 access_sale_order sale.order model_sale_order base.group_sale_salesman 1 1 1 0
3 access_sale_shop sale.shop model_sale_shop base.group_user 1 0 0 0
4 access_sale_order_line sale.order.line model_sale_order_line base.group_sale_salesman 1 1 1 1
5 access_sale_order_line_accountant sale.order.line accountant model_sale_order_line account.group_account_user 1 1 0 0
6 access_account_invoice_tax_salesman account_invoice_tax salesman account.model_account_invoice_tax base.group_sale_salesman 1 1 1 0

View File

@ -51,7 +51,7 @@
<record model="ir.ui.menu" id="base.menu_base_config"> <record model="ir.ui.menu" id="base.menu_base_config">
<field eval="[(4, ref('base.group_sale_manager'))]" name="groups_id"/> <field eval="[(4, ref('base.group_sale_manager'))]" name="groups_id"/>
</record> </record>
<!-- Multi - Company Rules --> <!-- Multi - Company Rules -->
<record model="ir.rule" id="sale_order_comp_rule"> <record model="ir.rule" id="sale_order_comp_rule">
@ -73,7 +73,7 @@
<field name="model_id" ref="model_sale_shop"/> <field name="model_id" ref="model_sale_shop"/>
<field name="global" eval="True"/> <field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record> </record>
<!-- Multi - Salesmen sales order assignation rules --> <!-- Multi - Salesmen sales order assignation rules -->

View File

@ -1,19 +1,31 @@
- -
In order to test the cancel sale order. In order to test the cancel sale order.
First I confirm order. I confirm order.
- -
!workflow {model: sale.order, action: order_confirm, ref: sale_order_8} !workflow {model: sale.order, action: order_confirm, ref: sale_order_8}
- -
I check state of order in 'Sale Order'. I check state of order in 'Sale Order'.
- -
!assert {model: sale.order, id: sale_order_8, string: Sale order should be In Progress state}: !assert {model: sale.order, id: sale_order_8, string: Sale order should be In Progress state}:
- state == 'progress' - state == 'manual'
- -
I check that Invoice should be created. I check that Invoice should not be created.
- -
!python {model: sale.order}: | !python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale_order_8")) sale_order = self.browse(cr, uid, ref("sale_order_8"))
assert len(sale_order.invoice_ids) == True, "Invoice should be created." assert len(sale_order.invoice_ids) == False, "Invoice should not be created."
-
I create advance invoice.
-
!python {model: sale.advance.payment.inv}: |
ctx = context.copy()
ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_8")], "active_id":ref("sale.sale_order_8")})
order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale_order_line_20"), context=context)
pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty})
self.create_invoices(cr, uid, [pay_id], context=ctx)
- -
To cancel the sale order from Invoice Exception, I have to cancel the invoice of sale order. To cancel the sale order from Invoice Exception, I have to cancel the invoice of sale order.
- -

View File

@ -10,5 +10,5 @@
I make duplicate order and delete. I make duplicate order and delete.
- -
!python {model: sale.order}: | !python {model: sale.order}: |
id = self.copy(cr, uid, ref('sale_order_1')) id = self.copy(cr, uid, ref('sale_order_2'))
self.unlink(cr, uid, [id]) self.unlink(cr, uid, [id])

View File

@ -11,13 +11,13 @@
product_uom_qty: 1.0 product_uom_qty: 1.0
product_uom: 1 product_uom: 1
price_unit: 150.0 price_unit: 150.0
name: 'Basic pc' name: 'PC Assemble SC234'
order_line: order_line:
- product_id: product.product_product_5 - product_id: product.product_product_5
product_uom_qty: 10.0 product_uom_qty: 10.0
product_uom: 1 product_uom: 1
price_unit: 200.0 price_unit: 200.0
name: 'Medium pc' name: 'PC Assemble + Custom (PC on Demand)'
- -
I confirm the sale order I confirm the sale order
- -
@ -72,10 +72,10 @@
"__model": "purchase.order.line", "__model": "purchase.order.line",
"__import_module": "sale", "__import_module": "sale",
"__import_model": "sale.order.line", "__import_model": "sale.order.line",
"name": "Basic PC", "name": "PC Assemble SC234",
"date_planned": "2011-09-30", "date_planned": "2011-09-30",
"price_unit": 150.0, "price_unit": 150.0,
"product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_3", "[PC1] Basic PC"], "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_3", "[PCSC234] PC Assemble SC234"],
"product_qty": 1.0, "product_qty": 1.0,
"product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"], "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"],
}, },
@ -85,10 +85,10 @@
"__model": "purchase.order.line", "__model": "purchase.order.line",
"__import_module": "sale", "__import_module": "sale",
"__import_model": "sale.order.line", "__import_model": "sale.order.line",
"name": "Medium PC", "name": "PC on Demand",
"date_planned": "2011-09-15", "date_planned": "2011-09-15",
"price_unit": 100.0, "price_unit": 100.0,
"product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_5", "[PC3] Medium PC"], "product_id": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_product_5", "[PC-DEM] PC on Demand"],
"product_qty": 2.0, "product_qty": 2.0,
"product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"], "product_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"],
}], }],
@ -107,13 +107,15 @@
assert order_new.amount_untaxed == 350, "Untaxed amount is wrong" assert order_new.amount_untaxed == 350, "Untaxed amount is wrong"
assert len(order_new.order_line) == 2, "Sale order lines mismatch" assert len(order_new.order_line) == 2, "Sale order lines mismatch"
for sale_line in order_new.order_line: for sale_line in order_new.order_line:
if sale_line.name == 'Basic PC':
# assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,) if sale_line.name == 'PC Assemble SC234':
#assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,)
assert sale_line.product_uom.name == "Unit" , "uom is not same" assert sale_line.product_uom.name == "Unit" , "uom is not same"
assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,) assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,)
assert sale_line.product_uom_qty == 1 , "product qty is not same" assert sale_line.product_uom_qty == 1 , "product qty is not same"
elif sale_line.name == 'Medium PC':
# assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,) elif sale_line.name == 'PC on Demand':
#assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,)
assert sale_line.product_uom.name == "Unit" , "uom is not same" assert sale_line.product_uom.name == "Unit" , "uom is not same"
assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,) assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,)
assert sale_line.product_uom_qty == 2 , "product qty is not same" assert sale_line.product_uom_qty == 2 , "product qty is not same"

View File

@ -1,27 +1,27 @@
- -
I confirm the Quotation with "Deliver & invoice on demand". I confirm the Quotation with "Deliver & invoice on demand".
- -
!workflow {model: sale.order, action: order_confirm, ref: sale.sale_order_7} !workflow {model: sale.order, action: order_confirm, ref: sale_order_7}
- -
I check that Invoice should not created. I check that Invoice should not created.
- -
!python {model: sale.order}: | !python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale.sale_order_7")) sale_order = self.browse(cr, uid, ref("sale_order_7"))
assert len(sale_order.invoice_ids) == False, "Invoice should not created." assert len(sale_order.invoice_ids) == False, "Invoice should not created."
- -
I create advance invoice. I create advance invoice.
- -
!python {model: sale.advance.payment.inv}: | !python {model: sale.advance.payment.inv}: |
ctx = context.copy() ctx = context.copy()
ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.sale_order_7")], "active_id":ref("sale.sale_order_7")}) ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_7")], "active_id":ref("sale_order_7")})
order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale.sale_order_line_16"), context=context) order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale_order_line_16"), context=context)
pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty}) pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty})
self.create_invoices(cr, uid, [pay_id], context=ctx) self.create_invoices(cr, uid, [pay_id], context=ctx)
- -
I check Invoice which made advance I check Invoice which made advance
- -
!python {model: sale.order}: | !python {model: sale.order}: |
order = self.browse(cr, uid, ref('sale.sale_order_7')) order = self.browse(cr, uid, ref('sale_order_7'))
assert order.invoice_ids, "Invoice should be created after make advance invoice." assert order.invoice_ids, "Invoice should be created after make advance invoice."
- -
I create manual Invoice for order. I create manual Invoice for order.
@ -31,7 +31,7 @@
- -
!python {model: sale.make.invoice}: | !python {model: sale.make.invoice}: |
ctx = context.copy() ctx = context.copy()
ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.sale_order_7")], "active_id":ref("sale.sale_order_7")}) ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_7")], "active_id":ref("sale_order_7")})
self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context) self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context)
- -
@ -39,13 +39,13 @@
- -
!python {model: sale.order.line.make.invoice}: | !python {model: sale.order.line.make.invoice}: |
ctx = context.copy() ctx = context.copy()
ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("sale.sale_order_line_17")], "active_id":ref("sale.sale_order_line_17")}) ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("sale_order_line_17")], "active_id":ref("sale_order_line_17")})
self.make_invoices(cr, uid, [], context=ctx) self.make_invoices(cr, uid, [], context=ctx)
- -
I check Invoice which made from sale order line. I check Invoice which made from sale order line.
- -
!python {model: sale.order.line}: | !python {model: sale.order.line}: |
line = self.browse(cr, uid, ref('sale.sale_order_line_17')) line = self.browse(cr, uid, ref('sale_order_line_17'))
assert line.invoiced, "Line is not invoiced." assert line.invoiced, "Line is not invoiced."
assert line.invoice_lines, "Invoice line should be created." assert line.invoice_lines, "Invoice line should be created."
- -
@ -56,7 +56,7 @@
- -
!python {model: sale.make.invoice}: | !python {model: sale.make.invoice}: |
ctx = context.copy() ctx = context.copy()
ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.sale_order_7")], "active_id":ref("sale.sale_order_7")}) ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_7")], "active_id":ref("sale_order_7")})
self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context) self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context)
- -
I open the Invoice. I open the Invoice.
@ -64,7 +64,7 @@
!python {model: sale.order}: | !python {model: sale.order}: |
import netsvc import netsvc
wf_service = netsvc.LocalService("workflow") wf_service = netsvc.LocalService("workflow")
so = self.browse(cr, uid, ref("sale.sale_order_7")) so = self.browse(cr, uid, ref("sale_order_7"))
for invoice in so.invoice_ids: for invoice in so.invoice_ids:
wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr) wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
- -
@ -72,29 +72,19 @@
- -
!python {model: account.invoice}: | !python {model: account.invoice}: |
sale_order = self.pool.get('sale.order') sale_order = self.pool.get('sale.order')
order = sale_order.browse(cr, uid, ref("sale.sale_order_7")) order = sale_order.browse(cr, uid, ref("sale_order_7"))
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1) journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
for invoice in order.invoice_ids: for invoice in order.invoice_ids:
invoice.pay_and_reconcile( invoice.pay_and_reconcile(
invoice.amount_total, ref('account.cash'), ref('account.period_8'), invoice.amount_total, ref('account.cash'), ref('account.period_8'),
journal_ids[0], ref('account.cash'), journal_ids[0], ref('account.cash'),
ref('account.period_8'), journal_ids[0], ref('account.period_8'), journal_ids[0],
name='test') name='test')
- -
I check Invoice after do manual. I check Invoice after do manual.
- -
!python {model: sale.order}: | !python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale.sale_order_7")) sale_order = self.browse(cr, uid, ref("sale_order_7"))
assert sale_order.invoice_ids, "Invoice should be created." assert sale_order.invoice_ids, "Invoice should be created."
assert sale_order.invoiced, "Order is not invoiced." assert sale_order.invoiced, "Order is not invoiced."
assert sale_order.state == 'manual', 'Order should be in Manual.' assert sale_order.state == 'manual', 'Order should be in Manual.'
-
I set order policy "Deliver & invoice on demand" as default policy.
-
!record {model: sale.config.settings, id: sale_configuration_0}:
default_order_policy: 'manual'
-
!python {model: sale.config.settings}: |
self.execute(cr, uid, [ref("sale_configuration_0")], context=context)

View File

@ -19,5 +19,6 @@
# #
############################################################################## ##############################################################################
import sale_line_invoice import sale_line_invoice
import sale_make_invoice_advance
import sale_make_invoice
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -33,9 +33,8 @@ Using this module you will be able to link analytic accounts to sales orders.
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ['images/sale_order_analytic_account.jpeg', 'images/sales_order_line.jpeg'], 'images': ['images/sale_order_analytic_account.jpeg', 'images/sales_order_line.jpeg'],
'depends': ['sale', 'account_analytic_plans'], 'depends': ['sale', 'account_analytic_plans'],
'init_xml': [], 'data': ['sale_analytic_plans_view.xml'],
'update_xml': ['sale_analytic_plans_view.xml'], 'demo': [],
'demo_xml': [],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,
'certificate': '0066055860861', 'certificate': '0066055860861',

View File

@ -22,6 +22,11 @@
</field> </field>
</record> </record>
<!-- the presence of 'analytics_id' makes the order lines non-editable -->
<record id="sale.view_order_form_editable_list" model="ir.ui.view">
<field name="groups_id" eval="[(4, ref('analytic.group_analytic_accounting'))]"/>
</record>
<record model="ir.ui.view" id="view_order_line_form2_inherit"> <record model="ir.ui.view" id="view_order_line_form2_inherit">
<field name="name">sale.order.line.form2.inherit</field> <field name="name">sale.order.line.form2.inherit</field>
<field name="model">sale.order.line</field> <field name="model">sale.order.line</field>

View File

@ -38,14 +38,14 @@ modules.
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ['images/crm_statistics_dashboard.jpeg', 'images/opportunity_to_quote.jpeg'], 'images': ['images/crm_statistics_dashboard.jpeg', 'images/opportunity_to_quote.jpeg'],
'depends': ['sale_stock', 'crm'], 'depends': ['sale_stock', 'crm'],
'init_xml': [], 'data': [
'update_xml': ['wizard/crm_make_sale_view.xml', 'wizard/crm_make_sale_view.xml',
'sale_crm_view.xml', 'sale_crm_view.xml',
'process/sale_crm_process.xml', 'process/sale_crm_process.xml',
'security/sale_crm_security.xml', 'security/sale_crm_security.xml',
'security/ir.model.access.csv' 'security/ir.model.access.csv'
], ],
'demo_xml': [], 'demo': [],
'test': ['test/sale_crm.yml'], 'test': ['test/sale_crm.yml'],
'installable': True, 'installable': True,
'auto_install': True, 'auto_install': True,

View File

@ -106,7 +106,7 @@ class crm_make_sale(osv.osv_memory):
case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id}) case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
new_ids.append(new_id) new_ids.append(new_id)
message = _("Opportunity has been <b>converted</b> to the quotation <em>%s</em>.") % (sale_order.name) message = _("Opportunity has been <b>converted</b> to the quotation <em>%s</em>.") % (sale_order.name)
case.message_append_note(body=message) case.message_post(body=message)
if make.close: if make.close:
case_obj.case_close(cr, uid, data) case_obj.case_close(cr, uid, data)
if not new_ids: if not new_ids:

View File

@ -30,17 +30,19 @@ The sales journal modules allows you to categorise your sales and deliveries (pi
This module is very helpful for bigger companies that works by departments. This module is very helpful for bigger companies that works by departments.
You can use journal for different purposes, some examples: You can use journal for different purposes, some examples:
----------------------------------------------------------
* isolate sales of different departments * isolate sales of different departments
* journals for deliveries by truck or by UPS * journals for deliveries by truck or by UPS
Journals have a responsible and evolves between different status: Journals have a responsible and evolves between different status:
-----------------------------------------------------------------
* draft, open, cancel, done. * draft, open, cancel, done.
Batch operations can be processed on the different journals to confirm all sales Batch operations can be processed on the different journals to confirm all sales
at once, to validate or invoice packing. at once, to validate or invoice packing.
It also supports batch invoicing methods that can be configured by partners and It also supports batch invoicing methods that can be configured by partners and sales orders, examples:
sales orders, examples: -------------------------------------------------------------------------------------------------------
* daily invoicing * daily invoicing
* monthly invoicing * monthly invoicing
@ -50,12 +52,12 @@ Some statistics by journals are provided.
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ['images/invoice_type.jpeg'], 'images': ['images/invoice_type.jpeg'],
'depends': ['sale_stock'], 'depends': ['sale_stock'],
'init_xml': ['sale_journal_data.xml'], 'data': [
'update_xml': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'sale_journal_view.xml', 'sale_journal_view.xml',
'sale_journal_data.xml'
], ],
'demo_xml': ['sale_journal_demo.xml'], 'demo': ['sale_journal_demo.xml'],
'test': [ ], 'test': [ ],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,

View File

@ -19,25 +19,25 @@
############################################################################## ##############################################################################
{ {
"name": "Margins in Sales Orders", 'name': 'Margins in Sales Orders',
"version":"1.0", 'version':'1.0',
"category" : "Sales Management", 'category' : 'Sales Management',
"description": """ 'description': """
This module adds the 'Margin' on sales order. This module adds the 'Margin' on sales order.
============================================= =============================================
This gives the profitability by calculating the difference between the Unit This gives the profitability by calculating the difference between the Unit
Price and Cost Price. Price and Cost Price.
""", """,
"author":"OpenERP SA", 'author':'OpenERP SA',
"images":["images/sale_margin.jpeg"], 'images':['images/sale_margin.jpeg'],
"depends":["sale_stock"], 'depends':['sale_stock'],
"demo_xml":[], 'demo':[],
'test': ['test/sale_margin.yml'], 'test': ['test/sale_margin.yml'],
"update_xml":["security/ir.model.access.csv","sale_margin_view.xml"], 'data':['security/ir.model.access.csv','sale_margin_view.xml'],
"auto_install": False, 'auto_install': False,
"installable": True, 'installable': True,
"certificate" : "001165700015525701661", 'certificate' : '001165700015525701661',
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -9,7 +9,7 @@
invoice_quantity: order invoice_quantity: order
name: Test_SO011 name: Test_SO011
order_line: order_line:
- name: '[KEYA] Keyboard - AZERTY' - name: '[CARD] Graphics Card'
price_unit: 7.0 price_unit: 7.0
product_uom: product.product_uom_unit product_uom: product.product_uom_unit
product_uom_qty: 100.0 product_uom_qty: 100.0

View File

@ -35,12 +35,11 @@ from sales order. It adds sales name and sales Reference on production order.
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ['images/SO_to_MO.jpeg'], 'images': ['images/SO_to_MO.jpeg'],
'depends': ['mrp', 'sale_stock'], 'depends': ['mrp', 'sale_stock'],
'init_xml': [], 'data': [
'update_xml': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'sale_mrp_view.xml', 'sale_mrp_view.xml',
], ],
'demo_xml': [], 'demo': [],
'test':['test/sale_mrp.yml'], 'test':['test/sale_mrp.yml'],
'installable': True, 'installable': True,
'auto_install': True, 'auto_install': True,

View File

@ -29,22 +29,17 @@ Add additional date information to the sales order.
=================================================== ===================================================
You can add the following additional dates to a sale order: You can add the following additional dates to a sale order:
-----------------------------------------------------------
* Requested Date * Requested Date
* Commitment Date * Commitment Date
* Effective Date * Effective Date
""", """,
'author': 'OpenERP SA', 'author': 'OpenERP SA',
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': ["images/sale_order_dates.jpeg"], 'images': ['images/sale_order_dates.jpeg'],
'depends': ["sale_stock"], 'depends': ['sale_stock'],
'init_xml': [ 'data': ['sale_order_dates_view.xml'],
], 'demo': [],
'update_xml': [
'sale_order_dates_view.xml',
],
'demo_xml': [
],
'test': [], 'test': [],
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,

View File

@ -20,10 +20,11 @@
############################################################################## ##############################################################################
{ {
'name': 'Sale To Stock', 'name': 'Sales and Warehouse Management',
'version': '1.0', 'version': '1.0',
'category': 'Hidden', 'category': 'Hidden',
'description': """ 'description': """
'summary': 'Quotation, Sale Orders, Delivery & Invoicing Control',
This Module manage quotations and sales orders. This Module manage quotations and sales orders.
=========================================================================== ===========================================================================
@ -61,11 +62,9 @@ Dashboard for Sales Manager that includes:
'author': 'OpenERP SA', 'author': 'OpenERP SA',
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'images': [], 'images': [],
'depends': ['sale', 'procurement'], 'depends': ['sale', 'stock', 'procurement'],
'init_xml': [], 'init_xml': [],
'update_xml': ['wizard/sale_make_invoice_advance.xml', 'update_xml': ['security/sale_stock_security.xml',
'wizard/sale_make_invoice.xml',
'security/sale_stock_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'company_view.xml', 'company_view.xml',
'sale_stock_view.xml', 'sale_stock_view.xml',
@ -73,15 +72,16 @@ Dashboard for Sales Manager that includes:
'res_config_view.xml', 'res_config_view.xml',
'report/sale_report_view.xml', 'report/sale_report_view.xml',
'process/sale_stock_process.xml', 'process/sale_stock_process.xml',
], ],
'data': ['sale_stock_data.xml'], 'data': ['sale_stock_data.xml'],
'demo_xml': ['sale_stock_demo.xml'], 'demo_xml': ['sale_stock_demo.xml'],
'test': ['test/cancel_order_sale_stock.yml', 'test': ['test/cancel_order_sale_stock.yml',
'test/picking_order_policy.yml', 'test/picking_order_policy.yml',
'test/manual_order_policy.yml' 'test/prepaid_order_policy.yml',
], ],
'installable': True, 'installable': True,
'auto_install': True, 'auto_install': True,
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -26,6 +26,9 @@ from tools.translate import _
class sale_configuration(osv.osv_memory): class sale_configuration(osv.osv_memory):
_inherit = 'sale.config.settings' _inherit = 'sale.config.settings'
_columns = { _columns = {
'group_invoice_so_lines': fields.boolean('generate invoices based on the sale order',
implied_group='sale.group_invoice_so_lines',
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
'group_invoice_deli_orders': fields.boolean('generate invoices after and based on delivery orders', 'group_invoice_deli_orders': fields.boolean('generate invoices after and based on delivery orders',
implied_group='sale_stock.group_invoice_deli_orders', implied_group='sale_stock.group_invoice_deli_orders',
help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."), help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
@ -52,8 +55,11 @@ class sale_configuration(osv.osv_memory):
help="This allows to configure and use multiple shops."), help="This allows to configure and use multiple shops."),
'module_project_timesheet': fields.boolean("Project Timesheet"), 'module_project_timesheet': fields.boolean("Project Timesheet"),
'module_project_mrp': fields.boolean("Project MRP"), 'module_project_mrp': fields.boolean("Project MRP"),
}
}
_defaults = {
'default_order_policy': 'manual',
}
def default_get(self, cr, uid, fields, context=None): def default_get(self, cr, uid, fields, context=None):
res = super(sale_configuration, self).default_get(cr, uid, fields, context) res = super(sale_configuration, self).default_get(cr, uid, fields, context)

View File

@ -9,7 +9,11 @@
<field name="inherit_id" ref="sale.view_sales_config"/> <field name="inherit_id" ref="sale.view_sales_config"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<data> <data>
<xpath expr="//div[@name='invoice_so_lines']" position="after"> <xpath expr="//div[@name='timesheet']" position="before">
<div>
<field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)" class="oe_inline"/>
<label for="group_invoice_so_lines"/>
</div>
<div> <div>
<field name="group_invoice_deli_orders" class="oe_inline" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)"/> <field name="group_invoice_deli_orders" class="oe_inline" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)"/>
<label for="group_invoice_deli_orders"/> <label for="group_invoice_deli_orders"/>
@ -22,7 +26,11 @@
<xpath expr="//label[@string='Default Options']" position="replace"> <xpath expr="//label[@string='Default Options']" position="replace">
<label for="id" string="Default Options" attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False),('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False),('task_work','=',False), ('module_account_analytic_analysis','=',False)]}"/> <label for="id" string="Default Options" attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False),('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False),('task_work','=',False), ('module_account_analytic_analysis','=',False)]}"/>
</xpath> </xpath>
<xpath expr="//div[@name='default_order_policy']" position="after"> <xpath expr="//div[@name='time_unit']" position="before">
<div attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False)],'required': ['|',('group_invoice_so_lines','=',True),('group_invoice_deli_orders','=',True)]}">
<label for="default_order_policy"/>
<field name="default_order_policy" class="oe_inline"/>
</div>
<div attrs="{'invisible':[('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False)]}"> <div attrs="{'invisible':[('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False)]}">
<field name="module_delivery" class="oe_inline"/> <field name="module_delivery" class="oe_inline"/>
<label for="module_delivery"/> <label for="module_delivery"/>
@ -44,24 +52,15 @@
<label for="group_mrp_properties"/> <label for="group_mrp_properties"/>
</div> </div>
</div> </div>
<xpath expr="//div[@name='module_sale_margin']" position="before">
<xpath expr="//div[@name='Sale Features']/div[@name='module_sale_margin']" position="before">
<div> <div>
<field name="group_multiple_shops" class="oe_inline"/> <field name="group_multiple_shops" class="oe_inline"/>
<label for="group_multiple_shops"/> <label for="group_multiple_shops"/>
</div> </div>
</xpath> </xpath>
<field name="group_invoice_so_lines" position="replace"> <field name="group_invoice_so_lines" position="replace">
<field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)" class="oe_inline"/> <field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)" class="oe_inline"/>
</field> </field>
<xpath expr="//div[@name='default_order_policy']" position="replace">
<div attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False)],'required': ['|',('group_invoice_so_lines','=',True),('group_invoice_deli_orders','=',True)]}">
<label for="default_order_policy"/>
<field name="default_order_policy" class="oe_inline"/>
</div>
</xpath>
<xpath expr="//div[@name='time_unit']" position="replace"> <xpath expr="//div[@name='time_unit']" position="replace">
<div attrs="{'invisible': [('task_work','=',False), ('module_account_analytic_analysis','=',False)],'required': ['|', ('task_work','=',True), ('module_account_analytic_analysis','=',True)]}"> <div attrs="{'invisible': [('task_work','=',False), ('module_account_analytic_analysis','=',False)],'required': ['|', ('task_work','=',True), ('module_account_analytic_analysis','=',True)]}">
<label for="time_unit"/> <label for="time_unit"/>

View File

@ -28,9 +28,11 @@ from tools.translate import _
class sale_shop(osv.osv): class sale_shop(osv.osv):
_inherit = "sale.shop" _inherit = "sale.shop"
_columns = { _columns = {
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
} }
sale_shop()
class sale_order(osv.osv): class sale_order(osv.osv):
_inherit = "sale.order" _inherit = "sale.order"
@ -110,7 +112,7 @@ class sale_order(osv.osv):
return res return res
_columns = { _columns = {
'state': fields.selection([ 'state': fields.selection([
('draft', 'Draft Quotation'), ('draft', 'Draft Quotation'),
('sent', 'Quotation Sent'), ('sent', 'Quotation Sent'),
('cancel', 'Cancelled'), ('cancel', 'Cancelled'),
@ -142,7 +144,7 @@ class sale_order(osv.osv):
'picked_rate': fields.function(_picked_rate, string='Picked', type='float'), 'picked_rate': fields.function(_picked_rate, string='Picked', type='float'),
'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on', 'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on',
help="The sale order will automatically create the invoice proposition (draft invoice).\ help="The sale order will automatically create the invoice proposition (draft invoice).\
You have to choose if you want your invoice based on ordered ", required=True, readonly=True, states={'draft': [('readonly', False)]}), You have to choose if you want your invoice based on ordered ", required=True, readonly=True, states={'draft': [('readonly', False)]}),
} }
_defaults = { _defaults = {
'picking_policy': 'direct', 'picking_policy': 'direct',
@ -162,7 +164,16 @@ class sale_order(osv.osv):
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
def onchange_shop_id(self, cr, uid, ids, shop_id):
v = {}
if shop_id:
shop = self.pool.get('sale.shop').browse(cr, uid, shop_id)
v['project_id'] = shop.project_id.id
# Que faire si le client a une pricelist a lui ?
if shop.pricelist_id.id:
v['pricelist_id'] = shop.pricelist_id.id
return {'value': v}
def action_view_delivery(self, cr, uid, ids, context=None): def action_view_delivery(self, cr, uid, ids, context=None):
''' '''
@ -210,42 +221,11 @@ class sale_order(osv.osv):
self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line]) self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
self.confirm_send_note(cr, uid, ids, context) self.confirm_send_note(cr, uid, ids, context)
return True return True
def manual_invoice(self, cr, uid, ids, context=None):
""" create invoices for the given sale orders (ids), and open the form
view of one of the newly created invoices
"""
mod_obj = self.pool.get('ir.model.data')
wf_service = netsvc.LocalService("workflow")
# create invoices through the sale orders' workflow
inv_ids0 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
for id in ids:
wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
inv_ids1 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
# determine newly created invoices
new_inv_ids = list(inv_ids1 - inv_ids0)
res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
res_id = res and res[1] or False,
return {
'name': _('Customer Invoices'),
'view_type': 'form',
'view_mode': 'form',
'view_id': [res_id],
'res_model': 'account.invoice',
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
'nodestroy': True,
'target': 'current',
'res_id': new_inv_ids and new_inv_ids[0] or False,
}
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None): def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
res = super(sale_order,self).action_invoice_create( cr, uid, ids, grouped=grouped, states=states, date_inv = date_inv, context=context)
picking_obj = self.pool.get('stock.picking') picking_obj = self.pool.get('stock.picking')
res = super(sale_order,self).action_invoice_create( cr, uid, ids, grouped=grouped, states=states, date_inv = date_inv, context=context)
if context is None: if context is None:
context = {} context = {}
# If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the # If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
@ -518,9 +498,6 @@ class sale_order(osv.osv):
def get_needaction_user_ids(self, cr, uid, ids, context=None): def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = super(sale_order, self).get_needaction_user_ids(cr, uid, ids, context=context) result = super(sale_order, self).get_needaction_user_ids(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if (obj.state == 'manual' or obj.state == 'progress'):
result[obj.id].append(obj.user_id.id)
return result return result
def delivery_send_note(self, cr, uid, ids, picking_id, context=None): def delivery_send_note(self, cr, uid, ids, picking_id, context=None):
@ -550,14 +527,13 @@ class sale_order_line(osv.osv):
_inherit = 'sale.order.line' _inherit = 'sale.order.line'
_columns = { _columns = {
'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}), 'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}),
'procurement_id': fields.many2one('procurement.order', 'Procurement'),
'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."), help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}), 'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}),
'procurement_id': fields.many2one('procurement.order', 'Procurement'),
'product_packaging': fields.many2one('product.packaging', 'Packaging'), 'product_packaging': fields.many2one('product.packaging', 'Packaging'),
'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True), 'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'), 'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'),
} }
_defaults = { _defaults = {
'delay': 0.0, 'delay': 0.0,
@ -567,23 +543,33 @@ class sale_order_line(osv.osv):
def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None): def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
res = super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context) res = super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context)
def _get_line_qty(line): def _get_line_qty(line):
if not (line.order_id.invoice_quantity=='order') or line.procurement_id: if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
if line.product_uos:
return line.product_uos_qty or 0.0
return line.product_uom_qty
else:
return self.pool.get('procurement.order').quantity_get(cr, uid, return self.pool.get('procurement.order').quantity_get(cr, uid,
line.procurement_id.id, context=context) line.procurement_id.id, context=context)
def _get_line_uom(line): def _get_line_uom(line):
if not (line.order_id.invoice_quantity=='order') or line.procurement_id: if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
if line.product_uos:
return line.product_uos.id
return line.product_uom.id
else:
return self.pool.get('procurement.order').uom_get(cr, uid, return self.pool.get('procurement.order').uom_get(cr, uid,
line.procurement_id.id, context=context) line.procurement_id.id, context=context)
uosqty = _get_line_qty(line)
uos_id = _get_line_uom(line) if not line.invoiced:
pu = 0.0 uosqty = _get_line_qty(line)
if uosqty: uos_id = _get_line_uom(line)
pu = 0.0
if uosqty:
pu = round(line.price_unit * line.product_uom_qty / uosqty, pu = round(line.price_unit * line.product_uom_qty / uosqty,
self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price')) self.pool.get('decimal.precision').precision_get(cr, uid, 'Product Price'))
res.update({'price_unit': pu, 'quantity': uosqty,'uos_id': uos_id}) res.update({'price_unit': pu, 'quantity': uosqty, 'uos_id': uos_id})
return res return res
def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
@ -644,14 +630,14 @@ class sale_order_line(osv.osv):
res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty, res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty,
uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id, uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)
if not product: if not product:
return {'value': {'th_weight': 0, 'product_packaging': False, return {'value': {'th_weight': 0, 'product_packaging': False,
'product_uos_qty': qty}, 'domain': {'product_uom': [], 'product_uos_qty': qty}, 'domain': {'product_uom': [],
'product_uos': []}} 'product_uos': []}}
res = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context) res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
result = res.get('value', {}) result = res_packing.get('value', {})
warning_msgs = res.get('warning') and res['warning']['message'] or '' warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
product_obj = product_obj.browse(cr, uid, product, context=context) product_obj = product_obj.browse(cr, uid, product, context=context)
uom2 = False uom2 = False
if uom: if uom:
@ -671,7 +657,10 @@ class sale_order_line(osv.osv):
warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n" warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"
# get unit price # get unit price
if warning_msgs: if warning_msgs:
warning.update({'message': warning_msgs}) warning = {
'title': _('Configuration Error!'),
'message' : warning_msgs
}
res.update({'warning': warning}) res.update({'warning': warning})
return res return res
@ -683,4 +672,4 @@ class sale_order_line(osv.osv):
raise osv.except_osv( raise osv.except_osv(
_('Cannot cancel sales order line!'), _('Cannot cancel sales order line!'),
_('You must first cancel stock moves attached to this sales order line.')) _('You must first cancel stock moves attached to this sales order line.'))
return res return res

View File

@ -1,8 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data noupdate="1"> <data noupdate="1">
<!-- Resource: sale.shop -->
<record id="sale.sale_shop_1" model="sale.shop"> <record id="sale.sale_shop_1" model="sale.shop">
<field name="warehouse_id" ref="stock.warehouse0"/> <field name="warehouse_id" ref="stock.warehouse0"/>
<!-- Copy the name of any company. Without demo data this will yield
the main company name, which is correct. With demo data it will
be random, but it does not matter much -->
</record> </record>
</data> </data>
</openerp> </openerp>

View File

@ -1,35 +1,26 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data noupdate="1"> <data noupdate="1">
<record id="sale.sale_order_2" model="sale.order"> <record id="sale.sale_order_1" model="sale.order">
<field name="order_policy">manual</field> <field name="order_policy">prepaid</field>
</record> </record>
<record id="sale.sale_order_3" model="sale.order"> <record id="sale.sale_order_4" model="sale.order">
<field name="order_policy">manual</field> <field name="order_policy">prepaid</field>
</record> </record>
<record id="sale.sale_order_5" model="sale.order"> <record id="sale.sale_order_5" model="sale.order">
<field name="order_policy">picking</field> <field name="order_policy">picking</field>
</record> </record>
<record id="sale.sale_order_6" model="sale.order"> <record id="sale.sale_order_6" model="sale.order">
<field name="order_policy">picking</field> <field name="order_policy">picking</field>
</record> </record>
<record id="sale.sale_order_7" model="sale.order">
<field name="order_policy">manual</field>
</record>
<record id="sale.sale_order_8" model="sale.order">
<field name="order_policy">manual</field>
</record>
<!-- Confirm some Sale Orders--> <!-- Confirm some Sale Orders-->
<workflow action="order_confirm" model="sale.order" ref="sale.sale_order_1"/>
<workflow action="order_confirm" model="sale.order" ref="sale.sale_order_5"/> <workflow action="order_confirm" model="sale.order" ref="sale.sale_order_5"/>
<workflow action="order_confirm" model="sale.order" ref="sale.sale_order_7"/>
<record id="sale.sale_order_line_4" model="sale.order.line"> <record id="sale.sale_order_line_4" model="sale.order.line">
<field name="type">make_to_order</field> <field name="type">make_to_order</field>

View File

@ -2,19 +2,18 @@
<openerp> <openerp>
<data> <data>
<record id="view_shop_form_inherit" model="ir.ui.view"> <record id="view_sale_shop_form_inherit" model="ir.ui.view">
<field name="name">sale.shop.sale.stock</field> <field name="name">sale.shop.inherit.form</field>
<field name="model">sale.shop</field> <field name="model">sale.shop</field>
<field name="inherit_id" ref="sale.view_shop_form"/> <field name="inherit_id" ref="sale.view_shop_form"/>
<field name="type">form</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='shop']" position="before"> <xpath expr="//group[@name='shop']" position="before">
<label for="warehouse_id" class="oe_edit_only"/> <label for="warehouse_id" class="oe_edit_only"/>
<h2><field name="warehouse_id" required="1"/></h2> <h2><field name="warehouse_id" required="1"/></h2>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="view_shop_tree_inherit" model="ir.ui.view"> <record id="view_shop_tree_inherit" model="ir.ui.view">
<field name="name">sale.shop.sale.stock</field> <field name="name">sale.shop.sale.stock</field>
<field name="model">sale.shop</field> <field name="model">sale.shop</field>
@ -27,6 +26,7 @@
</field> </field>
</record> </record>
<menuitem action="sale.action_shop_form" id="menu_action_shop_form" parent="base.menu_base_config" sequence="35" groups="stock.group_locations"/>
<record id="view_order_tree_sale_stock_inherit" model="ir.ui.view"> <record id="view_order_tree_sale_stock_inherit" model="ir.ui.view">
<field name="name">sale.order.tree.sale.stock</field> <field name="name">sale.order.tree.sale.stock</field>
@ -47,27 +47,25 @@
<field name="type">form</field> <field name="type">form</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<data> <data>
<xpath expr="/form/header/span/button[@name='invoice_corrected']" position="after"> <xpath expr="//button[@name='invoice_corrected']" position="after">
<button name="ship_recreate" states="shipping_except" string="Recreate Delivery Order"/> <button name="ship_recreate" states="shipping_except" string="Recreate Delivery Order"/>
<button name="ship_corrected" states="shipping_except" string="Ignore Exception"/> <button name="ship_corrected" states="shipping_except" string="Ignore Exception"/>
</xpath> </xpath>
<xpath expr="/form/header/span/button[@name='action_view_invoice']" position="replace"> <xpath expr="//button[@name='action_button_confirm']" position="after">
<button name="action_view_invoice" string="Open Invoice" type="object" class="oe_highlight" <button name="action_view_invoice" string="Open Invoice" type="object" class="oe_highlight"
attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True),('order_policy','=','picking')]}"/> attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True),('order_policy','=','picking')]}"/>
</xpath> </xpath>
<xpath expr="/form/header/span/button[@name='action_view_invoice']" position="after"> <xpath expr="//button[@name='action_view_invoice']" position="after">
<button name="action_view_delivery" string="Open Delivery Order" type="object" class="oe_highlight" <button name="action_view_delivery" string="Open Delivery Order" type="object" class="oe_highlight"
attrs="{'invisible': ['|','|','|',('picking_ids','=',False),('picking_ids','=',[]), ('state', 'not in', ('progress','manual')),('shipped','=',True)]}"/> attrs="{'invisible': ['|','|','|',('picking_ids','=',False),('picking_ids','=',[]), ('state', 'not in', ('progress','manual')),('shipped','=',True)]}"/>
</xpath> </xpath>
<xpath expr="/form/header/span/button[@name='action_cancel']" position="after"> <xpath expr="//button[@name='action_cancel']" position="after">
<button name="ship_cancel" states="shipping_except" string="Cancel"/> <button name="ship_cancel" states="shipping_except" string="Cancel"/>
</xpath> </xpath>
<xpath expr="/form/header/span/button[@name='action_view_delivery']" position="after">
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice" class="oe_highlight" type="action" states="manual"/>
</xpath>
<field name="state" position="replace"> <field name="state" position="replace">
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/> <field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
</field> </field>
<field name="product_id" position="replace"> <field name="product_id" position="replace">
<field name="product_id" <field name="product_id"
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
@ -80,11 +78,11 @@
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, context)"/> on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, context)"/>
</field> </field>
<field name="shop_id" position="replace"> <field name="shop_id" position="replace">
<field name="shop_id" on_change="onchange_shop_id(shop_id)" widget="selection" groups="stock.group_locations"/> <field name="shop_id" on_change="onchange_shop_id(shop_id)" widget="selection" groups="stock.group_locations"/>
</field> </field>
<xpath expr="//page[@string='Other Information']/group/group/field[@name='invoiced']" position="after"> <field name='invoiced' position="after">
<field name="shipped"/> <field name="shipped"/>
</xpath> </field>
<field name="invoice_ids" position="after"> <field name="invoice_ids" position="after">
<separator string="Delivery Orders"/> <separator string="Delivery Orders"/>
<field name="picking_ids" context="{'default_type': 'out'}"> <field name="picking_ids" context="{'default_type': 'out'}">
@ -124,18 +122,17 @@
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/tree[@string='Sales Order Lines']/field[@name='th_weight']" position="after"> <xpath expr="//page[@string='Order Lines']/field[@name='order_line']/tree[@string='Sales Order Lines']/field[@name='th_weight']" position="after">
<field name="product_packaging" invisible="1"/> <field name="product_packaging" invisible="1"/>
</xpath> </xpath>
<xpath expr="//page[@string='Other Information']/group/group[@name='logistics']/field[@name='order_policy']" position="replace"> <field name='order_policy' position="replace">
<field name="order_policy" on_change="shipping_policy_change(order_policy)"/> <field name="order_policy" on_change="shipping_policy_change(order_policy)"/>
</xpath> <field name="invoice_quantity" invisible="1"/>
<xpath expr="//page[@string='Other Information']/group/group[@name='logistics']/field[@name='order_policy']" position="before"> </field>
<field name='order_policy' position="before">
<field name="incoterm" widget="selection" groups="base.group_user"/> <field name="incoterm" widget="selection" groups="base.group_user"/>
<field name="picking_policy" required="True"/> <field name="picking_policy" required="True"/>
</xpath> </field>
</data> </data>
</field> </field>
</record> </record>
<menuitem action="sale.action_shop_form" id="sale.menu_action_shop_form" parent="base.menu_base_config" sequence="35" groups="stock.group_locations"/>
</data> </data>
</openerp> </openerp>

View File

@ -53,17 +53,16 @@
<field name="act_to" ref="act_wait_ship"/> <field name="act_to" ref="act_wait_ship"/>
</record> </record>
<record id="trans_router_wait_invoice_shipping" model="workflow.transition"> <record id="trans_router_wait_invoice_shipping" model="workflow.transition">
<field name="act_from" ref="sale.act_wait_invoice"/> <field name="act_from" ref="sale.act_wait_invoice"/>
<field name="act_to" ref="sale.act_invoice_end"/> <field name="act_to" ref="sale.act_invoice_end"/>
<field name="condition">(order_policy=='picking')</field> <field name="condition">(order_policy=='picking')</field>
</record> </record>
<record id="trans_wait_invoice_invoice_manual" model="workflow.transition"> <record id="trans_wait_invoice_invoice" model="workflow.transition">
<field name="act_from" ref="sale.act_wait_invoice"/> <field name="act_from" ref="sale.act_wait_invoice"/>
<field name="act_to" ref="sale.act_invoice"/> <field name="act_to" ref="sale.act_invoice"/>
<field name="signal">manual_invoice</field> <field name="condition">(order_policy=='prepaid')</field>
</record> </record>
<record id="trans_wait_ship_cancel3" model="workflow.transition"> <record id="trans_wait_ship_cancel3" model="workflow.transition">

View File

@ -1,10 +1,12 @@
- -
Now I confirm the Quotation with "Pay before delivery" policy. Now I confirm the Quotation with "Pay before delivery" policy.
- -
!workflow {model: sale.order, action: order_confirm, ref: sale_order_4} !workflow {model: sale.order, action: order_confirm, ref: sale.sale_order_4}
- -
I check that delivery order should not created before invoice is paid. I check that delivery order should not created before invoice is paid.
- -
!python {model: sale.order}: | !python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale_order_4")) sale_order = self.browse(cr, uid, ref("sale.sale_order_4"))
assert len(sale_order.picking_ids) == False, "Delivery order should not created before invoice."
assert sale_order.invoice_ids, "Invoice should be created." assert sale_order.invoice_ids, "Invoice should be created."

View File

@ -22,6 +22,9 @@
attrs="{'invisible': [('advance_payment_method', '!=', 'percentage')]}"/> attrs="{'invisible': [('advance_payment_method', '!=', 'percentage')]}"/>
</div> </div>
</group> </group>
<div>
<b><label string="After clicking 'Show Lines to Invoice' button, select lines to invoice and make invoice from the 'More' button." attrs="{'invisible': [('advance_payment_method', '!=', 'lines')]}"/></b>
</div>
<footer> <footer>
<button name="create_invoices" string="Create Invoice" type="object" <button name="create_invoices" string="Create Invoice" type="object"
class="oe_highlight" class="oe_highlight"