[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",
"website" : "http://www.openerp.com",
"category" : "Hidden/Dependency",
"depends" : ["base","process", "product", "stock"],
"depends" : ["process", "product", "stock"],
"description": """
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
depending on the product's configuration.
""",
'init_xml': [],
'update_xml': [
'data': [
'security/ir.model.access.csv',
'security/procurement_security.xml',
'procurement_data.xml',
@ -55,13 +55,13 @@ depending on the product's configuration.
'procurement_view.xml',
'procurement_workflow.xml',
'process/procurement_process.xml',
"company_view.xml",
'company_view.xml',
'board_mrp_procurement_view.xml',
],
'demo_xml': ['stock_orderpoint.xml'],
'demo': ['stock_orderpoint.xml'],
'test': ['test/procurement.yml'],
'installable': True,
'auto_install': False,
'auto_install': True,
'certificate': '00954248826881074509',
'images': ['images/compute_schedulers.jpeg','images/config_companies_sched.jpeg', 'images/minimum_stock_rules.jpeg'],
}

View File

@ -23,15 +23,15 @@
'name': 'Sales Management',
'version': '1.0',
'category': 'Sales Management',
"sequence": 14,
"summary": "Quotations, Sale Orders, Invoicing",
'sequence': 14,
'summary': 'Quotations, Sale Orders, Invoicing',
'description': """
The base module to manage quotations and sales orders.
======================================================
Workflow with validation steps:
-------------------------------
* Quotation -> Sales order -> Invoice
* **Quotation** -> **Sales order** -> **Invoice**
Create Invoice:
---------------
@ -51,9 +51,11 @@ Dashboard for Sales Manager that includes:
'author': 'OpenERP SA',
'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'],
'depends': ['board', 'account_voucher'],
'init_xml': [],
'update_xml': ['wizard/sale_line_invoice.xml',
'depends': ['account_voucher'],
'data': [
'wizard/sale_make_invoice_advance.xml',
'wizard/sale_line_invoice.xml',
'wizard/sale_make_invoice.xml',
'security/sale_security.xml',
'security/ir.model.access.csv',
'sale_workflow.xml',
@ -68,10 +70,10 @@ Dashboard for Sales Manager that includes:
'edi/sale_order_action_data.xml',
'res_config_view.xml',
],
'demo_xml': ['sale_demo.xml'],
'demo': ['sale_demo.xml'],
'test': [
'test/sale_order_demo.yml',
'test/prepaid_order_policy.yml',
'test/manual_order_policy.yml',
'test/cancel_order.yml',
'test/delete_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.user_id as user_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,
s.state,
t.categ_id as categ_id,
@ -103,7 +103,7 @@ class sale_report(osv.osv):
s.partner_id,
s.user_id,
s.shop_id,
s.company_id,
s.company_id,
s.state,
s.pricelist_id,
s.project_id

View File

@ -27,9 +27,6 @@ class sale_configuration(osv.osv_memory):
_inherit = 'sale.config.settings'
_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',
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.
@ -40,11 +37,7 @@ class sale_configuration(osv.osv_memory):
(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.
It installs the account_analytic_analysis module."""),
'default_order_policy': fields.selection(
[('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'),
'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",
implied_group='product.group_sale_pricelist',
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.
This installs the module analytic_user_function."""),
'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):
@ -94,11 +89,9 @@ class sale_configuration(osv.osv_memory):
return ids and ids[0] or False
_defaults = {
'default_order_policy': 'manual',
'time_unit': _get_default_time_unit,
}
def set_sale_defaults(self, cr, uid, ids, context=None):
ir_model_data = self.pool.get('ir.model.data')
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:
user = self.pool.get('res.users').browse(cr, uid, uid, context)
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 {}
def onchange_task_work(self, cr, uid, ids, task_work, context=None):

View File

@ -11,23 +11,15 @@
<group>
<label for="id" string="Invoicing Process"/>
<div>
<div name="invoice_so_lines">
<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>
<div name="timesheet">
<field name="timesheet" class="oe_inline" on_change="onchange_timesheet(timesheet)"/>
<label for="timesheet"/>
</div>
</div>
</group>
<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 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)]}">
<label for="time_unit"/>
<field name="time_unit" domain="[('category_id.name','=','Working Time')]" class="oe_inline"/>
@ -53,6 +45,10 @@
<group>
<label for="id" string="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'>
<field name="module_sale_journal" class="oe_inline"/>
<label for="module_sale_journal"/>

View File

@ -47,7 +47,7 @@ sale_shop()
class sale_order(osv.osv):
_name = "sale.order"
_inherit = ['ir.needaction_mixin', 'mail.thread']
_inherit = ['mail.thread', 'ir.needaction_mixin']
_description = "Sales Order"
def copy(self, cr, uid, id, default=None, context=None):
@ -157,8 +157,9 @@ class sale_order(osv.osv):
_columns = {
'name': fields.char('Order Reference', size=64, required=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."),
'client_order_ref': fields.char('Customer Reference', size=64),
'state': fields.selection([
('draft', 'Draft Quotation'),
@ -166,6 +167,7 @@ class sale_order(osv.osv):
('cancel', 'Cancelled'),
('waiting_date', 'Waiting Schedule'),
('progress', 'Sale Order'),
('manual', 'Sale to Invoice'),
('invoice_except', 'Invoice Exception'),
('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),
@ -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_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([
('prepaid', 'Before Delivery'),
('manual', 'On Demand'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
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."""),
@ -217,7 +219,7 @@ class sale_order(osv.osv):
}
_defaults = {
'date_order': fields.date.context_today,
'order_policy': 'prepaid',
'order_policy': 'manual',
'state': 'draft',
'user_id': lambda obj, cr, uid, context: uid,
'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)
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={}):
if (not pricelist_id) or (not order_lines):
return {}
@ -317,7 +308,6 @@ class sale_order(osv.osv):
if not journal_ids:
raise osv.except_osv(_('Error!'),
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
invoice_vals = {
'name': order.client_order_ref or '',
'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,
'date_invoice': context.get('date_invoice', False),
'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
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
return invoice_vals
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)
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):
res = False
invoices = {}
@ -517,6 +538,7 @@ class sale_order(osv.osv):
#
if order.state == 'invoice_except':
self.write(cr, uid, [order.id], {'state': 'progress'}, context=context)
self.invoice_paid_send_note(cr, uid, [order.id], context=context)
return True
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):
if not o.order_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.confirm_send_note(cr, uid, ids, context)
return True
@ -591,37 +613,42 @@ class sale_order(osv.osv):
'context': ctx,
'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
# ------------------------------------------------
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)
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 needaction_domain_get(self, cr, uid, ids, context=None):
return [('state', '=', 'draft'), ('user_id','=',uid)]
def create_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=_("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):
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):
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)
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):
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):
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):
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()
# 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'])
return res
def _get_uom_id(self, cr, uid, *args):
try:
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.'),
'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'),
'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'
_defaults = {
@ -704,7 +730,7 @@ class sale_order_line(osv.osv):
(this is used for returning products including service)
:return: dict of values to create() the invoice line
"""
res = {}
def _get_line_qty(line):
if (line.order_id.invoice_quantity=='order'):
if line.product_uos:
@ -716,7 +742,6 @@ class sale_order_line(osv.osv):
if line.product_uos:
return line.product_uos.id
return line.product_uom.id
if not line.invoiced:
if not account_id:
if line.product_id:
@ -743,7 +768,7 @@ class sale_order_line(osv.osv):
if not account_id:
raise osv.except_osv(_('Error!'),
_('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.'))
return {
res = {
'name': line.name,
'origin': line.order_id.name,
'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,
}
return False
return res
def invoice_line_create(self, cr, uid, ids, context=None):
if context is None:
@ -842,10 +867,9 @@ class sale_order_line(osv.osv):
'product_uos': []}}
if not date_order:
date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
res = {}
result = res
warning_msgs = res.get('warning') and res['warning']['message'] or ''
#
result = {}
warning_msgs = {}
product_obj = product_obj.browse(cr, uid, product, context=context)
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"/>
<!-- 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>
</function>
<!-- notify all employees of module installation -->
<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>
</openerp>

View File

@ -9,7 +9,6 @@
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">prepaid</field>
</record>
<record id="sale_order_line_1" model="sale.order.line">
@ -49,6 +48,7 @@
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record>
<record id="sale_order_line_4" model="sale.order.line">
@ -78,6 +78,7 @@
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record>
<record id="sale_order_line_6" model="sale.order.line">
@ -107,7 +108,6 @@
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">prepaid</field>
</record>
<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_invoice_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="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record>
<record id="sale_order_line_16" model="sale.order.line">
@ -264,6 +264,7 @@
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
</record>
<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="price_unit">12.50</field>
</record>
<!-- 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.. -->
<!-- Demo Data for Product -->

View File

@ -13,7 +13,7 @@
<!-- Resource: sale.order.line -->
<record id="test_order_1_line_1" model="sale.order.line">
<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_uom" ref="product.product_uom_unit"/>
<field name="price_unit">450</field>
@ -23,7 +23,7 @@
</record>
<record id="test_order_1_line_3" model="sale.order.line">
<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_uom" ref="product.product_uom_unit"/>
<field name="price_unit">90</field>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Top menu item -->
<!--
This menu item's purpose is to overwrite another one defined in
@ -32,7 +31,7 @@
</group>
</group>
</form>
</field>
</field>
</record>
<record id="view_shop_tree" model="ir.ui.view">
@ -65,7 +64,6 @@
</field>
</record>
<menuitem action="action_shop_form" id="menu_action_shop_form" parent="base.menu_base_config" sequence="35"/>
<!-- Sale order Read/Unread actions -->
<record id="actions_server_sale_order_unread" model="ir.actions.server">
@ -130,8 +128,8 @@
<field name="model">sale.order</field>
<field name="priority">2</field>
<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')">
<field name="needaction_pending" invisible="1"/>
<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="message_unread" invisible="1"/>
<field name="name"/>
<field name="date_order"/>
<field name="partner_id"/>
@ -152,18 +150,21 @@
<span groups="base.group_user">
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/>
<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="print_quotation" string="Send by Post" type="object" states="draft,sent"/>
<button name="action_button_confirm" states="draft" string="Confirm" type="object" class="oe_highlight"/>
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight"/>
<button name="action_quotation_send" string="Send by Mail" type="object" states="sent"/>
<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_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="action_cancel" states="manual,progress" string="Cancel" type="object"/>
<button name="invoice_cancel" states="invoice_except" string="Cancel"/>
</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>
<sheet>
<h1>
@ -180,7 +181,7 @@
</group>
<group>
<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 domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/>
</group>
@ -237,25 +238,26 @@
</div>
</form>
<tree string="Sales Order Lines" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="state" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="tax_id" invisible="1"/>
<field name="th_weight" invisible="1"/>
<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}"
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)"/>
<field name="name"/>
<field name="type" invisible="1"/>
<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}"
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"
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}'/>
<field name="product_uos_qty" groups="product.group_uos"/>
<field name="product_uos" string="UoS" groups="product.group_uos"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="product_uos_qty" groups="product.group_uos" invisible="1"/>
<field name="product_uos" string="UoS" groups="product.group_uos" invisible="1"/>
<field name="tax_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','&lt;&gt;','purchase')]"/>
<field name="price_unit"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="price_subtotal"/>
</tree>
</field>
@ -278,7 +280,7 @@
<page string="Other Information" groups="base.group_user">
<group>
<group name="logistics">
<field name="order_policy"/>
<field name="order_policy" readonly="1"/>
<field name="invoice_quantity" invisible="True"/>
</group>
<group groups="base.group_user">
@ -319,13 +321,27 @@
</field>
</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">
<field name="name">sale.order.list.select</field>
<field name="model">sale.order</field>
<field name="arch" type="xml">
<search string="Search Sales Order">
<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/>
<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'))]"/>

View File

@ -39,7 +39,7 @@
<field name="name">done</field>
<field name="flow_stop">True</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>
</record>
@ -135,10 +135,10 @@
<field name="signal">cancel</field>
</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_to" ref="act_invoice"/>
<field name="condition">(order_policy=='prepaid')</field>
<field name="signal">manual_invoice</field>
</record>
<record id="trans_invoice_invoice_end" model="workflow.transition">
@ -146,6 +146,7 @@
<field name="act_to" ref="act_invoice_end"/>
<field name="signal">subflow.paid</field>
</record>
<record id="trans_invoice_invoice_except" model="workflow.transition">
<field name="act_from" ref="act_invoice"/>
<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
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_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_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

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

View File

@ -1,19 +1,31 @@
-
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}
-
I check state of order in 'Sale Order'.
-
!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}: |
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.
-

View File

@ -10,5 +10,5 @@
I make duplicate order and delete.
-
!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])

View File

@ -11,13 +11,13 @@
product_uom_qty: 1.0
product_uom: 1
price_unit: 150.0
name: 'Basic pc'
name: 'PC Assemble SC234'
order_line:
- product_id: product.product_product_5
product_uom_qty: 10.0
product_uom: 1
price_unit: 200.0
name: 'Medium pc'
name: 'PC Assemble + Custom (PC on Demand)'
-
I confirm the sale order
-
@ -72,10 +72,10 @@
"__model": "purchase.order.line",
"__import_module": "sale",
"__import_model": "sale.order.line",
"name": "Basic PC",
"name": "PC Assemble SC234",
"date_planned": "2011-09-30",
"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_uom": ["product:5af1272e-dd26-11e0-b65e-701a04e25543.product_uom_unit", "Unit"],
},
@ -85,10 +85,10 @@
"__model": "purchase.order.line",
"__import_module": "sale",
"__import_model": "sale.order.line",
"name": "Medium PC",
"name": "PC on Demand",
"date_planned": "2011-09-15",
"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_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 len(order_new.order_line) == 2, "Sale order lines mismatch"
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.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"
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.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"

View File

@ -1,27 +1,27 @@
-
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.
-
!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."
-
I create advance invoice.
-
!python {model: sale.advance.payment.inv}: |
ctx = context.copy()
ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.sale_order_7")], "active_id":ref("sale.sale_order_7")})
order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale.sale_order_line_16"), context=context)
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_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})
self.create_invoices(cr, uid, [pay_id], context=ctx)
-
I check Invoice which made advance
-
!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."
-
I create manual Invoice for order.
@ -31,7 +31,7 @@
-
!python {model: sale.make.invoice}: |
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)
-
@ -39,13 +39,13 @@
-
!python {model: sale.order.line.make.invoice}: |
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)
-
I check Invoice which made from 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.invoice_lines, "Invoice line should be created."
-
@ -56,7 +56,7 @@
-
!python {model: sale.make.invoice}: |
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)
-
I open the Invoice.
@ -64,7 +64,7 @@
!python {model: sale.order}: |
import netsvc
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:
wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
@ -72,29 +72,19 @@
-
!python {model: account.invoice}: |
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)
for invoice in order.invoice_ids:
invoice.pay_and_reconcile(
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],
name='test')
-
I check Invoice after do manual.
-
!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.invoiced, "Order is not invoiced."
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_make_invoice_advance
import sale_make_invoice
# 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',
'images': ['images/sale_order_analytic_account.jpeg', 'images/sales_order_line.jpeg'],
'depends': ['sale', 'account_analytic_plans'],
'init_xml': [],
'update_xml': ['sale_analytic_plans_view.xml'],
'demo_xml': [],
'data': ['sale_analytic_plans_view.xml'],
'demo': [],
'installable': True,
'auto_install': False,
'certificate': '0066055860861',

View File

@ -22,6 +22,11 @@
</field>
</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">
<field name="name">sale.order.line.form2.inherit</field>
<field name="model">sale.order.line</field>

View File

@ -38,14 +38,14 @@ modules.
'website': 'http://www.openerp.com',
'images': ['images/crm_statistics_dashboard.jpeg', 'images/opportunity_to_quote.jpeg'],
'depends': ['sale_stock', 'crm'],
'init_xml': [],
'update_xml': ['wizard/crm_make_sale_view.xml',
'sale_crm_view.xml',
'process/sale_crm_process.xml',
'security/sale_crm_security.xml',
'security/ir.model.access.csv'
],
'demo_xml': [],
'data': [
'wizard/crm_make_sale_view.xml',
'sale_crm_view.xml',
'process/sale_crm_process.xml',
'security/sale_crm_security.xml',
'security/ir.model.access.csv'
],
'demo': [],
'test': ['test/sale_crm.yml'],
'installable': 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})
new_ids.append(new_id)
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:
case_obj.case_close(cr, uid, data)
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.
You can use journal for different purposes, some examples:
----------------------------------------------------------
* isolate sales of different departments
* journals for deliveries by truck or by UPS
Journals have a responsible and evolves between different status:
-----------------------------------------------------------------
* draft, open, cancel, done.
Batch operations can be processed on the different journals to confirm all sales
at once, to validate or invoice packing.
It also supports batch invoicing methods that can be configured by partners and
sales orders, examples:
It also supports batch invoicing methods that can be configured by partners and sales orders, examples:
-------------------------------------------------------------------------------------------------------
* daily invoicing
* monthly invoicing
@ -50,12 +52,12 @@ Some statistics by journals are provided.
'website': 'http://www.openerp.com',
'images': ['images/invoice_type.jpeg'],
'depends': ['sale_stock'],
'init_xml': ['sale_journal_data.xml'],
'update_xml': [
'data': [
'security/ir.model.access.csv',
'sale_journal_view.xml',
'sale_journal_data.xml'
],
'demo_xml': ['sale_journal_demo.xml'],
'demo': ['sale_journal_demo.xml'],
'test': [ ],
'installable': True,
'auto_install': False,

View File

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

View File

@ -9,7 +9,7 @@
invoice_quantity: order
name: Test_SO011
order_line:
- name: '[KEYA] Keyboard - AZERTY'
- name: '[CARD] Graphics Card'
price_unit: 7.0
product_uom: product.product_uom_unit
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',
'images': ['images/SO_to_MO.jpeg'],
'depends': ['mrp', 'sale_stock'],
'init_xml': [],
'update_xml': [
'data': [
'security/ir.model.access.csv',
'sale_mrp_view.xml',
],
'demo_xml': [],
'demo': [],
'test':['test/sale_mrp.yml'],
'installable': 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:
-----------------------------------------------------------
* Requested Date
* Commitment Date
* Effective Date
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ["images/sale_order_dates.jpeg"],
'depends': ["sale_stock"],
'init_xml': [
],
'update_xml': [
'sale_order_dates_view.xml',
],
'demo_xml': [
],
'images': ['images/sale_order_dates.jpeg'],
'depends': ['sale_stock'],
'data': ['sale_order_dates_view.xml'],
'demo': [],
'test': [],
'installable': True,
'auto_install': False,

View File

@ -20,10 +20,11 @@
##############################################################################
{
'name': 'Sale To Stock',
'name': 'Sales and Warehouse Management',
'version': '1.0',
'category': 'Hidden',
'description': """
'summary': 'Quotation, Sale Orders, Delivery & Invoicing Control',
This Module manage quotations and sales orders.
===========================================================================
@ -61,11 +62,9 @@ Dashboard for Sales Manager that includes:
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': [],
'depends': ['sale', 'procurement'],
'depends': ['sale', 'stock', 'procurement'],
'init_xml': [],
'update_xml': ['wizard/sale_make_invoice_advance.xml',
'wizard/sale_make_invoice.xml',
'security/sale_stock_security.xml',
'update_xml': ['security/sale_stock_security.xml',
'security/ir.model.access.csv',
'company_view.xml',
'sale_stock_view.xml',
@ -73,15 +72,16 @@ Dashboard for Sales Manager that includes:
'res_config_view.xml',
'report/sale_report_view.xml',
'process/sale_stock_process.xml',
],
'data': ['sale_stock_data.xml'],
'demo_xml': ['sale_stock_demo.xml'],
'test': ['test/cancel_order_sale_stock.yml',
'test/picking_order_policy.yml',
'test/manual_order_policy.yml'
'test/prepaid_order_policy.yml',
],
'installable': 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):
_inherit = 'sale.config.settings'
_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',
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'."),
@ -52,8 +55,11 @@ class sale_configuration(osv.osv_memory):
help="This allows to configure and use multiple shops."),
'module_project_timesheet': fields.boolean("Project Timesheet"),
'module_project_mrp': fields.boolean("Project MRP"),
}
}
_defaults = {
'default_order_policy': 'manual',
}
def default_get(self, cr, uid, fields, context=None):
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="arch" type="xml">
<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>
<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"/>
@ -22,7 +26,11 @@
<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)]}"/>
</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)]}">
<field name="module_delivery" class="oe_inline"/>
<label for="module_delivery"/>
@ -44,24 +52,15 @@
<label for="group_mrp_properties"/>
</div>
</div>
<xpath expr="//div[@name='Sale Features']/div[@name='module_sale_margin']" position="before">
<xpath expr="//div[@name='module_sale_margin']" position="before">
<div>
<field name="group_multiple_shops" class="oe_inline"/>
<label for="group_multiple_shops"/>
</div>
</xpath>
<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>
<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">
<div attrs="{'invisible': [('task_work','=',False), ('module_account_analytic_analysis','=',False)],'required': ['|', ('task_work','=',True), ('module_account_analytic_analysis','=',True)]}">
<label for="time_unit"/>

View File

@ -28,9 +28,11 @@ from tools.translate import _
class sale_shop(osv.osv):
_inherit = "sale.shop"
_columns = {
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
}
sale_shop()
class sale_order(osv.osv):
_inherit = "sale.order"
@ -110,7 +112,7 @@ class sale_order(osv.osv):
return res
_columns = {
'state': fields.selection([
'state': fields.selection([
('draft', 'Draft Quotation'),
('sent', 'Quotation Sent'),
('cancel', 'Cancelled'),
@ -142,7 +144,7 @@ class sale_order(osv.osv):
'picked_rate': fields.function(_picked_rate, string='Picked', type='float'),
'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on',
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 = {
'picking_policy': 'direct',
@ -162,7 +164,16 @@ class sale_order(osv.osv):
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):
'''
@ -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.confirm_send_note(cr, uid, ids, context)
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):
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')
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:
context = {}
# 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):
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
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'
_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)]}),
'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)]},
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'),
'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'),
}
_defaults = {
'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):
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):
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,
line.procurement_id.id, context=context)
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,
line.procurement_id.id, context=context)
uosqty = _get_line_qty(line)
uos_id = _get_line_uom(line)
pu = 0.0
if uosqty:
if not line.invoiced:
uosqty = _get_line_qty(line)
uos_id = _get_line_uom(line)
pu = 0.0
if uosqty:
pu = round(line.price_unit * line.product_uom_qty / uosqty,
self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price'))
res.update({'price_unit': pu, 'quantity': uosqty,'uos_id': uos_id})
self.pool.get('decimal.precision').precision_get(cr, uid, 'Product Price'))
res.update({'price_unit': pu, 'quantity': uosqty, 'uos_id': uos_id})
return res
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,
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)
if not product:
return {'value': {'th_weight': 0, 'product_packaging': False,
'product_uos_qty': qty}, 'domain': {'product_uom': [],
'product_uos': []}}
res = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
result = res.get('value', {})
warning_msgs = res.get('warning') and res['warning']['message'] or ''
res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
result = res_packing.get('value', {})
warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
product_obj = product_obj.browse(cr, uid, product, context=context)
uom2 = False
if uom:
@ -671,7 +657,10 @@ class sale_order_line(osv.osv):
warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"
# get unit price
if warning_msgs:
warning.update({'message': warning_msgs})
warning = {
'title': _('Configuration Error!'),
'message' : warning_msgs
}
res.update({'warning': warning})
return res
@ -683,4 +672,4 @@ class sale_order_line(osv.osv):
raise osv.except_osv(
_('Cannot cancel 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"?>
<openerp>
<data noupdate="1">
<!-- Resource: sale.shop -->
<record id="sale.sale_shop_1" model="sale.shop">
<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>
</data>
</openerp>

View File

@ -1,35 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="sale.sale_order_2" model="sale.order">
<field name="order_policy">manual</field>
<record id="sale.sale_order_1" model="sale.order">
<field name="order_policy">prepaid</field>
</record>
<record id="sale.sale_order_3" model="sale.order">
<field name="order_policy">manual</field>
<record id="sale.sale_order_4" model="sale.order">
<field name="order_policy">prepaid</field>
</record>
<record id="sale.sale_order_5" model="sale.order">
<field name="order_policy">picking</field>
</record>
<record id="sale.sale_order_6" model="sale.order">
<field name="order_policy">picking</field>
</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-->
<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_7"/>
<record id="sale.sale_order_line_4" model="sale.order.line">
<field name="type">make_to_order</field>

View File

@ -2,19 +2,18 @@
<openerp>
<data>
<record id="view_shop_form_inherit" model="ir.ui.view">
<field name="name">sale.shop.sale.stock</field>
<record id="view_sale_shop_form_inherit" model="ir.ui.view">
<field name="name">sale.shop.inherit.form</field>
<field name="model">sale.shop</field>
<field name="inherit_id" ref="sale.view_shop_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<xpath expr="//group[@name='shop']" position="before">
<label for="warehouse_id" class="oe_edit_only"/>
<h2><field name="warehouse_id" required="1"/></h2>
<label for="warehouse_id" class="oe_edit_only"/>
<h2><field name="warehouse_id" required="1"/></h2>
</xpath>
</field>
</record>
<record id="view_shop_tree_inherit" model="ir.ui.view">
<field name="name">sale.shop.sale.stock</field>
<field name="model">sale.shop</field>
@ -27,6 +26,7 @@
</field>
</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">
<field name="name">sale.order.tree.sale.stock</field>
@ -47,27 +47,25 @@
<field name="type">form</field>
<field name="arch" type="xml">
<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_corrected" states="shipping_except" string="Ignore Exception"/>
</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"
attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True),('order_policy','=','picking')]}"/>
</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"
attrs="{'invisible': ['|','|','|',('picking_ids','=',False),('picking_ids','=',[]), ('state', 'not in', ('progress','manual')),('shipped','=',True)]}"/>
</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"/>
</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" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
</field>
<field name="product_id" position="replace">
<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}"
@ -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)"/>
</field>
<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>
<xpath expr="//page[@string='Other Information']/group/group/field[@name='invoiced']" position="after">
<field name='invoiced' position="after">
<field name="shipped"/>
</xpath>
</field>
<field name="invoice_ids" position="after">
<separator string="Delivery Orders"/>
<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">
<field name="product_packaging" invisible="1"/>
</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)"/>
</xpath>
<xpath expr="//page[@string='Other Information']/group/group[@name='logistics']/field[@name='order_policy']" position="before">
<field name="invoice_quantity" invisible="1"/>
</field>
<field name='order_policy' position="before">
<field name="incoterm" widget="selection" groups="base.group_user"/>
<field name="picking_policy" required="True"/>
</xpath>
</field>
</data>
</field>
</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>
</openerp>

View File

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

View File

@ -22,6 +22,9 @@
attrs="{'invisible': [('advance_payment_method', '!=', 'percentage')]}"/>
</div>
</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>
<button name="create_invoices" string="Create Invoice" type="object"
class="oe_highlight"