[MERGE] trunk-first_10_clicks_sale-rco (usability improvements)

bzr revid: rco@openerp.com-20120725151923-47wtfb28y97h4car
This commit is contained in:
Raphael Collet
2012-07-25 17:19:23 +02:00
35 changed files with 605 additions and 266 deletions
+17 -2
View File
@@ -196,7 +196,7 @@
<notebook>
<page string="Invoice">
<field context="{'partner_id': partner_id, 'price_type': 'price_type' in dir() and price_type or False, 'type': type}" name="invoice_line">
<tree string="Invoice lines">
<tree string="Invoice lines" editable="bottom">
<field name="product_id" on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
<field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id" on_change="onchange_account_id(product_id,parent.partner_id,parent.type,parent.fiscal_position,account_id)" groups="base.group_account_user"/>
<field name="invoice_line_tax_id" view_mode="2" context="{'type':parent.type}" domain="[('parent_id','=',False)]"/>
@@ -344,7 +344,22 @@
<field name="sent" invisible="1"/>
<notebook colspan="4">
<page string="Invoice Lines">
<field name="invoice_line" nolabel="1" widget="one2many_list" context="{'type': type}"/>
<field name="invoice_line" nolabel="1" widget="one2many_list" context="{'type': type}">
<tree string="Invoice Lines" editable="bottom">
<field name="invoice_line_tax_id" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="name"/>
<field name="account_id" groups="account.group_account_user"
domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]"
on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)"/>
<field name="quantity"/>
<field name="uos_id" groups="product.group_uom"
on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
<field name="price_unit"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="price_subtotal"/>
</tree>
</field>
<group class="oe_subtotal_footer oe_right">
<field name="amount_untaxed"/>
<div>
@@ -1,20 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- rename root menu "Accounting" -->
<record id="account.menu_finance" model="ir.ui.menu">
<field name="name">Accounting</field>
</record>
</data>
<!--
It's easier for new users to not activate this (ex: they misconfigure
header and footer.)
<record model="ir.actions.report.xml" id="account.account_invoices">
<field name="attachment_use">1</field>
</record>
-->
<data noupdate="1">
<!-- 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>Module Accounting and Finance has been installed</value>
<value>From the top menu Accounting, manage all of your accounting:
general accounting, cost/analytic accounting, third party
accounting, taxes, budgets, customer and supplier invoices,
bank statements, reconciliation process.
</value>
</function>
</data>
</openerp>
+3 -1
View File
@@ -38,7 +38,9 @@ eInvoicing & Payments module manage all Voucher Entries such as "Reconciliation
"website" : "http://tinyerp.com",
"images" : ["images/customer_payment.jpeg","images/journal_voucher.jpeg","images/sales_receipt.jpeg","images/supplier_voucher.jpeg"],
"depends" : ["account"],
"init_xml" : [],
"init_xml" : [
'account_voucher_data.xml',
],
"demo_xml" : [],
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module eInvoicing &amp; Payments has been installed</value>
<value>From the top menu Invoicing, manage your customer and supplier
invoices. You can also manage refunds, receipts and register
payments.
In order to manage all accounting features (journal items,
chart of accounts, etc), you should install the module
"Accounting and Finance".
</value>
</function>
</data>
</openerp>
+9 -4
View File
@@ -33,13 +33,18 @@ Shows you a list of applications features to install from.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base'],
'init_xml': [],
'update_xml': ['security/ir.model.access.csv', 'base_setup_views.xml', 'res_config_view.xml'],
'demo_xml': [],
'depends': ['base', 'web_kanban'],
'data': [
'security/ir.model.access.csv',
'base_setup_views.xml',
'res_config_view.xml',
'res_partner_view.xml',
],
'demo': [],
'installable': True,
'auto_install': False,
'certificate': '0086711085869',
'images': ['images/base_setup1.jpeg','images/base_setup2.jpeg','images/base_setup3.jpeg','images/base_setup4.jpeg',],
'js': ['static/src/js/base_setup.js'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+19
View File
@@ -0,0 +1,19 @@
<openerp>
<data>
<!-- Add partner categories in partner kanban view -->
<record id="res_partner_kanban_view" model="ir.ui.view">
<field name="name">res.partner.kanban.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@class='oe_kanban_partner_categories']" position="inside">
<t t-foreach="record.category_id.raw_value" t-as="category">
<span class="oe_tag" t-att-data-category_id="category"/>
</t>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -0,0 +1,24 @@
openerp.base_setup = function(openerp) {
/* extend kanban to include the names of partner categories in the kanban view of partners */
openerp.web_kanban.KanbanView.include({
on_groups_started: function() {
var self = this;
self._super.apply(this, arguments);
if (this.dataset.model === 'res.partner') {
/* Set names for partner categories */
var category_ids = [];
this.$element.find('.oe_kanban_partner_categories span').each(function() {
category_ids.push($(this).data('category_id'));
});
var dataset = new openerp.web.DataSetSearch(this, 'res.partner.category', self.session.context);
dataset.name_get(_.uniq(category_ids)).then(function(result) {
_.each(result, function(value) {
self.$element
.find('.oe_kanban_partner_categories span[data-category_id=' + value[0] + ']')
.html(value[1]);
});
});
}
}
});
};
+22
View File
@@ -17,5 +17,27 @@
<field name="name">Sales Department</field>
<field name="code">Sales</field>
</record>
<!-- 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>Module CRM has been installed</value>
<value>From the top menu Sales, manage your sales pipeline: leads,
opportunities, meetings, phone calls, and customers. OpenERP
ensures that all cases are successfully tracked by all parties.
It can automatically send reminders, escalate requests, trigger
specific methods and lots of other actions based on your own
enterprise rules.
In the Sales settings, you can configure an email gateway to
automatically create leads from messages sent on a particular
email address.
To manage quotations and sale orders, install the module "Sales
Management". With this module, you will be able to create
quotations directly from opportunities.
</value>
</function>
</data>
</openerp>
+4 -3
View File
@@ -106,16 +106,17 @@
<field name="model">res.partner</field>
<field name="type">kanban</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="priority" eval="10"/>
<field name="arch" type="xml">
<field name="mobile" position="after">
<field name="opportunity_count"/>
<field name="meeting_count"/>
</field>
<xpath expr="//h4[@class='oe_partner_heading']" position="after">
<a name="%(relate_partner_opportunities)d" type="action" t-if="record.opportunity_count.value>0" class="oe_tag">
<xpath expr="//div[@class='oe_kanban_partner_links']" position="inside">
<a name="%(relate_partner_opportunities)d" type="action" t-if="record.opportunity_count.value>0">
<t t-esc="record.opportunity_count.value"/> Opportunities
</a>
<a name="%(crm_meeting_partner)d" type="action" t-if="record.meeting_count.value>0" class="oe_tag">
<a name="%(crm_meeting_partner)d" type="action" t-if="record.meeting_count.value>0">
<t t-esc="record.meeting_count.value"/> Meetings
</a>
</xpath>
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Events Organisation has been installed</value>
<value>Organize events and manage their registrations. You can
automatically confirm and send acknowledgements of registrations
by email.
</value>
</function>
</data>
</openerp>
+17
View File
@@ -1,6 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Employee Directory has been installed</value>
<value>Manage your human resources in OpenERP: employees and hierarchy,
HR departments and jobs.
More features are available in the following modules:
Recruitment Process (manage job positions and recruitment),
Timesheets Validation (record timesheets and attendance),
Leaves Management (keep track of employee leaves),
Expenses Management (manage employee expenses),
Employee Appraisals (organize employee surveys, where employees
evaluate their subordinates or their manager.)
</value>
</function>
<record id="employee" model="hr.employee">
<field name="name">Administrator</field>
@@ -1,6 +1,18 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Employee Appraisals has been installed</value>
<value>Create evaluations for your subordinates or manager. You can
define a plan with several surveys, where you organize evaluation
surveys related to the hierarchy levels. Evaluations filled by
employees can exported as pdf files.
</value>
</function>
<record id="survey_2" model="survey">
<field name="title">Self Appraisal</field>
<field name="max_response_limit">20</field>
+17 -4
View File
@@ -1,10 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!--
Resource: product.uom.categ
-->
<record id="cat_expense" model="product.category">
<!-- 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>Module Expenses Management has been installed</value>
<value>Manage your employee's expenses, with validations by employee
manager and accountant, creation and payment of invoice.
This module also uses the analytic accounting and is compatible
with the invoice on timesheet module so that you will be able to
automatically re-invoice your customer's expenses if your work
by project.
</value>
</function>
<!-- Resource: product.uom.categ -->
<record id="cat_expense" model="product.category">
<field name="parent_id" ref="product.cat0"/>
<field name="name">Expenses</field>
</record>
+37 -27
View File
@@ -1,34 +1,44 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<data noupdate="1">
<!-- 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>Module Leaves Management has been installed</value>
<value>Manage employee leaves from the top menu "Human Resources."
Employees can create leave requests that are validated by their
manager and/or HR people. Once validated, they are visible in
the employee's calendar. HR people can define leave types and
allocate off-days for employees.
</value>
</function>
<!-- Casual leave -->
<record model="hr.holidays.status" id="holiday_status_cl">
<field name="name" eval="'Legal Leaves '+time.strftime('%Y')"/>
<field name="color_name">black</field>
</record>
<!-- Casual leave -->
<record model="hr.holidays.status" id="holiday_status_cl">
<field name="name" eval="'Legal Leaves '+time.strftime('%Y')"/>
<field name="color_name">black</field>
</record>
<!-- Sick leave -->
<record model="hr.holidays.status" id="holiday_status_sl">
<field name="name">Sick Leaves</field>
<field name="limit">True</field>
<field name="color_name">red</field>
</record>
<!-- Sick leave -->
<record model="hr.holidays.status" id="holiday_status_sl">
<field name="name">Sick Leaves</field>
<field name="limit">True</field>
<field name="color_name">red</field>
</record>
<!-- Compensatory Days -->
<record model="hr.holidays.status" id="holiday_status_comp">
<field name="name">Compensatory Days</field>
<field name="limit">True</field>
<field name="color_name">lavender</field>
</record>
<!-- Compensatory Days -->
<record model="hr.holidays.status" id="holiday_status_comp">
<field name="name">Compensatory Days</field>
<field name="limit">True</field>
<field name="color_name">lavender</field>
</record>
<!--Unpaid Leave -->
<record model="hr.holidays.status" id="holiday_status_unpaid">
<field name="name">Unpaid</field>
<field name="limit">True</field>
<field name="color_name">brown</field>
</record>
</data>
<!--Unpaid Leave -->
<record model="hr.holidays.status" id="holiday_status_unpaid">
<field name="name">Unpaid</field>
<field name="limit">True</field>
<field name="color_name">brown</field>
</record>
</data>
</openerp>
@@ -1,6 +1,20 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Recruitment Process has been installed</value>
<value>
Manage job positions and the recruitment process in your company.
This module is integrated with the module Survey to help you to
define interviews for different jobs.
You can automatically create application records from an email
gateway, that you can configure in the Human Resources Settings.
</value>
</function>
<!-- Meeting Types (for interview meetings) -->
<record model="crm.meeting.type" id="categ_meet_interview">
@@ -1,6 +1,15 @@
<?xml version="1.0" ?>
<openerp>
<data noupdate="1">
<!-- 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>Module Timesheets Validation has been installed</value>
<value>From the top menu "Human Resources", encode and validate
timesheets and attendances.
</value>
</function>
<record id="ir_actions_server_timsheet_sheet" model="ir.actions.server">
<field eval="5" name="sequence"/>
+11
View File
@@ -14,5 +14,16 @@
<field name="group_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<!-- 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>Module Social Network has been installed</value>
<value>Manage all communications on your documents (emails,
notifications, comments and discussions) and keep track of
news on documents you follow.
</value>
</function>
</data>
</openerp>
-2
View File
@@ -822,8 +822,6 @@ class mail_thread(osv.Model):
def message_append_note(self, cr, uid, ids, subject=None, body=None, parent_id=False,
type='notification', content_subtype='html', context=None):
if type in ['notification', 'comment']:
subject = None
if content_subtype == 'html':
body_html = body
body_text = body
+14
View File
@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module MRP has been installed</value>
<value>Manage your manufacturing process in OpenERP by defining bill
of materials (BoM), routings and work centers. This module
supports complete integration and planification of stockable
goods, consumable, and services.
From the Manufacturing Settings, you can choose to compute
production schedules periodically or just-in-time.
</value>
</function>
<record id="sequence_mrp_prod_type" model="ir.sequence.type">
<field name="name">Production order</field>
+16 -2
View File
@@ -1,12 +1,26 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record model="pos.config" id="pos_config_main">
<field name="name">Main PoS</field>
</record>
</data>
<data noupdate="1">
<!-- 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>Module Point of Sale has been installed</value>
<value>Encode sale orders, register payments, compute money to return,
create invoices, and manage refunds of former sales through a
specific, web-based, user interface.
Simply click on the top menu "Point of Sale" to launch its
interface. You can configure your point of sale and perform
backend operations in the menu "PoS Backend".
</value>
</function>
</data>
</openerp>
+16
View File
@@ -59,5 +59,21 @@
<field name="case_default" eval="True"/>
<field name="fold" eval="True"/>
</record>
<!-- 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>Module Project Management has been installed</value>
<value>Manage multi-level projects and tasks. You can delegate tasks,
track the work done on tasks, and review your planning based on
the entered data.
You can manage todo lists on tasks by installing the module
"Todo Lists", which supports the methodology Getting Things
Done (GTD). You can also manage issues/bugs in projects by
installing the module "Issues Tracker."
</value>
</function>
</data>
</openerp>
+14
View File
@@ -22,6 +22,20 @@
<field name="name">Long Term</field>
<field name="icon">terp-project</field>
</record>
</data>
<data noupdate="1">
<!-- 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>Module Todo Lists has been installed</value>
<value>
Add todo items on project tasks, to help you organize your work.
This module supports the methodology Getting Things Done (GTD),
created by David Allen, and described in the book of the same
name.
</value>
</function>
</data>
</openerp>
@@ -31,5 +31,19 @@
<field name="name">v3.0</field>
</record>
<!-- 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>Module Issues Tracker has been installed</value>
<value>Manage the issues you might face in a project, like bugs in a
system, client complaints or material breakdowns. You can
record issues, assign them to some responsible person, and keep
track of their status as they evolve over time.
You can access issues from the top menu Project, and access the
issues of a specific project from the projects gallery view.
</value>
</function>
</data>
</openerp>
+13
View File
@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Purchase Management has been installed</value>
<value>From the top menu Purchases, create purchase orders to buy
products from your suppliers, encode supplier invoices and
manage your payments.
You can also manage purchase requisitions, see the Purchase
Settings.
</value>
</function>
<record id="req_link_purchase_order" model="res.request.link">
<field name="name">Purchase Order</field>
+3
View File
@@ -69,6 +69,9 @@ class sale_configuration(osv.osv_memory):
'group_sale_delivery_address': fields.boolean("Allow Different Addresses for Delivery and Invoice",
implied_group='sale.group_delivery_invoice_address',
help="Allows you to specify different delivery and invoice addresses on a sale order."),
'group_mrp_properties': fields.boolean('Properties on Lines',
implied_group='sale.group_mrp_properties',
help="Allows you to tag sale order lines with properties."),
'group_discount_per_so_line': fields.boolean("Discount per Line",
implied_group='sale.group_discount_per_so_line',
help="Allows you to apply some discount per sale order line."),
+1
View File
@@ -20,6 +20,7 @@
<field name="decimal_precision"/>
<field name="default_picking_policy" attrs="{'invisible':[('group_invoice_deli_orders','=',False)]}"/>
<field name="group_discount_per_so_line"/>
<field name="group_mrp_properties"/>
<field name="module_sale_margin"/>
<field name="module_sale_journal"/>
</group>
+3 -2
View File
@@ -24,12 +24,13 @@
<field name="model">res.partner</field>
<field name="type">kanban</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<field name="mobile" position="after">
<field name="sale_order_count"/>
</field>
<xpath expr="//h4[@class='oe_partner_heading']" position="after">
<a name="%(sale.act_res_partner_2_sale_order)d" type="action" t-if="record.sale_order_count.value>0" class="oe_tag">
<xpath expr="//div[@class='oe_kanban_partner_links']" position="inside">
<a name="%(sale.act_res_partner_2_sale_order)d" type="action" t-if="record.sale_order_count.value>0">
<t t-esc="record.sale_order_count.value"/> Sales
</a>
</xpath>
+10 -10
View File
@@ -483,19 +483,19 @@ class sale_order(osv.osv):
return {'type': 'ir.actions.report.xml', 'report_name': 'sale.order', 'datas': datas, 'nodestroy': 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")
inv_ids = set()
inv_ids1 = set()
for id in ids:
for record in self.pool.get('sale.order').browse(cr, uid, id).invoice_ids:
inv_ids.add(record.id)
# inv_ids would have old invoices if any
# 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)
for record in self.pool.get('sale.order').browse(cr, uid, id).invoice_ids:
inv_ids1.add(record.id)
inv_ids = list(inv_ids1.difference(inv_ids))
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,
@@ -510,7 +510,7 @@ class sale_order(osv.osv):
'type': 'ir.actions.act_window',
'nodestroy': True,
'target': 'current',
'res_id': inv_ids and inv_ids[0] or False,
'res_id': new_inv_ids and new_inv_ids[0] or False,
}
def action_view_invoice(self, cr, uid, ids, context=None):
+15 -29
View File
@@ -1,17 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!--
Requests Links
-->
<!-- Requests Links -->
<record id="req_link_sale_order" model="res.request.link">
<field name="name">Sales Order</field>
<field name="object">sale.order</field>
</record>
<!--
Resource: sale.shop
-->
<!-- Resource: sale.shop -->
<record id="shop" model="sale.shop">
<field name="company_id" ref="base.main_company"/>
<field name="warehouse_id" ref="stock.warehouse0"/>
@@ -26,29 +22,19 @@
<function eval="('default',False,'shop_id', [('sale.order', False)], shop, True, False, False, False, True)" id="sale_default_set" model="ir.values" name="set"/>
</data>
<data>
<record id="message_welcome_sale" model="mail.message">
<field name="subject">Module sale installed!</field>
<field name="type">comment</field>
<field name="subtype">text</field>
<field name="model">res.users</field>
<field name="res_id" ref="base.user_root"/>
<field name="body_text">Welcome to OpenERP
You can click on the top menu Sales to manage your
customers, your quotations and sales orders.
If you need to manage your sales pipeline (leads,
opportunities, phonecalls), you can install the CRM module
from the Settings top menu.
</field>
</record>
<record id="message_welcome_sale_root" model="mail.notification">
<field name="user_id" ref="base.user_root"/>
<field name="message_id" ref="message_welcome_sale"/>
</record>
<!-- 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>Module Sales Management has been installed</value>
<value>From the top menu Sales, manage your customers, quotations and
sales orders. With sale orders, you can manage product
deliveries and customer invoices.
If you need to manage your sales pipeline (leads, opportunities,
phonecalls), you can install the module CRM from the top menu
Settings.
</value>
</function>
</data>
</openerp>
+25 -12
View File
@@ -157,7 +157,6 @@
<button name="ship_recreate" states="shipping_except" string="Recreate Delivery Order"/>
<button name="ship_corrected" states="shipping_except" string="Ignore Exception"/>
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft,sent"/>
<button name="manual_invoice" states="manual" string="Create Final Invoice" type="object" class="oe_highlight"/>
<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_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/>
@@ -165,7 +164,8 @@
attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True),('order_policy','=','picking')]}"/>
<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)]}"/>
<button name="%(action_view_sale_advance_payment_inv)d" string="Advance Invoice" type="action" states="manual"/>
<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="ship_cancel" states="shipping_except" string="Cancel"/>
@@ -199,7 +199,6 @@
<form string="Sales Order Lines" version="7.0">
<header>
<button name="%(action_view_sale_order_line_make_invoice)d" states="confirmed" string="Invoice" type="action" icon="terp-document-new"/>
<field name="invoiced" invisible="1"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done" statusbar_colors='{"exception":"red","cancel":"red"}'/>
</header>
<group>
@@ -244,7 +243,8 @@
<!-- we should put a config wizard for these two fields -->
<field name="address_allotment_id"/>
<field name="property_ids" widget="many2many_tags"/>
<field name="property_ids" widget="many2many_tags"
groups="sale.group_mrp_properties"/>
</group>
</group>
<label for="name"/>
@@ -256,14 +256,27 @@
<field name="move_ids" widget="many2many"/>
</div>
</form>
<tree string="Sales Order Lines">
<field name="state" invisible="1" />
<field name="sequence"/>
<tree string="Sales Order Lines" editable="bottom">
<field name="state" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="delay" invisible="1"/>
<field name="tax_id" invisible="1"/>
<field name="type" invisible="1"/>
<field name="th_weight" invisible="1"/>
<field name="product_packaging" 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="product_uom_qty" string="Quantity"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field groups="product.group_uos" name="product_uos_qty" string="Quantity (UoS)"/>
<field groups="product.group_uos" name="product_uos" string="UoS"/>
<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" class="oe_no_button"/>
<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="price_unit"/>
<field name="price_subtotal" groups="base.group_sale_notes_subtotal"/>
@@ -456,7 +469,7 @@
<tree string="Sales Order Lines">
<field name="order_id"/>
<field name="order_partner_id"/>
<field name="product_id"/>
<field name="name"/>
<field name="product_uom_qty" string="Qty"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="salesman_id"/>
+5
View File
@@ -35,6 +35,11 @@
<field name="category_id" ref="base.module_category_hidden"/>
</record>
<record id="group_mrp_properties" model="res.groups">
<field name="name">Properties on lines</field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
<record id="group_discount_per_so_line" model="res.groups">
<field name="name">Discount on lines</field>
<field name="category_id" ref="base.module_category_hidden"/>
+1 -1
View File
@@ -16,7 +16,7 @@
ctx = context.copy()
ctx.update({"active_model": 'sale.order', "active_ids": [ref("order4")], "active_id":ref("order4")})
order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("line7"), context=context)
pay_id = self.create(cr, uid, {'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)
-
I check Invoice which made advance
+155 -146
View File
@@ -26,189 +26,198 @@ class sale_advance_payment_inv(osv.osv_memory):
_name = "sale.advance.payment.inv"
_description = "Sales Advance Payment Invoice"
def _default_product_id(self, cr, uid, context=None):
try:
product_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'advance_product_0')
except ValueError:
#a ValueError is returned if the xml id given is not found in the table ir_model_data
return False
return product_id[1]
_columns = {
'product_id': fields.many2one('product.product', 'Advance Product', help="Select a product of type service which is called 'Advance Product'. You may have to create it and set it as a default value on this field."),
'amount': fields.float('Advance Amount', digits_compute= dp.get_precision('Sale Price'), required=True, help="The amount to be invoiced in advance."),
'advance_payment_method':fields.selection(
[('all', 'All'), ('percentage','Percentage'), ('fixed','Fixed Price'),
('lines', 'Some Order Lines')],
'Type', required=True,
help="""Use All to create the final invoice.
Use Percentage to invoice a percentage of the total amount.
Use Fixed Price to invoice a specific amound in advance.
Use Some Order Lines to invoice a selection of the sale order lines."""),
'qtty': fields.float('Quantity', digits=(16, 2), required=True),
'advance_payment_method':fields.selection([('percentage','Percentage'), ('fixed','Fixed Price')], 'Type', required=True, help="Use Fixed Price if you want to give specific amount in Advance. Use Percentage if you want to give percentage of Total Invoice Amount."),
'product_id': fields.many2one('product.product', 'Advance Product',
help="""Select a product of type service which is called 'Advance Product'.
You may have to create it and set it as a default value on this field."""),
'amount': fields.float('Advance Amount', digits_compute= dp.get_precision('Sale Price'),
help="The amount to be invoiced in advance."),
}
def _get_advance_product(self, cr, uid, context=None):
try:
product = self.pool.get('ir.model.data').get_object(cr, uid, 'sale', 'advance_product_0')
except ValueError:
# a ValueError is returned if the xml id given is not found in the table ir_model_data
return False
return product.id
_defaults = {
'advance_payment_method': 'all',
'qtty': 1.0,
'advance_payment_method': 'fixed',
'product_id': _default_product_id,
'product_id': _get_advance_product,
}
def onchange_advance_payment_method(self, cr, uid, ids, advance_payment_method, product_id, context=None):
def onchange_method(self, cr, uid, ids, advance_payment_method, product_id, context=None):
if advance_payment_method == 'percentage':
return {'value': {'amount':0, 'product_id':False }}
if not product_id:
return {'value': {'amount': 0}}
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
return {'value': {'amount': product.list_price}}
if product_id:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
return {'value': {'amount': product.list_price}}
return {'value': {'amount': 0}}
def create_invoices(self, cr, uid, ids, context=None):
"""
To create invoices.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID or list of IDs if we want more than one
@param context: A standard dictionary
@return:
"""
list_inv = []
obj_sale = self.pool.get('sale.order')
obj_lines = self.pool.get('account.invoice.line')
inv_obj = self.pool.get('account.invoice')
""" create invoices for the active sale orders """
if context is None:
context = {}
wizard = self.browse(cr, uid, ids[0], context)
sale_ids = context.get('active_ids', [])
for sale_adv_obj in self.browse(cr, uid, ids, context=context):
for sale in obj_sale.browse(cr, uid, context.get('active_ids', []), context=context):
create_ids = []
ids_inv = []
if sale.order_policy == 'postpaid':
raise osv.except_osv(
_('Error'),
_("You cannot make an advance on a sales order \
that is defined as 'Automatic Invoice after delivery'."))
val = obj_lines.product_id_change(cr, uid, [], sale_adv_obj.product_id.id,
uom = False, partner_id = sale.partner_id.id, fposition_id = sale.fiscal_position.id)
res = val['value']
if wizard.advance_payment_method == 'all':
# create the final invoices of the active sale orders
res = self.pool.get('sale.order').manual_invoice(cr, uid, sale_ids, context)
if context.get('open_invoices', False):
return res
return {'type': 'ir.actions.act_window_close'}
if not sale_adv_obj.product_id.id :
prop = self.pool.get('ir.property').get(cr, uid,
'property_account_income_categ', 'product.category',
context=context)
account_id = prop and prop.id or False
account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, sale.fiscal_position.id or False, account_id)
if not account_id:
raise osv.except_osv(_('Configuration Error !'),
_('There is no income account defined as global property.'))
res['account_id'] = account_id
if wizard.advance_payment_method == 'lines':
# open the list view of sale order lines to invoice
act_window = self.pool.get('ir.actions.act_window')
res = act_window.for_xml_id(cr, uid, 'sale', 'action_order_line_tree2', context)
res['context'] = {
'search_default_uninvoiced': 1,
'search_default_order_id': sale_ids and sale_ids[0] or False,
}
return res
if not res.get('account_id'):
assert wizard.advance_payment_method in ('fixed', 'percentage')
sale_obj = self.pool.get('sale.order')
inv_obj = self.pool.get('account.invoice')
inv_line_obj = self.pool.get('account.invoice.line')
inv_ids = []
for sale in sale_obj.browse(cr, uid, sale_ids, context=context):
if sale.order_policy == 'postpaid':
raise osv.except_osv(
_('Error'),
_("You cannot make an advance on a sales order \
that is defined as 'Automatic Invoice after delivery'."))
val = inv_line_obj.product_id_change(cr, uid, [], wizard.product_id.id,
uom=False, partner_id=sale.partner_id.id, fposition_id=sale.fiscal_position.id)
res = val['value']
# determine and check income account
if not wizard.product_id.id :
prop = self.pool.get('ir.property').get(cr, uid,
'property_account_income_categ', 'product.category', context=context)
prop_id = prop and prop.id or False
account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, sale.fiscal_position.id or False, prop_id)
if not account_id:
raise osv.except_osv(_('Configuration Error !'),
_('There is no income account defined ' \
'for this product: "%s" (id:%d)') % \
(sale_adv_obj.product_id.name, sale_adv_obj.product_id.id,))
_('There is no income account defined as global property.'))
res['account_id'] = account_id
if not res.get('account_id'):
raise osv.except_osv(_('Configuration Error !'),
_('There is no income account defined for this product: "%s" (id:%d)') % \
(wizard.product_id.name, wizard.product_id.id,))
final_amount = 0
if sale_adv_obj.amount <= 0.00:
raise osv.except_osv(_('Data Insufficient !'),
_('Please check the Advance Amount, it should not be 0 or less!'))
if sale_adv_obj.advance_payment_method == 'percentage':
final_amount = sale.amount_total * sale_adv_obj.amount / 100
if not res.get('name'):
res['name'] = _("Advance of %s %%") % (sale_adv_obj.amount)
else:
final_amount = sale_adv_obj.amount
if not res.get('name'):
#TODO: should find a way to call formatLang() from rml_parse
if sale.pricelist_id.currency_id.position == 'after':
res['name'] = _("Advance of %s %s") % (final_amount, sale.pricelist_id.currency_id.symbol)
else:
res['name'] = _("Advance of %s %s") % (sale.pricelist_id.currency_id.symbol, final_amount)
# determine invoice amount
if wizard.amount <= 0.00:
raise osv.except_osv(_('Incorrect Data'),
_('The value of Advance Amount must be positive.'))
if wizard.advance_payment_method == 'percentage':
inv_amount = sale.amount_total * wizard.amount / 100
if not res.get('name'):
res['name'] = _("Advance of %s %%") % (wizard.amount)
else:
inv_amount = wizard.amount
if not res.get('name'):
#TODO: should find a way to call formatLang() from rml_parse
symbol = sale.pricelist_id.currency_id.symbol
if sale.pricelist_id.currency_id.position == 'after':
res['name'] = _("Advance of %s %s") % (inv_amount, symbol)
else:
res['name'] = _("Advance of %s %s") % (symbol, inv_amount)
if res.get('invoice_line_tax_id'):
res['invoice_line_tax_id'] = [(6, 0, res.get('invoice_line_tax_id'))]
else:
res['invoice_line_tax_id'] = False
# determine taxes
if res.get('invoice_line_tax_id'):
res['invoice_line_tax_id'] = [(6, 0, res.get('invoice_line_tax_id'))]
else:
res['invoice_line_tax_id'] = False
line_id = obj_lines.create(cr, uid, {
# create the invoice
inv_line_values = {
'name': res.get('name'),
'account_id': res['account_id'],
'price_unit': inv_amount,
'quantity': wizard.qtty or 1.0,
'discount': False,
'uos_id': res.get('uos_id', False),
'product_id': wizard.product_id.id,
'invoice_line_tax_id': res.get('invoice_line_tax_id'),
'account_analytic_id': sale.project_id.id or False,
}
inv_values = {
'name': sale.client_order_ref or sale.name,
'origin': sale.name,
'type': 'out_invoice',
'reference': False,
'account_id': sale.partner_id.property_account_receivable.id,
'partner_id': sale.partner_id.id,
'invoice_line': [(0, 0, inv_line_values)],
'currency_id': sale.pricelist_id.currency_id.id,
'comment': '',
'payment_term': sale.payment_term.id,
'fiscal_position': sale.fiscal_position.id or sale.partner_id.property_account_position.id
}
inv_id = inv_obj.create(cr, uid, inv_values, context=context)
inv_obj.button_reset_taxes(cr, uid, [inv_id], context=context)
inv_ids.append(inv_id)
# add the invoice to the sale order's invoices
sale.write({'invoice_ids': [(4, inv_id)]})
# If invoice on picking: add the cost on the SO
# If not, the advance will be deduced when generating the final invoice
if sale.order_policy == 'picking':
vals = {
'order_id': sale.id,
'name': res.get('name'),
'account_id': res['account_id'],
'price_unit': final_amount,
'quantity': sale_adv_obj.qtty or 1.0,
'price_unit': -inv_amount,
'product_uom_qty': wizard.qtty or 1.0,
'product_uos_qty': wizard.qtty or 1.0,
'product_uos': res.get('uos_id', False),
'product_uom': res.get('uom_id', False),
'product_id': wizard.product_id.id or False,
'discount': False,
'uos_id': res.get('uos_id', False),
'product_id': sale_adv_obj.product_id.id,
'invoice_line_tax_id': res.get('invoice_line_tax_id'),
'account_analytic_id': sale.project_id.id or False,
#'note':'',
})
create_ids.append(line_id)
inv = {
'name': sale.client_order_ref or sale.name,
'origin': sale.name,
'type': 'out_invoice',
'reference': False,
'account_id': sale.partner_id.property_account_receivable.id,
'partner_id': sale.partner_id.id,
'invoice_line': [(6, 0, create_ids)],
'currency_id': sale.pricelist_id.currency_id.id,
'comment': '',
'payment_term': sale.payment_term.id,
'fiscal_position': sale.fiscal_position.id or sale.partner_id.property_account_position.id
'tax_id': res.get('invoice_line_tax_id'),
}
self.pool.get('sale.order.line').create(cr, uid, vals, context=context)
inv_id = inv_obj.create(cr, uid, inv)
inv_obj.button_reset_taxes(cr, uid, [inv_id], context=context)
for inv in sale.invoice_ids:
ids_inv.append(inv.id)
ids_inv.append(inv_id)
obj_sale.write(cr, uid, [sale.id], {'invoice_ids': [(6, 0, ids_inv)]})
list_inv.append(inv_id)
#
# If invoice on picking: add the cost on the SO
# If not, the advance will be deduced when generating the final invoice
#
if sale.order_policy == 'picking':
vals = {
'order_id': sale.id,
'name': res.get('name'),
'price_unit': -final_amount,
'product_uom_qty': sale_adv_obj.qtty or 1.0,
'product_uos_qty': sale_adv_obj.qtty or 1.0,
'product_uos': res.get('uos_id', False),
'product_uom': res.get('uom_id', False),
'product_id': sale_adv_obj.product_id.id or False,
'discount': False,
'tax_id': res.get('invoice_line_tax_id'),
}
self.pool.get('sale.order.line').create(cr, uid, vals, context=context)
context.update({'invoice_id':list_inv})
if context.get('open_invoices'):
return self.open_invoices( cr, uid, ids, context=context)
if context.get('open_invoices', False):
return self.open_invoices( cr, uid, ids, inv_ids, context=context)
return {'type': 'ir.actions.act_window_close'}
def open_invoices(self, cr, uid, ids, context=None):
if context is None:
context = {}
mod_obj = self.pool.get('ir.model.data')
for advance_pay in self.browse(cr, uid, ids, context=context):
form_res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
form_id = form_res and form_res[1] or False
tree_res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_tree')
tree_id = tree_res and tree_res[1] or False
def open_invoices(self, cr, uid, ids, invoice_ids, context=None):
""" open a view on one of the given invoice_ids """
ir_model_data = self.pool.get('ir.model.data')
form_res = ir_model_data.get_object_reference(cr, uid, 'account', 'invoice_form')
form_id = form_res and form_res[1] or False
tree_res = ir_model_data.get_object_reference(cr, uid, 'account', 'invoice_tree')
tree_id = tree_res and tree_res[1] or False
return {
'name': _('Advance Invoice'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'account.invoice',
'res_id': int(context['invoice_id'][0]),
'res_id': invoice_ids[0],
'view_id': False,
'views': [(form_id, 'form'), (tree_id, 'tree')],
'context': "{'type': 'out_invoice'}",
'type': 'ir.actions.act_window',
}
}
sale_advance_payment_inv()
@@ -7,19 +7,35 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Advance Invoice" version="7.0">
<header>
<button name="create_invoices" string="Create Invoice" type="object" context="{'open_invoices': False}" class="oe_highlight" />
<button name="create_invoices" string="Create and view Invoice" type="object" context="{'open_invoices': True}" class="oe_highlight" />
or
<button string="Cancel" class="oe_link" special="cancel" />
</header>
<group col="4">
<field name="advance_payment_method" on_change="onchange_advance_payment_method(advance_payment_method,product_id)"/>
<newline />
<group>
<field name="advance_payment_method"
on_change="onchange_method(advance_payment_method, product_id)"/>
<field name="qtty" invisible="1"/>
<field name="product_id" on_change="onchange_advance_payment_method(advance_payment_method,product_id)" context="{'search_default_services':1}" attrs="{'invisible': [('advance_payment_method','=','percentage')]}" colspan="2"/>
<field name="amount" colspan="2"/>
<field name="product_id"
on_change="onchange_method(advance_payment_method, product_id)"
context="{'search_default_services': 1}"
attrs="{'invisible': [('advance_payment_method','!=','fixed')]}"/>
<label for="amount" attrs="{'invisible': [('advance_payment_method', 'not in', ('fixed','percentage'))]}"/>
<div attrs="{'invisible': [('advance_payment_method', 'not in', ('fixed','percentage'))]}">
<field name="amount"
attrs="{'required': [('advance_payment_method', 'in', ('fixed','percentage'))]}"/>
<label string="%%"
attrs="{'invisible': [('advance_payment_method', '!=', 'percentage')]}"/>
</div>
</group>
<footer>
<button name="create_invoices" string="Create Invoice" type="object"
class="oe_highlight"
attrs="{'invisible': [('advance_payment_method', '=', 'lines')]}"/>
<button name="create_invoices" string="Create and view Invoice" type="object"
context="{'open_invoices': True}" class="oe_highlight"
attrs="{'invisible': [('advance_payment_method', '=', 'lines')]}"/>
<button name="create_invoices" string="Show Lines to Invoice" type="object"
class="oe_highlight"
attrs="{'invisible': [('advance_payment_method', '!=', 'lines')]}"/>
or
<button string="Cancel" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
+11
View File
@@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- 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>Module Warehouse Management has been installed</value>
<value>Manage your product inventoy and stock locations. You can
control your stock moves history and planning, perform stock
valuation, and trace product lots upstream and downstream
(based on serial numbers.)
</value>
</function>
<record id="stock_journal_sequence" model="ir.sequence">
<field name="name">Stock Journal Sequence</field>