[MERGE] master
This commit is contained in:
commit
0fa755bc89
|
@ -25,4 +25,4 @@ install/win32/meta.py
|
|||
/lib/
|
||||
/man/
|
||||
/share/
|
||||
/src/
|
||||
/src/
|
93
README.md
93
README.md
|
@ -1,73 +1,52 @@
|
|||
About Odoo
|
||||
==========
|
||||
Odoo
|
||||
----
|
||||
|
||||
Odoo is a suite of open source Business apps. More info at http://www.odoo.com
|
||||
Odoo is a suite of web based open source business apps. More info at http://www.odoo.com
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
[Setup/migration guide for employees](https://github.com/odoo/odoo/blob/master/doc/git.rst)
|
||||
The easiest way to play with it is the <a href="https://www.odoo.com/page/start">Odoo free trial</a>, email registration is NOT required, use the "skip this step" link on the registration page to skip it.
|
||||
|
||||
|
||||
Migration from bazaar
|
||||
=====================
|
||||
Getting started with Odoo developement
|
||||
--------------------------------------
|
||||
|
||||
If you have existing bazaar branches and want to move them to a git repository,
|
||||
there are several options:
|
||||
If you are a developer type the following command at your terminal [1]:
|
||||
|
||||
* download http://nightly.openerp.com/move-branch.zip and run it with
|
||||
`python move-branch.zip -h` (for the help). It should be able to convert
|
||||
simple-enough branches for you (even if they have merge commits &al)
|
||||
* Extract the branch contents as patches and use `git apply` or `git am` to
|
||||
rebuild a branch from them
|
||||
* Replay the branch by hand
|
||||
wget -O- https://raw.githubusercontent.com/odoo/odoo/master/odoo.py | python
|
||||
|
||||
Then follow <a href="https://doc.openerp.com/trunk/server/howto/howto_website/">the developer tutorial</a>
|
||||
|
||||
[1] You may want to check the content of the <a href="https://raw.githubusercontent.com/odoo/odoo/master/odoo.py">odoo.py file</a> before executing it.
|
||||
|
||||
|
||||
System Requirements
|
||||
-------------------
|
||||
Packages, tarballs and installers
|
||||
---------------------------------
|
||||
|
||||
The dependencies are listed in setup.py
|
||||
* Debian packages
|
||||
|
||||
Add this apt repository to your /etc/apt/sources.list file
|
||||
|
||||
deb http://nightly.openerp.com/8.0/deb/ ./
|
||||
|
||||
Then type:
|
||||
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install odoo
|
||||
|
||||
* <a href="http://nightly.openerp.com/">Source tarballs</a>
|
||||
|
||||
* <a href="http://nightly.openerp.com/">Windows installer</a>
|
||||
|
||||
* <a href="http://nightly.openerp.com/">RPM package</a>
|
||||
|
||||
|
||||
Debian/Ubuntu
|
||||
-------------
|
||||
For Odoo employees
|
||||
------------------
|
||||
|
||||
Add the apt repository
|
||||
To add the odoo-dev remote use this command:
|
||||
|
||||
deb http://nightly.openerp.com/7.0/deb/ ./
|
||||
$ ./odoo.py setup_git_dev
|
||||
|
||||
in your source.list and type:
|
||||
To fetch odoo merge pull requests refs use this command:
|
||||
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install openerp
|
||||
|
||||
Or download the deb file and type:
|
||||
|
||||
$ sudo dpkg -i <openerp-deb-filename>
|
||||
$ sudo apt-get install -f
|
||||
|
||||
RedHat, Fedora, CentOS
|
||||
----------------------
|
||||
|
||||
Install the required dependencies:
|
||||
|
||||
$ yum install python
|
||||
$ easy_install pip
|
||||
$ pip install .....
|
||||
|
||||
Install the openerp rpm
|
||||
|
||||
$ rpm -i openerp-VERSION.rpm
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
Check the notes in setup.py
|
||||
|
||||
|
||||
Setting up your database
|
||||
------------------------
|
||||
|
||||
Point your browser to http://localhost:8069/ and click "Manage Databases", the
|
||||
default master password is "admin".
|
||||
$ ./odoo.py setup_git_review
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
</group>
|
||||
<group>
|
||||
<field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '<>', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)" groups="account.group_account_user"/>
|
||||
<field name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
|
||||
<field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
|
||||
<field domain="[('type','<>','view'), ('company_id', '=', parent.company_id)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
</group>
|
||||
|
|
|
@ -1,57 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product.normal.form.inherit</field>
|
||||
<field name="model">product.product</field>
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.form.inherit</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="priority">5</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Sales" position="after">
|
||||
<page string="Accounting" groups="account.group_account_invoice">
|
||||
<group>
|
||||
<label for="categ_id" string="Internal Category"/>
|
||||
<div><field name="categ_id" colspan="3" nolabel="1"/></div>
|
||||
</group>
|
||||
<group name="properties">
|
||||
<group>
|
||||
<field name="property_account_income" domain="[('type','=','other')]" groups="account.group_account_user"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
attrs="{'readonly': [('is_product_variant', '=', True)]}"/>
|
||||
<field name="taxes_id" colspan="2" widget="many2many_tags"
|
||||
attrs="{'readonly':[ '|', ('sale_ok','=',0), ('is_only_child', '=', False)]}"/>
|
||||
attrs="{'readonly':[ '|', ('sale_ok','=',0), ('is_product_variant', '=', True)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="property_account_expense" domain="[('type','=','other')]" groups="account.group_account_user"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
attrs="{'readonly': [('is_product_variant', '=', True)]}"/>
|
||||
<field name="supplier_taxes_id" colspan="2" widget="many2many_tags"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
attrs="{'readonly': [('is_product_variant', '=', True)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.form.inherit</field>
|
||||
<record id="product_template_search_view" model="ir.ui.view">
|
||||
<field name="name">product.template.search</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="product.product_template_search_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Accounting">
|
||||
<group name="properties">
|
||||
<group>
|
||||
<field name="property_account_income" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="taxes_id" colspan="2" widget="many2many_tags"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="property_account_expense" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="supplier_taxes_id" colspan="2" widget="many2many_tags"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
<field name="product_variant_ids" position="after">
|
||||
<field name="categ_id"/>
|
||||
</field>
|
||||
<xpath expr="//group[@string='Group by...']" position="inside">
|
||||
<filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="view_category_property_form" model="ir.ui.view">
|
||||
<field name="name">product.category.property.form.inherit</field>
|
||||
<field name="model">product.category</field>
|
||||
|
|
|
@ -161,7 +161,7 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
|
|||
dates_query += ' < %s)'
|
||||
args_list += (form[str(i)]['stop'],)
|
||||
args_list += (self.date_from,)
|
||||
self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit)
|
||||
self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit), l.reconcile_partial_id
|
||||
FROM account_move_line AS l, account_account, account_move am
|
||||
WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)
|
||||
AND (am.state IN %s)
|
||||
|
@ -173,12 +173,24 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
|
|||
AND account_account.active
|
||||
AND ''' + dates_query + '''
|
||||
AND (l.date <= %s)
|
||||
GROUP BY l.partner_id''', args_list)
|
||||
t = self.cr.fetchall()
|
||||
d = {}
|
||||
for i in t:
|
||||
d[i[0]] = i[1]
|
||||
history.append(d)
|
||||
GROUP BY l.partner_id, l.reconcile_partial_id''', args_list)
|
||||
partners_partial = self.cr.fetchall()
|
||||
partners_amount = dict((i[0],0) for i in partners_partial)
|
||||
for partner_info in partners_partial:
|
||||
if partner_info[2]:
|
||||
# in case of partial reconciliation, we want to keep the left amount in the oldest period
|
||||
self.cr.execute('''SELECT MIN(COALESCE(date_maturity,date)) FROM account_move_line WHERE reconcile_partial_id = %s''', (partner_info[2],))
|
||||
date = self.cr.fetchall()
|
||||
if date and args_list[-3] <= date[0][0] <= args_list[-2]:
|
||||
# partial reconcilation
|
||||
self.cr.execute('''SELECT SUM(l.debit-l.credit)
|
||||
FROM account_move_line AS l
|
||||
WHERE l.reconcile_partial_id = %s''', (partner_info[2],))
|
||||
unreconciled_amount = self.cr.fetchall()
|
||||
partners_amount[partner_info[0]] += unreconciled_amount[0][0]
|
||||
else:
|
||||
partners_amount[partner_info[0]] += partner_info[1]
|
||||
history.append(partners_amount)
|
||||
|
||||
for partner in partners:
|
||||
values = {}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-8">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<address t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-6">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<span t-field="o.name"/><br/>
|
||||
<span t-raw="addresses[o.id].replace('\n\n', '\n').replace('\n', '<br>')"/>
|
||||
<span t-field="o.vat"/>
|
||||
|
|
|
@ -69,7 +69,7 @@ class account_analytic_invoice_line(osv.osv):
|
|||
if partner_id:
|
||||
part = self.pool.get('res.partner').browse(cr, uid, partner_id, context=local_context)
|
||||
if part.lang:
|
||||
context.update({'lang': part.lang})
|
||||
local_context.update({'lang': part.lang})
|
||||
|
||||
result = {}
|
||||
res = self.pool.get('product.product').browse(cr, uid, product, context=local_context)
|
||||
|
@ -79,7 +79,12 @@ class account_analytic_invoice_line(osv.osv):
|
|||
price = res.price
|
||||
else:
|
||||
price = res.list_price
|
||||
result.update({'name': name or res.description or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price})
|
||||
if not name:
|
||||
name = self.pool.get('product.product').name_get(cr, uid, [res.id], context=local_context)[0][1]
|
||||
if res.description_sale:
|
||||
name += '\n'+res.description_sale
|
||||
|
||||
result.update({'name': name or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price})
|
||||
|
||||
res_final = {'value':result}
|
||||
if result['uom_id'] != res.uom_id.id:
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
<div attrs="{'invisible': [('recurring_invoices','=',False)]}">
|
||||
<field name="recurring_invoice_line_ids">
|
||||
<tree string="Account Analytic Lines" editable="bottom">
|
||||
<field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, name, parent.partner_id, price_unit, parent.pricelist_id, parent.company_id)"/>
|
||||
<field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, False, parent.partner_id, False, parent.pricelist_id, parent.company_id)"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="uom_id"/>
|
||||
|
|
|
@ -1,29 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product.normal.form.inherit.stock</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="account.product_normal_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="property_account_expense" position="after">
|
||||
<label string="" colspan="2"/>
|
||||
<field name="property_account_creditor_price_difference" domain="[('type','<>','view'),('type','<>','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />
|
||||
<newline/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.form.inherit</field>
|
||||
<field name="name">product.normal.form.inherit.stock</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="account.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="property_account_expense" position="after">
|
||||
<label string="" colspan="2"/>
|
||||
<field name="purchase_ok" invisible="1"/>
|
||||
<field name="property_account_creditor_price_difference" domain="[('type','<>','view'),('type','<>','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />
|
||||
<newline/>
|
||||
</field>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_category_property_form" model="ir.ui.view">
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
import datetime
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import ustr
|
||||
from openerp.tools.translate import _
|
||||
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
@ -114,7 +115,7 @@ class crossovered_budget_lines(osv.osv):
|
|||
for line in self.browse(cr, uid, ids, context=context):
|
||||
acc_ids = [x.id for x in line.general_budget_id.account_ids]
|
||||
if not acc_ids:
|
||||
raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % str(line.general_budget_id.name))
|
||||
raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name))
|
||||
date_to = line.date_to
|
||||
date_from = line.date_from
|
||||
if context.has_key('wizard_date_from'):
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-6">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
========================
|
||||
|
||||
******
|
||||
saas-5
|
||||
saas-4
|
||||
******
|
||||
|
||||
- Library update: ``mygengo`` (https://pypi.python.org/pypi/mygengo/1.3.3) was outdated and has been replaced by ``gengo`` (https://pypi.python.org/pypi/gengo).
|
||||
- Library update: ``mygengo`` (https://pypi.python.org/pypi/mygengo/1.3.3) was outdated and has been replaced by ``gengo`` (https://pypi.python.org/pypi/gengo).
|
||||
|
|
|
@ -65,7 +65,7 @@ class res_partner(osv.osv):
|
|||
'date_review_next' : fields.date('Next Partner Review'),
|
||||
# customer implementation
|
||||
'assigned_partner_id': fields.many2one(
|
||||
'res.partner', 'Implementedy by',
|
||||
'res.partner', 'Implemented by',
|
||||
),
|
||||
'implemented_partner_ids': fields.one2many(
|
||||
'res.partner', 'assigned_partner_id',
|
||||
|
|
|
@ -3,6 +3,7 @@ access_ crm_lead_report_assign,crm.lead.report.assign,model_crm_lead_report_assi
|
|||
access_ crm_lead_report_assign_all,crm.lead.report.assign.all,model_crm_lead_report_assign,base.group_user,1,0,0,0
|
||||
access_crm_partner_report,crm.partner.report.assign.all,model_crm_partner_report_assign,base.group_sale_salesman,1,0,0,0
|
||||
access_res_partner_grade,res.partner.grade,model_res_partner_grade,base.group_sale_salesman,1,1,1,0
|
||||
access_res_partner_grade_public,res.partner.grade,model_res_partner_grade,base.group_public,1,0,0,0
|
||||
access_res_partner_grade_manager,res.partner.grade.manager,model_res_partner_grade,base.group_sale_manager,1,1,1,1
|
||||
"access_partner_activation_manager","res.partner.activation.manager","model_res_partner_activation","base.group_partner_manager",1,1,1,1
|
||||
partner_access_crm_lead,crm.lead,model_crm_lead,base.group_portal,1,1,0,0
|
||||
partner_access_crm_lead,crm.lead,model_crm_lead,base.group_portal,1,1,0,0
|
||||
|
|
|
|
@ -192,15 +192,16 @@ class delivery_grid(osv.osv):
|
|||
weight = 0
|
||||
volume = 0
|
||||
quantity = 0
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for line in order.order_line:
|
||||
if not line.product_id or line.is_delivery:
|
||||
continue
|
||||
weight += (line.product_id.weight or 0.0) * line.product_uom_qty
|
||||
volume += (line.product_id.volume or 0.0) * line.product_uom_qty
|
||||
quantity += line.product_uom_qty
|
||||
q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uos_qty, line.product_id.uom_id.id)
|
||||
weight += (line.product_id.weight or 0.0) * q
|
||||
volume += (line.product_id.volume or 0.0) * q
|
||||
quantity += q
|
||||
total = order.amount_total or 0.0
|
||||
|
||||
|
||||
return self.get_price_from_picking(cr, uid, id, total,weight, volume, quantity, context=context)
|
||||
|
||||
def get_price_from_picking(self, cr, uid, id, total, weight, volume, quantity, context=None):
|
||||
|
|
|
@ -42,6 +42,7 @@ this event.
|
|||
'data': [
|
||||
'event_sale_view.xml',
|
||||
'event_sale_data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': ['event_demo.xml'],
|
||||
'test': ['test/confirm.yml'],
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="event_sale_product_form">
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view" />
|
||||
|
||||
<record model="ir.ui.view" id="event_sale_product_template_form">
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<div name="options" position="after">
|
||||
<field name="event_ok" on_change="onchange_event_ok(type, event_ok, context)"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<label for="event_ok"/>
|
||||
<div name="options" position="inside">
|
||||
<div>
|
||||
<field name="event_ok" on_change="onchange_event_ok(type, event_ok, context)"/>
|
||||
<label for="event_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name='type' position="after">
|
||||
<field name="event_type_id" attrs="{'invisible': [('event_ok', '=', False)],
|
||||
'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="event_type_id" attrs="{'invisible': [('event_ok', '=', False)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -50,20 +51,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="event_sale_product_template_form">
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<div name="options" position="inside">
|
||||
<field name="event_ok" on_change="onchange_event_ok(type, event_ok, context)"/>
|
||||
<label for="event_ok"/>
|
||||
</div>
|
||||
<field name='company_id' position="after">
|
||||
<field name="event_type_id" attrs="{'invisible': [('event_ok', '=', False)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="event_order_line">
|
||||
<field name="name">event.sale.order</field>
|
||||
<field name="model">sale.order</field>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_event_event_ticket_user,event.event.ticket.user,event_sale.model_event_event_ticket,event.group_event_user,1,0,0,0
|
||||
access_event_event_ticket_admin,event.event.ticket.admin,event_sale.model_event_event_ticket,event.group_event_manager,1,1,1,1
|
|
|
@ -392,8 +392,8 @@ class hr_expense_expense(osv.osv):
|
|||
return result
|
||||
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
class product_template(osv.osv):
|
||||
_inherit = "product.template"
|
||||
_columns = {
|
||||
'hr_expense_ok': fields.boolean('Can be Expensed', help="Specify if the product can be selected in an HR expense line."),
|
||||
}
|
||||
|
|
|
@ -191,13 +191,15 @@
|
|||
|
||||
|
||||
<record id="view_product_hr_expense_form" model="ir.ui.view">
|
||||
<field name="name">product.product.expense.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="name">product.template.expense.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="options" position="inside">
|
||||
<field name="hr_expense_ok"/>
|
||||
<label for="hr_expense_ok"/>
|
||||
<div>
|
||||
<field name="hr_expense_ok"/>
|
||||
<label for="hr_expense_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<tr>
|
||||
<td><strong>Address</strong></td>
|
||||
<td colspan="3">
|
||||
<div t-filed="o.employee_id.address_home_id"
|
||||
<div t-field="o.employee_id.address_home_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -114,6 +114,15 @@ class hr_applicant(osv.Model):
|
|||
return int(department_ids[0][0])
|
||||
return None
|
||||
|
||||
def _get_default_company_id(self, cr, uid, department_id=None, context=None):
|
||||
company_id = False
|
||||
if department_id:
|
||||
department = self.pool['hr.department'].browse(cr, uid, department_id, context=context)
|
||||
company_id = department.company_id.id if department and department.company_id else False
|
||||
if not company_id:
|
||||
company_id = self.pool['res.company']._company_default_get(cr, uid, 'hr.applicant', context=context)
|
||||
return company_id
|
||||
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
stage_obj = self.pool.get('hr.recruitment.stage')
|
||||
|
@ -231,7 +240,7 @@ class hr_applicant(osv.Model):
|
|||
'user_id': lambda s, cr, uid, c: uid,
|
||||
'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
|
||||
'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c),
|
||||
'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, s._get_default_department_id(cr, uid, c), c),
|
||||
'color': 0,
|
||||
'date_last_stage_update': fields.datetime.now,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="oe_structure"/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-7">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<div t-field="user.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
</div>
|
||||
|
|
|
@ -669,9 +669,10 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
def message_get_default_recipients(self, cr, uid, ids, context=None):
|
||||
if context and context.get('thread_model') and context['thread_model'] in self.pool and context['thread_model'] != self._name:
|
||||
sub_ctx = dict(context)
|
||||
sub_ctx.pop('thread_model')
|
||||
return self.pool[context['thread_model']].message_get_default_recipients(cr, uid, ids, context=sub_ctx)
|
||||
if hasattr(self.pool[context['thread_model']], 'message_get_default_recipients'):
|
||||
sub_ctx = dict(context)
|
||||
sub_ctx.pop('thread_model')
|
||||
return self.pool[context['thread_model']].message_get_default_recipients(cr, uid, ids, context=sub_ctx)
|
||||
res = {}
|
||||
for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
recipient_ids, email_to, email_cc = set(), False, False
|
||||
|
|
|
@ -919,15 +919,45 @@ openerp.mail = function (session) {
|
|||
this.$('.oe_mail_expand').on('click', this.on_expand);
|
||||
this.$('.oe_mail_reduce').on('click', this.on_expand);
|
||||
this.$('.oe_mail_action_model').on('click', this.on_record_clicked);
|
||||
this.$('.oe_mail_action_author').on('click', this.on_record_author_clicked);
|
||||
},
|
||||
|
||||
on_record_clicked: function (event) {
|
||||
event.preventDefault();
|
||||
var self = this;
|
||||
var state = {
|
||||
'model': this.model,
|
||||
'id': this.res_id,
|
||||
'title': this.record_name
|
||||
};
|
||||
session.webclient.action_manager.do_push_state(state);
|
||||
this.context.params = {
|
||||
model: this.model,
|
||||
res_id: this.res_id,
|
||||
};
|
||||
this.thread.ds_thread.call("message_redirect_action", {context: this.context}).then(function(action){
|
||||
self.do_action(action);
|
||||
});
|
||||
},
|
||||
|
||||
on_record_author_clicked: function (event) {
|
||||
event.preventDefault();
|
||||
var partner_id = $(event.target).data('partner');
|
||||
var state = {
|
||||
'model': 'res.partner',
|
||||
'id': partner_id,
|
||||
'title': this.record_name
|
||||
};
|
||||
session.webclient.action_manager.do_push_state(state);
|
||||
var action = {
|
||||
type:'ir.actions.act_window',
|
||||
view_type: 'form',
|
||||
view_mode: 'form',
|
||||
res_model: 'res.partner',
|
||||
views: [[false, 'form']],
|
||||
res_id: partner_id,
|
||||
}
|
||||
this.do_action(action);
|
||||
},
|
||||
|
||||
/* Call the on_compose_message on the thread of this message. */
|
||||
|
|
|
@ -273,7 +273,7 @@
|
|||
<t t-if="widget.attachment_ids.length > 0">
|
||||
<div class="oe_msg_attachment_list"></div>
|
||||
</t>
|
||||
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-esc="widget.author_id[2]"/></a>
|
||||
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}" t-att-data-partner="widget.author_id[0]" class="oe_mail_action_author"><t t-esc="widget.author_id[2]"/></a>
|
||||
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-esc="widget.author_id[2]"/></span>
|
||||
<t t-if="widget.type == 'notification'">
|
||||
updated document
|
||||
|
@ -293,7 +293,7 @@
|
|||
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
|
||||
t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
|
||||
<span t-attf-class="oe_partner_follower">
|
||||
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-esc="partner[1]"/></a>
|
||||
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}" t-att-data-partner="partner[0]" class="oe_mail_action_author"><t t-esc="partner[1]"/></a>
|
||||
<t t-if="!widget.options.show_link" t-esc="partner[1]"/>
|
||||
</span>
|
||||
<t t-if="!partner_last">,</t>
|
||||
|
|
|
@ -4,10 +4,9 @@ from datetime import datetime
|
|||
from dateutil import relativedelta
|
||||
import json
|
||||
import random
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
from openerp import tools
|
||||
from openerp.exceptions import Warning
|
||||
from openerp.tools.safe_eval import safe_eval as eval
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import osv, fields
|
||||
|
@ -62,6 +61,12 @@ class MassMailingContact(osv.Model):
|
|||
rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
|
||||
return self.name_get(cr, uid, [rec_id], context)[0]
|
||||
|
||||
def message_get_default_recipients(self, cr, uid, ids, context=None):
|
||||
res = {}
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
res[record.id] = {'partner_ids': [], 'email_to': record.email, 'email_cc': False}
|
||||
return res
|
||||
|
||||
|
||||
class MassMailingList(osv.Model):
|
||||
"""Model of a contact list. """
|
||||
|
@ -549,6 +554,8 @@ class MassMailing(osv.Model):
|
|||
for mailing in self.browse(cr, uid, ids, context=context):
|
||||
# instantiate an email composer + send emails
|
||||
res_ids = self.get_recipients(cr, uid, mailing, context=context)
|
||||
if not res_ids:
|
||||
raise Warning('Please select recipients.')
|
||||
comp_ctx = dict(context, active_ids=res_ids)
|
||||
composer_values = {
|
||||
'author_id': author_id,
|
||||
|
|
|
@ -462,7 +462,7 @@ class Product(osv.osv):
|
|||
return super(Product,self).fields_view_get(cr, user, view_id, view_type, context, toolbar, submenu)
|
||||
|
||||
'''Product'''
|
||||
_inherit = 'product.product'
|
||||
_inherit = 'product.template'
|
||||
_columns = {
|
||||
'membership': fields.boolean('Membership', help='Check if the product is eligible for membership.'),
|
||||
'membership_date_from': fields.date('Membership Start Date', help='Date from which membership becomes active.'),
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<record model="ir.ui.view" id="membership_product_search_form_view">
|
||||
<field name="name">membership.product.search.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Membership Products">
|
||||
<field name="name" filter_domain="['|',('name','ilike',self),('code','ilike',self)]" string="Membership Product"/>
|
||||
|
@ -24,10 +24,10 @@
|
|||
|
||||
<record model="ir.ui.view" id="membership_products_tree">
|
||||
<field name="name">Membership products</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="priority">50</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Membership products">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="membership_date_from"/>
|
||||
<field name="membership_date_to"/>
|
||||
|
@ -41,7 +41,8 @@
|
|||
|
||||
<record model="ir.ui.view" id="membership_products_form">
|
||||
<field name="name">Membership Products</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="priority">50</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Membership products" version="7.0">
|
||||
<sheet>
|
||||
|
@ -81,31 +82,27 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_normal_form_view">
|
||||
<record model="ir.ui.view" id="product_template_form_view">
|
||||
<field name="name">Membership Products</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="priority">6</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<page string="Accounting" position="after">
|
||||
<page string="Membership">
|
||||
<group col="1">
|
||||
<group>
|
||||
<field name="membership" readonly="0"/>
|
||||
</group>
|
||||
<group attrs="{'invisible':[('membership','=',False)]}">
|
||||
<field name="membership_date_from" readonly="0" attrs="{'required':[('membership','=',True)]}"/>
|
||||
<field name="membership_date_to" readonly="0" attrs="{'required':[('membership','=',True)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</page>
|
||||
<field name="type" position="after">
|
||||
<field name="membership" readonly="0" attrs="{'invisible': [('type', '!=', 'service')]}"/>
|
||||
</field>
|
||||
<field name="description" position="before">
|
||||
<group attrs="{'invisible':[('membership','=',False)]}">
|
||||
<field name="membership_date_from" readonly="0" attrs="{'required':[('membership','=',True)]}"/>
|
||||
<field name="membership_date_to" readonly="0" attrs="{'required':[('membership','=',True)]}"/>
|
||||
</group>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_membership_products">
|
||||
<field name="name">Membership Products</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="res_model">product.template</field>
|
||||
<field name="domain">[('membership','=',True), ('type', '=', 'service')]</field>
|
||||
<field name="context">{'membership':True, 'type':'service', 'default_membership': True, 'default_type': 'service'}</field>
|
||||
<field name="search_view_id" ref="membership_product_search_form_view"/>
|
||||
|
|
|
@ -178,106 +178,238 @@ class mrp_bom(osv.osv):
|
|||
bom_parent = bom_obj.browse(cr, uid, bom_id, context=context)
|
||||
for bom in self.browse(cr, uid, ids, context=context):
|
||||
if (bom_parent) or (bom.id == bom_id):
|
||||
result[bom.id] = map(lambda x: x.id, bom.bom_lines)
|
||||
result[bom.id] = map(lambda x: x.id, bom.bom_line_ids)
|
||||
else:
|
||||
result[bom.id] = []
|
||||
if bom.bom_lines:
|
||||
if bom.bom_line_ids:
|
||||
continue
|
||||
ok = ((name=='child_complete_ids'))
|
||||
if (bom.type=='phantom' or ok):
|
||||
sids = bom_obj.search(cr, uid, [('bom_id','=',False),('product_id','=',bom.product_id.id)])
|
||||
sids = bom_obj.search(cr, uid, [('product_tmpl_id','=',bom.product_tmpl_id.id)])
|
||||
if sids:
|
||||
bom2 = bom_obj.browse(cr, uid, sids[0], context=context)
|
||||
result[bom.id] += map(lambda x: x.id, bom2.bom_lines)
|
||||
|
||||
result[bom.id] += map(lambda x: x.id, bom2.bom_line_ids)
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64),
|
||||
'code': fields.char('Reference', size=16),
|
||||
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the bills of material without removing it."),
|
||||
'type': fields.selection([('normal', 'Normal BoM'), ('phantom', 'Sets / Phantom')], 'BoM Type', required=True,
|
||||
help= "If a by-product is used in several products, it can be useful to create its own BoM. "\
|
||||
"Though if you don't want separated production orders for this by-product, select Set/Phantom as BoM type. "\
|
||||
"If a Phantom BoM is used for a root product, it will be sold and shipped as a set of components, instead of being produced."),
|
||||
'date_start': fields.date('Valid From', help="Validity of this BoM or component. Keep empty if it's always valid."),
|
||||
'date_stop': fields.date('Valid Until', help="Validity of this BoM or component. Keep empty if it's always valid."),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of bills of material."),
|
||||
'type': fields.selection([('normal', 'Normal'), ('phantom', 'Set')], 'BoM Type', required=True,
|
||||
help= "Set: When processing a sales order for this product, the delivery order will contain the raw materials, instead of the finished product."),
|
||||
'position': fields.char('Internal Reference', size=64, help="Reference to a position in an external plan."),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True),
|
||||
'product_uos_qty': fields.float('Product UOS Qty'),
|
||||
'product_uos': fields.many2one('product.uom', 'Product UOS', help="Product UOS (Unit of Sale) is the unit of measurement for the invoicing and promotion of stock."),
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product', required=True),
|
||||
'product_id': fields.many2one('product.product', 'Product Variant',
|
||||
domain="[('product_tmpl_id','=',product_tmpl_id)]",
|
||||
help="If a product variant is defined the BOM is available only for this product."),
|
||||
'bom_line_ids': fields.one2many('mrp.bom.line', 'bom_id', 'BoM Lines'),
|
||||
|
||||
'product_qty': fields.float('Product Quantity', required=True, digits_compute=dp.get_precision('Product Unit of Measure')),
|
||||
'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True, help="Unit of Measure (Unit of Measure) is the unit of measurement for the inventory control"),
|
||||
'date_start': fields.date('Valid From', help="Validity of this BoM. Keep empty if it's always valid."),
|
||||
'date_stop': fields.date('Valid Until', help="Validity of this BoM. Keep empty if it's always valid."),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of bills of material."),
|
||||
'routing_id': fields.many2one('mrp.routing', 'Routing', help="The list of operations (list of work centers) to produce the finished product. "\
|
||||
"The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production planning."),
|
||||
'product_rounding': fields.float('Product Rounding', help="Rounding applied on the product quantity."),
|
||||
'product_efficiency': fields.float('Manufacturing Efficiency', required=True, help="A factor of 0.9 means a loss of 10% within the production process."),
|
||||
'bom_lines': fields.one2many('mrp.bom', 'bom_id', 'BoM Lines'),
|
||||
'bom_id': fields.many2one('mrp.bom', 'Parent BoM', ondelete='cascade', select=True),
|
||||
'routing_id': fields.many2one('mrp.routing', 'Routing', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production planning."),
|
||||
'property_ids': fields.many2many('mrp.property', 'mrp_bom_property_rel', 'bom_id', 'property_id', 'Properties'),
|
||||
'product_efficiency': fields.float('Manufacturing Efficiency', required=True, help="A factor of 0.9 means a loss of 10% during the production process."),
|
||||
'property_ids': fields.many2many('mrp.property', string='Properties'),
|
||||
'child_complete_ids': fields.function(_child_compute, relation='mrp.bom', string="BoM Hierarchy", type='many2many'),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
}
|
||||
|
||||
def _get_uom_id(self, cr, uid, *args):
|
||||
return self.pool["product.uom"].search(cr, uid, [], limit=1, order='id')[0]
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'product_efficiency': lambda *a: 1.0,
|
||||
'product_qty': lambda *a: 1.0,
|
||||
'product_efficiency': lambda *a: 1.0,
|
||||
'product_rounding': lambda *a: 0.0,
|
||||
'type': lambda *a: 'normal',
|
||||
'product_uom': _get_uom_id,
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.bom', context=c),
|
||||
}
|
||||
_order = "sequence"
|
||||
_parent_name = "bom_id"
|
||||
_sql_constraints = [
|
||||
('bom_qty_zero', 'CHECK (product_qty>0)', 'All product quantities must be greater than 0.\n' \
|
||||
'You should install the mrp_byproduct module if you want to manage extra products on BoMs !'),
|
||||
]
|
||||
|
||||
def _check_recursion(self, cr, uid, ids, context=None):
|
||||
level = 100
|
||||
while len(ids):
|
||||
cr.execute('select distinct bom_id from mrp_bom where id IN %s', (tuple(ids),))
|
||||
ids = filter(None, map(lambda x: x[0], cr.fetchall()))
|
||||
if not level:
|
||||
return False
|
||||
level -= 1
|
||||
return True
|
||||
def _bom_find(self, cr, uid, product_uom, product_tmpl_id=None, product_id=None, properties=None):
|
||||
""" Finds BoM for particular product and product uom.
|
||||
@param product_tmpl_id: Selected product.
|
||||
@param product_uom: Unit of measure of a product.
|
||||
@param properties: List of related properties.
|
||||
@return: False or BoM id.
|
||||
"""
|
||||
if properties is None:
|
||||
properties = []
|
||||
domain = None
|
||||
if product_id:
|
||||
domain = ['|',('product_id', '=', product_id),('product_tmpl_id.product_variant_ids', '=', product_id)]
|
||||
else:
|
||||
domain = [('product_id', '=', False), ('product_tmpl_id', '=', product_tmpl_id)]
|
||||
if product_uom:
|
||||
domain += [('product_uom','=',product_uom)]
|
||||
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
||||
ids = self.search(cr, uid, domain)
|
||||
for bom in self.pool.get('mrp.bom').browse(cr, uid, ids):
|
||||
if not set(map(int,bom.property_ids or [])) - set(properties or []):
|
||||
return bom.id
|
||||
return False
|
||||
|
||||
def _check_product(self, cr, uid, ids, context=None):
|
||||
all_prod = []
|
||||
boms = self.browse(cr, uid, ids, context=context)
|
||||
def check_bom(boms):
|
||||
res = True
|
||||
for bom in boms:
|
||||
if bom.product_id.id in all_prod:
|
||||
res = res and False
|
||||
all_prod.append(bom.product_id.id)
|
||||
lines = bom.bom_lines
|
||||
if lines:
|
||||
res = res and check_bom([bom_id for bom_id in lines if bom_id not in boms])
|
||||
def _bom_explode(self, cr, uid, bom, product, factor, properties=None, level=0, routing_id=False, previous_products=None, master_bom=None):
|
||||
""" Finds Products and Work Centers for related BoM for manufacturing order.
|
||||
@param bom: BoM of particular product template.
|
||||
@param product: Select a particular variant of the BoM. If False use BoM without variants.
|
||||
@param factor: Factor of product UoM.
|
||||
@param properties: A List of properties Ids.
|
||||
@param level: Depth level to find BoM lines starts from 10.
|
||||
@param previous_products: List of product previously use by bom explore to avoid recursion
|
||||
@param master_bom: When recursion, used to display the name of the master bom
|
||||
@return: result: List of dictionaries containing product details.
|
||||
result2: List of dictionaries containing Work Center details.
|
||||
"""
|
||||
routing_obj = self.pool.get('mrp.routing')
|
||||
all_prod = [] + (previous_products or [])
|
||||
master_bom = master_bom or bom
|
||||
|
||||
def _factor(factor, product_efficiency, product_rounding):
|
||||
factor = factor / (product_efficiency or 1.0)
|
||||
factor = _common.ceiling(factor, product_rounding)
|
||||
if factor < product_rounding:
|
||||
factor = product_rounding
|
||||
return factor
|
||||
|
||||
factor = _factor(factor, bom.product_efficiency, bom.product_rounding)
|
||||
|
||||
result = []
|
||||
result2 = []
|
||||
|
||||
routing = (routing_id and routing_obj.browse(cr, uid, routing_id)) or bom.routing_id or False
|
||||
if routing:
|
||||
for wc_use in routing.workcenter_lines:
|
||||
wc = wc_use.workcenter_id
|
||||
d, m = divmod(factor, wc_use.workcenter_id.capacity_per_cycle)
|
||||
mult = (d + (m and 1.0 or 0.0))
|
||||
cycle = mult * wc_use.cycle_nbr
|
||||
result2.append({
|
||||
'name': tools.ustr(wc_use.name) + ' - ' + tools.ustr(bom.product_tmpl_id.name_get()[0][1]),
|
||||
'workcenter_id': wc.id,
|
||||
'sequence': level + (wc_use.sequence or 0),
|
||||
'cycle': cycle,
|
||||
'hour': float(wc_use.hour_nbr * mult + ((wc.time_start or 0.0) + (wc.time_stop or 0.0) + cycle * (wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)),
|
||||
})
|
||||
|
||||
for bom_line_id in bom.bom_line_ids:
|
||||
if bom_line_id.date_start and bom_line_id.date_start > time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) or \
|
||||
bom_line_id.date_stop and bom_line_id.date_stop > time.strftime(DEFAULT_SERVER_DATETIME_FORMAT):
|
||||
continue
|
||||
# check properties
|
||||
if set(map(int,bom_line_id.property_ids or [])) - set(properties or []):
|
||||
continue
|
||||
# all bom_line_id variant values must be in the product
|
||||
if bom_line_id.attribute_value_ids:
|
||||
if not product or (set(map(int,bom_line_id.attribute_value_ids or [])) - set(map(int,product.attribute_value_ids))):
|
||||
continue
|
||||
|
||||
if bom_line_id.product_id.id in all_prod:
|
||||
raise osv.except_osv(_('Invalid Action!'), _('BoM "%s" contains a BoM line with a product recursion: "%s".') % (master_bom.name,bom_line_id.product_id.name_get()[0][1]))
|
||||
all_prod.append(bom_line_id.product_id.id)
|
||||
|
||||
if bom_line_id.type != "phantom":
|
||||
result.append({
|
||||
'name': bom_line_id.product_id.name,
|
||||
'product_id': bom_line_id.product_id.id,
|
||||
'product_qty': _factor(bom_line_id.product_qty * factor, bom_line_id.product_efficiency, bom_line_id.product_rounding),
|
||||
'product_uom': bom_line_id.product_uom.id,
|
||||
'product_uos_qty': bom_line_id.product_uos and bom_line_id.product_uos_qty * factor or False,
|
||||
'product_uos': bom_line_id.product_uos and bom_line_id.product_uos.id or False,
|
||||
})
|
||||
else:
|
||||
bom_id = self._bom_find(cr, uid, bom_line_id.product_uom.id, product_id=bom_line_id.product_id.id, properties=properties)
|
||||
bom2 = self.browse(cr, uid, bom_id)
|
||||
if bom2:
|
||||
res = self._bom_explode(cr, uid, bom2, bom_line_id.product_id, factor,
|
||||
properties=properties, level=level + 10, previous_products=all_prod, master_bom=master_bom)
|
||||
result = result + res[0]
|
||||
result2 = result2 + res[1]
|
||||
else:
|
||||
raise osv.except_osv(_('Invalid Action!'), _('BoM "%s" contains a phantom BoM line but the product "%s" don\'t have any BoM defined.') % (master_bom.name,bom_line_id.product_id.name_get()[0][1]))
|
||||
|
||||
return result, result2
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
bom_data = self.read(cr, uid, id, [], context=context)
|
||||
default.update(name=_("%s (copy)") % (bom_data['name']))
|
||||
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
|
||||
|
||||
def onchange_uom(self, cr, uid, ids, product_tmpl_id, product_uom, context=None):
|
||||
res = {'value': {}}
|
||||
if not product_uom or not product_tmpl_id:
|
||||
return res
|
||||
return check_bom(boms)
|
||||
product = self.pool.get('product.template').browse(cr, uid, product_tmpl_id, context=context)
|
||||
uom = self.pool.get('product.uom').browse(cr, uid, product_uom, context=context)
|
||||
if uom.category_id.id != product.uom_id.category_id.id:
|
||||
res['warning'] = {'title': _('Warning'), 'message': _('The Product Unit of Measure you chose has a different category than in the product form.')}
|
||||
res['value'].update({'product_uom': product.uom_id.id})
|
||||
return res
|
||||
|
||||
_constraints = [
|
||||
(_check_recursion, 'Error ! You cannot create recursive BoM.', ['parent_id']),
|
||||
(_check_product, 'BoM line product should not be same as BoM product.', ['product_id']),
|
||||
]
|
||||
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, name, product_qty=0, context=None):
|
||||
def onchange_product_tmpl_id(self, cr, uid, ids, product_tmpl_id, product_qty=0, context=None):
|
||||
""" Changes UoM and name if product_id changes.
|
||||
@param name: Name of the field
|
||||
@param product_id: Changed product_id
|
||||
@return: Dictionary of changed values
|
||||
"""
|
||||
res = {}
|
||||
if product_id:
|
||||
prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
res['value'] = {'name': prod.name, 'product_uom': prod.uom_id.id, 'product_uos_qty': 0, 'product_uos': False}
|
||||
if prod.uos_id.id:
|
||||
res['value']['product_uos_qty'] = product_qty * prod.uos_coeff
|
||||
res['value']['product_uos'] = prod.uos_id.id
|
||||
if product_tmpl_id:
|
||||
prod = self.pool.get('product.template').browse(cr, uid, product_tmpl_id, context=context)
|
||||
res['value'] = {
|
||||
'name': prod.name,
|
||||
'product_uom': prod.uom_id.id,
|
||||
}
|
||||
return res
|
||||
|
||||
class mrp_bom_line(osv.osv):
|
||||
_name = 'mrp.bom.line'
|
||||
_order = "sequence"
|
||||
|
||||
_columns = {
|
||||
'type': fields.selection([('normal', 'Normal'), ('phantom', 'Phantom')], 'BoM Line Type', required=True,
|
||||
help="Phantom: this product line will not appear in the raw materials of manufacturing orders,"
|
||||
"it will be directly replaced by the raw materials of its own BoM, without triggering"
|
||||
"an extra manufacturing order."),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True),
|
||||
'product_uos_qty': fields.float('Product UOS Qty'),
|
||||
'product_uos': fields.many2one('product.uom', 'Product UOS', help="Product UOS (Unit of Sale) is the unit of measurement for the invoicing and promotion of stock."),
|
||||
'product_qty': fields.float('Product Quantity', required=True, digits_compute=dp.get_precision('Product Unit of Measure')),
|
||||
'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True,
|
||||
help="Unit of Measure (Unit of Measure) is the unit of measurement for the inventory control"),
|
||||
|
||||
'date_start': fields.date('Valid From', help="Validity of component. Keep empty if it's always valid."),
|
||||
'date_stop': fields.date('Valid Until', help="Validity of component. Keep empty if it's always valid."),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying."),
|
||||
'routing_id': fields.many2one('mrp.routing', 'Routing', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production planning."),
|
||||
'product_rounding': fields.float('Product Rounding', help="Rounding applied on the product quantity."),
|
||||
'product_efficiency': fields.float('Manufacturing Efficiency', required=True, help="A factor of 0.9 means a loss of 10% within the production process."),
|
||||
'property_ids': fields.many2many('mrp.property', string='Properties'),
|
||||
|
||||
'bom_id': fields.many2one('mrp.bom', 'Parent BoM', ondelete='cascade', select=True, required=True),
|
||||
'attribute_value_ids': fields.many2many('product.attribute.value', string='Variants', help="BOM Product Variants needed form apply this line."),
|
||||
}
|
||||
|
||||
def _get_uom_id(self, cr, uid, *args):
|
||||
return self.pool["product.uom"].search(cr, uid, [], limit=1, order='id')[0]
|
||||
_defaults = {
|
||||
'product_qty': lambda *a: 1.0,
|
||||
'product_efficiency': lambda *a: 1.0,
|
||||
'product_rounding': lambda *a: 0.0,
|
||||
'type': lambda *a: 'normal',
|
||||
'product_uom': _get_uom_id,
|
||||
}
|
||||
_sql_constraints = [
|
||||
('bom_qty_zero', 'CHECK (product_qty>0)', 'All product quantities must be greater than 0.\n' \
|
||||
'You should install the mrp_byproduct module if you want to manage extra products on BoMs !'),
|
||||
]
|
||||
|
||||
def onchange_uom(self, cr, uid, ids, product_id, product_uom, context=None):
|
||||
res = {'value': {}}
|
||||
if not product_uom or not product_id:
|
||||
|
@ -289,96 +421,23 @@ class mrp_bom(osv.osv):
|
|||
res['value'].update({'product_uom': product.uom_id.id})
|
||||
return res
|
||||
|
||||
def _bom_find(self, cr, uid, product_id, product_uom, properties=None):
|
||||
""" Finds BoM for particular product and product uom.
|
||||
@param product_id: Selected product.
|
||||
@param product_uom: Unit of measure of a product.
|
||||
@param properties: List of related properties.
|
||||
@return: False or BoM id.
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, product_qty=0, context=None):
|
||||
""" Changes UoM if product_id changes.
|
||||
@param product_id: Changed product_id
|
||||
@return: Dictionary of changed values
|
||||
"""
|
||||
if properties is None:
|
||||
properties = []
|
||||
domain = [('product_id', '=', product_id), ('bom_id', '=', False),
|
||||
'|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
||||
ids = self.search(cr, uid, domain)
|
||||
max_prop = 0
|
||||
result = False
|
||||
for bom in self.pool.get('mrp.bom').browse(cr, uid, ids):
|
||||
prop = 0
|
||||
for prop_id in bom.property_ids:
|
||||
if prop_id.id in properties:
|
||||
prop += 1
|
||||
if (prop > max_prop) or ((max_prop == 0) and not result):
|
||||
result = bom.id
|
||||
max_prop = prop
|
||||
return result
|
||||
|
||||
def _bom_explode(self, cr, uid, bom, factor, properties=None, addthis=False, level=0, routing_id=False):
|
||||
""" Finds Products and Work Centers for related BoM for manufacturing order.
|
||||
@param bom: BoM of particular product.
|
||||
@param factor: Factor of product UoM.
|
||||
@param properties: A List of properties Ids.
|
||||
@param addthis: If BoM found then True else False.
|
||||
@param level: Depth level to find BoM lines starts from 10.
|
||||
@return: result: List of dictionaries containing product details.
|
||||
result2: List of dictionaries containing Work Center details.
|
||||
"""
|
||||
routing_obj = self.pool.get('mrp.routing')
|
||||
factor = factor / (bom.product_efficiency or 1.0)
|
||||
factor = _common.ceiling(factor, bom.product_rounding)
|
||||
if factor < bom.product_rounding:
|
||||
factor = bom.product_rounding
|
||||
result = []
|
||||
result2 = []
|
||||
phantom = False
|
||||
if bom.type == 'phantom' and not bom.bom_lines:
|
||||
newbom = self._bom_find(cr, uid, bom.product_id.id, bom.product_uom.id, properties)
|
||||
|
||||
if newbom:
|
||||
res = self._bom_explode(cr, uid, self.browse(cr, uid, [newbom])[0], factor * bom.product_qty, properties, addthis=True, level=level + 10)
|
||||
result = result + res[0]
|
||||
result2 = result2 + res[1]
|
||||
phantom = True
|
||||
else:
|
||||
phantom = False
|
||||
if not phantom:
|
||||
if addthis and not bom.bom_lines:
|
||||
result.append({
|
||||
'name': bom.product_id.name,
|
||||
'product_id': bom.product_id.id,
|
||||
'product_qty': bom.product_qty * factor,
|
||||
'product_uom': bom.product_uom.id,
|
||||
'product_uos_qty': bom.product_uos and bom.product_uos_qty * factor or False,
|
||||
'product_uos': bom.product_uos and bom.product_uos.id or False,
|
||||
})
|
||||
routing = (routing_id and routing_obj.browse(cr, uid, routing_id)) or bom.routing_id or False
|
||||
if routing:
|
||||
for wc_use in routing.workcenter_lines:
|
||||
wc = wc_use.workcenter_id
|
||||
d, m = divmod(factor, wc_use.workcenter_id.capacity_per_cycle)
|
||||
mult = (d + (m and 1.0 or 0.0))
|
||||
cycle = mult * wc_use.cycle_nbr
|
||||
result2.append({
|
||||
'name': tools.ustr(wc_use.name) + ' - ' + tools.ustr(bom.product_id.name),
|
||||
'workcenter_id': wc.id,
|
||||
'sequence': level + (wc_use.sequence or 0),
|
||||
'cycle': cycle,
|
||||
'hour': float(wc_use.hour_nbr * mult + ((wc.time_start or 0.0) + (wc.time_stop or 0.0) + cycle * (wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)),
|
||||
})
|
||||
for bom2 in bom.bom_lines:
|
||||
res = self._bom_explode(cr, uid, bom2, factor, properties, addthis=True, level=level + 10)
|
||||
result = result + res[0]
|
||||
result2 = result2 + res[1]
|
||||
return result, result2
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
bom_data = self.read(cr, uid, id, [], context=context)
|
||||
default.update(name=_("%s (copy)") % (bom_data['name']), bom_id=False)
|
||||
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
|
||||
|
||||
res = {}
|
||||
if product_id:
|
||||
prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
res['value'] = {
|
||||
'product_uom': prod.uom_id.id,
|
||||
'product_uos_qty': 0,
|
||||
'product_uos': False
|
||||
}
|
||||
if prod.uos_id.id:
|
||||
res['value']['product_uos_qty'] = product_qty * prod.uos_coeff
|
||||
res['value']['product_uos'] = prod.uos_id.id
|
||||
return res
|
||||
|
||||
class mrp_production(osv.osv):
|
||||
"""
|
||||
|
@ -475,7 +534,7 @@ class mrp_production(osv.osv):
|
|||
'date_planned': fields.datetime('Scheduled Date', required=True, select=1, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'date_start': fields.datetime('Start Date', select=True, readonly=True),
|
||||
'date_finished': fields.datetime('End Date', select=True, readonly=True),
|
||||
'bom_id': fields.many2one('mrp.bom', 'Bill of Material', domain=[('bom_id', '=', False)], readonly=True, states={'draft': [('readonly', False)]},
|
||||
'bom_id': fields.many2one('mrp.bom', 'Bill of Material', readonly=True, states={'draft': [('readonly', False)]},
|
||||
help="Bill of Materials allow you to define the list of required raw materials to make a finished product."),
|
||||
'routing_id': fields.many2one('mrp.routing', string='Routing', on_delete='set null', readonly=True, states={'draft': [('readonly', False)]},
|
||||
help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production plannification."),
|
||||
|
@ -586,7 +645,7 @@ class mrp_production(osv.osv):
|
|||
}}
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
bom_id = bom_obj._bom_find(cr, uid, product.id, product.uom_id and product.uom_id.id, [])
|
||||
bom_id = bom_obj._bom_find(cr, uid, product.uom_id and product.uom_id.id, product_id=product.id, properties=[])
|
||||
routing_id = False
|
||||
if bom_id:
|
||||
bom_point = bom_obj.browse(cr, uid, bom_id, context=context)
|
||||
|
@ -635,7 +694,7 @@ class mrp_production(osv.osv):
|
|||
bom_point = production.bom_id
|
||||
bom_id = production.bom_id.id
|
||||
if not bom_point:
|
||||
bom_id = bom_obj._bom_find(cr, uid, production.product_id.id, production.product_uom.id, properties)
|
||||
bom_id = bom_obj._bom_find(cr, uid, production.product_uom.id, product_id=production.product_id.id, properties=properties)
|
||||
if bom_id:
|
||||
bom_point = bom_obj.browse(cr, uid, bom_id)
|
||||
routing_id = bom_point.routing_id.id or False
|
||||
|
@ -646,9 +705,8 @@ class mrp_production(osv.osv):
|
|||
|
||||
# get components and workcenter_lines from BoM structure
|
||||
factor = uom_obj._compute_qty(cr, uid, production.product_uom.id, production.product_qty, bom_point.product_uom.id)
|
||||
res = bom_obj._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, properties, routing_id=production.routing_id.id)
|
||||
results = res[0] # product_lines
|
||||
results2 = res[1] # workcenter_lines
|
||||
# product_lines, workcenter_lines
|
||||
results, results2 = bom_obj._bom_explode(cr, uid, bom_point, production.product_id, factor / bom_point.product_qty, properties, routing_id=production.routing_id.id)
|
||||
# reset product_lines in production order
|
||||
for line in results:
|
||||
line['production_id'] = production.id
|
||||
|
@ -777,15 +835,18 @@ class mrp_production(osv.osv):
|
|||
dicts = {}
|
||||
# Find product qty to be consumed and consume it
|
||||
for scheduled in production.product_lines:
|
||||
consumed_qty = consumed_data.get(scheduled.product_id.id, 0.0)
|
||||
product_id = scheduled.product_id.id
|
||||
|
||||
consumed_qty = consumed_data.get(product_id, 0.0)
|
||||
|
||||
# qty available for consume and produce
|
||||
qty_avail = scheduled.product_qty - consumed_qty
|
||||
if qty_avail <= 0.0:
|
||||
# there will be nothing to consume for this raw material
|
||||
continue
|
||||
|
||||
if not dicts.get(scheduled.product_id.id):
|
||||
dicts[scheduled.product_id.id] = {}
|
||||
if not dicts.get(product_id):
|
||||
dicts[product_id] = {}
|
||||
|
||||
# total qty of consumed product we need after this consumption
|
||||
total_consume = ((product_qty + produced_qty) * scheduled.product_qty / production.product_qty)
|
||||
|
@ -795,9 +856,8 @@ class mrp_production(osv.osv):
|
|||
for move in production.move_lines:
|
||||
if qty <= 0.0:
|
||||
break
|
||||
if move.product_id.id != scheduled.product_id.id:
|
||||
if move.product_id.id != product_id:
|
||||
continue
|
||||
product_id = scheduled.product_id.id
|
||||
|
||||
q = min(move.product_qty, qty)
|
||||
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, scheduled.product_id, q, domain=[('qty', '>', 0.0)],
|
||||
|
@ -895,7 +955,8 @@ class mrp_production(osv.osv):
|
|||
#consumed more in wizard than previously planned
|
||||
product = self.pool.get('product.product').browse(cr, uid, consume['product_id'], context=context)
|
||||
extra_move_id = self._make_consume_line_from_data(cr, uid, production, product, product.uom_id.id, remaining_qty, False, 0, context=context)
|
||||
stock_mov_obj.action_done(cr, uid, [extra_move_id], context=context)
|
||||
if extra_move_id:
|
||||
stock_mov_obj.action_done(cr, uid, [extra_move_id], context=context)
|
||||
|
||||
self.message_post(cr, uid, production_id, body=_("%s produced") % self._description, context=context)
|
||||
self.signal_button_produce_done(cr, uid, [production_id])
|
||||
|
@ -1111,24 +1172,4 @@ class mrp_production_product_line(osv.osv):
|
|||
'production_id': fields.many2one('mrp.production', 'Production Order', select=True),
|
||||
}
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
def _bom_orders_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
Bom = self.pool('mrp.bom')
|
||||
Production = self.pool('mrp.production')
|
||||
return {
|
||||
product_id: {
|
||||
'bom_count': Bom.search_count(cr, uid, [('product_id', '=', product_id), ('bom_id', '=', False)], context=context),
|
||||
'mo_count': Production.search_count(cr,uid, [('product_id', '=', product_id)], context=context),
|
||||
'bom_strct': Bom.search_count(cr, uid, [('product_id', '=', product_id), ('bom_id', '=', False)], context=context),
|
||||
}
|
||||
for product_id in ids
|
||||
}
|
||||
_columns = {
|
||||
'bom_ids': fields.one2many('mrp.bom', 'product_id', 'Bill of Materials'),
|
||||
'bom_count': fields.function(_bom_orders_count, string='# Bill of Material', type='integer', multi="_bom_order_count"),
|
||||
'bom_strct': fields.function(_bom_orders_count, string='# Bill of Material Structure', type='integer', multi="_bom_order_count"),
|
||||
'mo_count': fields.function(_bom_orders_count, string='# Manufacturing Orders', type='integer', multi="_bom_order_count"),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -245,16 +245,14 @@
|
|||
|
||||
<record id="mrp_bom_1" model="mrp.bom">
|
||||
<field name="name">HDD 500GB</field>
|
||||
<field name="product_id" ref="product.product_product_18"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_18_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="routing_id" ref="mrp_routing_0"/>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_2" model="mrp.bom">
|
||||
<field name="name">320GB HDD</field>
|
||||
<record id="mrp_bom_line_1" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_17"/>
|
||||
<field name="product_qty">2</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
|
@ -263,398 +261,394 @@
|
|||
<field name="bom_id" ref="mrp_bom_1"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_3" model="mrp.bom">
|
||||
<record id="mrp_bom_2" model="mrp.bom">
|
||||
<field name="name">HDD 2TB on Demand</field>
|
||||
<field name="product_id" ref="product.product_product_19"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_19_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="routing_id" ref="mrp_routing_1"/>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_4" model="mrp.bom">
|
||||
<field name="name">HDD 500GB</field>
|
||||
<record id="mrp_bom_line_2" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_18"/>
|
||||
<field name="product_qty">4</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_2"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_3" model="mrp.bom">
|
||||
<field name="name">HDD on Demand</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_19_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_line_3" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_17"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_3"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_5" model="mrp.bom">
|
||||
<field name="name">HDD on Demand</field>
|
||||
<field name="product_id" ref="product.product_product_19"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_6" model="mrp.bom">
|
||||
<field name="name">320GB HDD</field>
|
||||
<field name="product_id" ref="product.product_product_17"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_5"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_7" model="mrp.bom">
|
||||
<record id="mrp_bom_4" model="mrp.bom">
|
||||
<field name="name">Laptop Customized</field>
|
||||
<field name="product_id" ref="product.product_product_27"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_27_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="routing_id" ref="mrp_routing_1"/>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_8" model="mrp.bom">
|
||||
<field name="name">Windows 7 Professional</field>
|
||||
<record id="mrp_bom_line_4" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_40"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
<field name="bom_id" ref="mrp_bom_4"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_9" model="mrp.bom">
|
||||
<field name="name">USB Keyboard, QWERTY</field>
|
||||
<record id="mrp_bom_line_5" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_8"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
<field name="bom_id" ref="mrp_bom_4"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_10" model="mrp.bom">
|
||||
<field name="name">Mouse, Wireless</field>
|
||||
<record id="mrp_bom_line_6" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
<field name="bom_id" ref="mrp_bom_4"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_11" model="mrp.bom">
|
||||
<record id="mrp_bom_5" model="mrp.bom">
|
||||
<field name="name">Laptop Customized + Azerty</field>
|
||||
<field name="product_id" ref="product.product_product_27"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_27_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_12" model="mrp.bom">
|
||||
<field name="name">Windows 7 Professional</field>
|
||||
<record id="mrp_bom_line_7" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_40"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
<field name="bom_id" ref="mrp_bom_5"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_13" model="mrp.bom">
|
||||
<field name="name">USB Keyboard, AZERTY</field>
|
||||
<record id="mrp_bom_line_8" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_9"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
<field name="bom_id" ref="mrp_bom_5"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_14" model="mrp.bom">
|
||||
<field name="name">Mouse, Laser</field>
|
||||
<record id="mrp_bom_line_9" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_11"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
<field name="bom_id" ref="mrp_bom_5"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_15" model="mrp.bom">
|
||||
<record id="mrp_bom_6" model="mrp.bom">
|
||||
<field name="name">Computer Case-1</field>
|
||||
<field name="product_id" ref="product.product_product_16"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_16_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_16" model="mrp.bom">
|
||||
<field name="name">Processesor AMD 8-Core</field>
|
||||
<record id="mrp_bom_line_10" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_23"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_15"/>
|
||||
<field name="bom_id" ref="mrp_bom_6"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_17" model="mrp.bom">
|
||||
<field name="name">Motherboard I9P57</field>
|
||||
<record id="mrp_bom_line_11" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_20"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_15"/>
|
||||
<field name="bom_id" ref="mrp_bom_6"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_18" model="mrp.bom">
|
||||
<field name="name">HDD 320GB</field>
|
||||
<record id="mrp_bom_line_12" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_17"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">8</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_15"/>
|
||||
<field name="bom_id" ref="mrp_bom_6"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_19" model="mrp.bom">
|
||||
<record id="mrp_bom_7" model="mrp.bom">
|
||||
<field name="name">Computer Case-2</field>
|
||||
<field name="product_id" ref="product.product_product_16"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_16_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_20" model="mrp.bom">
|
||||
<field name="name">Processor Core i5 2.70 Ghz</field>
|
||||
<record id="mrp_bom_line_13" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_22"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_19"/>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_21" model="mrp.bom">
|
||||
<field name="name">Motherboard A20Z7</field>
|
||||
<record id="mrp_bom_line_14" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_21"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_19"/>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_22" model="mrp.bom">
|
||||
<field name="name">HDD 500GB</field>
|
||||
<record id="mrp_bom_line_15" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_18"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_19"/>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_23" model="mrp.bom">
|
||||
<field name="name">Graphics Card</field>
|
||||
<record id="mrp_bom_line_16" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_24"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_19"/>
|
||||
<field name="bom_id" ref="mrp_bom_7"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_24" model="mrp.bom">
|
||||
<record id="mrp_bom_8" model="mrp.bom">
|
||||
<field name="name">PC Assemble + 2GB RAM</field>
|
||||
<field name="product_id" ref="product.product_product_4"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_3_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="type">phantom</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_25" model="mrp.bom">
|
||||
<field name="name">15" LCD Monitor </field>
|
||||
<record id="mrp_bom_line_17" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_6"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_26" model="mrp.bom">
|
||||
<field name="name">Computer Case-1</field>
|
||||
<record id="mrp_bom_line_18" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_16"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_27" model="mrp.bom">
|
||||
<field name="name">Mouse, Laser</field>
|
||||
<record id="mrp_bom_line_19" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_11"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_28" model="mrp.bom">
|
||||
<field name="name">USB Keyboard, QWERTY</field>
|
||||
<record id="mrp_bom_line_20" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_8"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">8</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_29" model="mrp.bom">
|
||||
<field name="name">RAM DDR2 1GB</field>
|
||||
<record id="mrp_bom_line_21" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_15"/>
|
||||
<field name="product_qty">2</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_30" model="mrp.bom">
|
||||
<record id="mrp_bom_9" model="mrp.bom">
|
||||
<field name="name">PC Assemble + 512MB RAM</field>
|
||||
<field name="product_id" ref="product.product_product_3"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_3_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="routing_id" ref="mrp_routing_2"/>
|
||||
<field name="type">phantom</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_31" model="mrp.bom">
|
||||
<field name="name">17" LCD Monitor</field>
|
||||
<record id="mrp_bom_line_22" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_7"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_30"/>
|
||||
<field name="bom_id" ref="mrp_bom_9"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_32" model="mrp.bom">
|
||||
<field name="name">Computer Case-2</field>
|
||||
<record id="mrp_bom_line_23" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_16"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_30"/>
|
||||
<field name="bom_id" ref="mrp_bom_9"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_33" model="mrp.bom">
|
||||
<field name="name">Mouse, Laser</field>
|
||||
<record id="mrp_bom_line_24" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_11"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_30"/>
|
||||
<field name="bom_id" ref="mrp_bom_9"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_34" model="mrp.bom">
|
||||
<field name="name">USB Keyboard, QWERTY</field>
|
||||
<record id="mrp_bom_line_25" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_8"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">8</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_30"/>
|
||||
<field name="bom_id" ref="mrp_bom_9"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_35" model="mrp.bom">
|
||||
<field name="name">RAM DDR 512MB</field>
|
||||
<record id="mrp_bom_line_26" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_13"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_30"/>
|
||||
<field name="bom_id" ref="mrp_bom_9"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_36" model="mrp.bom">
|
||||
<record id="mrp_bom_10" model="mrp.bom">
|
||||
<field name="name">PC Assemble + Custom RAM (PC on Demand)</field>
|
||||
<field name="product_id" ref="product.product_product_5"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_5_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="routing_id" ref="mrp_routing_2"/>
|
||||
<field name="type">phantom</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_37" model="mrp.bom">
|
||||
<field name="name">15" LCD Monitor </field>
|
||||
<record id="mrp_bom_line_27" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_6"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_36"/>
|
||||
<field name="bom_id" ref="mrp_bom_10"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_38" model="mrp.bom">
|
||||
<field name="name">Computer Case-1</field>
|
||||
<record id="mrp_bom_line_28" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_16"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_36"/>
|
||||
<field name="bom_id" ref="mrp_bom_10"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_39" model="mrp.bom">
|
||||
<field name="name">RAM DDR 512MB</field>
|
||||
<record id="mrp_bom_line_29" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_13"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">6</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_36"/>
|
||||
<field name="bom_id" ref="mrp_bom_10"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_40" model="mrp.bom">
|
||||
<field name="name">Mouse, Laser</field>
|
||||
<record id="mrp_bom_line_30" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_11"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">8</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_36"/>
|
||||
<field name="bom_id" ref="mrp_bom_10"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_41" model="mrp.bom">
|
||||
<field name="name">USB Keyboard, QWERTY</field>
|
||||
<record id="mrp_bom_line_31" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_8"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_36"/>
|
||||
<field name="bom_id" ref="mrp_bom_10"/>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_11" model="mrp.bom">
|
||||
<field name="name">iPad Retina Display</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_4_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">1</field>
|
||||
<field name="type">normal</field>
|
||||
</record>
|
||||
<record id="mrp_bom_line_32" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_14"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">1</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_1')])]"/>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
</record>
|
||||
<record id="mrp_bom_line_33" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_15"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_2')])]"/>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
</record>
|
||||
<record id="mrp_bom_line_34" model="mrp.bom.line">
|
||||
<field name="product_id" ref="product.product_product_23"/>
|
||||
<field name="product_qty">1</field>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">3</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="bom_id" ref="mrp_bom_11"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mrp_production_1" model="mrp.production">
|
||||
<field name="product_id" ref="product.product_product_4"/>
|
||||
<field name="product_id" ref="product.product_product_3"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="product_qty">3</field>
|
||||
<field name="location_src_id" ref="stock.stock_location_stock"/>
|
||||
<field name="location_dest_id" ref="stock.stock_location_output"/>
|
||||
<field name="bom_id" ref="mrp_bom_24"/>
|
||||
<field name="bom_id" ref="mrp_bom_8"/>
|
||||
<field name="routing_id" ref="mrp.mrp_routing_2"/>
|
||||
</record>
|
||||
|
||||
|
@ -663,7 +657,7 @@
|
|||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="location_src_id" ref="stock.stock_location_stock"/>
|
||||
<field name="location_dest_id" ref="stock.stock_location_output"/>
|
||||
<field name="bom_id" ref="mrp.mrp_bom_7"/>
|
||||
<field name="bom_id" ref="mrp.mrp_bom_4"/>
|
||||
<field name="routing_id" ref="mrp.mrp_routing_1"/>
|
||||
</record>
|
||||
<workflow action="button_confirm" model="mrp.production" ref="mrp_production_1"/>
|
||||
|
|
|
@ -347,22 +347,17 @@
|
|||
<form string="Bill of Material" version="7.0">
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name, product_qty, context)" class="oe_inline"/>
|
||||
<field name="product_tmpl_id" on_change="onchange_product_tmpl_id(product_tmpl_id, product_qty, context)"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom" class="oe_inline" on_change="onchange_uom(product_tmpl_id, product_uom)" groups="product.group_uom"/>
|
||||
<label for="product_qty" string="Quantity"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline" on_change="onchange_product_id(product_id, name, product_qty, context)"/>
|
||||
<field name="product_uom" class="oe_inline" on_change="onchange_uom(product_id, product_uom)" groups="product.group_uom"/>
|
||||
</div>
|
||||
<label for="product_uos_qty" groups="product.group_uos"/>
|
||||
<div groups="product.group_uos" >
|
||||
<field name="product_uos_qty"
|
||||
class="oe_inline"/>
|
||||
<label string="-" attrs="{'invisible':[('product_uos','=',False)]}" class="oe_inline"/>
|
||||
<field name="product_uos" class="oe_inline"/>
|
||||
<field name="product_qty" class="oe_inline" on_change="onchange_product_tmpl_id(product_tmpl_id, product_qty, context)"/>
|
||||
<field name="product_uom" class="oe_inline" on_change="onchange_uom(product_tmpl_id, product_uom)" groups="product.group_uom"/>
|
||||
</div>
|
||||
<label for="routing_id" class="oe_inline" groups="mrp.group_mrp_routings"/>
|
||||
<div groups="mrp.group_mrp_routings">
|
||||
<field name="routing_id" class="oe_inline"/>
|
||||
<field name="routing_id" class="oe_inline"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
|
@ -378,14 +373,19 @@
|
|||
</group>
|
||||
<notebook>
|
||||
<page string="Components">
|
||||
<field name="bom_lines" widget="one2many_list">
|
||||
<field name="bom_line_ids" widget="one2many_list">
|
||||
<tree string="Components" editable="bottom">
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name)"/>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, product_qty)"/>
|
||||
<field name="type"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_rounding"/>
|
||||
<field name="product_efficiency"/>
|
||||
<field name="product_uom" on_change="onchange_uom(product_id, product_uom)" groups="product.group_uom"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="routing_id"/>
|
||||
<field name="attribute_value_ids" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
|
@ -393,7 +393,6 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="position"/>
|
||||
<field name="bom_id"/>
|
||||
<field name="sequence"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
|
@ -422,11 +421,11 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Search Bill Of Material">
|
||||
<field name="name" string="Bill Of Material" filter_domain="['|',('name','ilike',self),('code','ilike',self)]"/>
|
||||
<field name="bom_lines" string="Components"/>
|
||||
<field name="product_id"/>
|
||||
<field name="bom_line_ids" string="Components"/>
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_tmpl_id'}"/>
|
||||
<filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'product_uom'}"/>
|
||||
<filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
|
||||
|
@ -439,13 +438,13 @@
|
|||
<record id="mrp_bom_tree_view" model="ir.ui.view">
|
||||
<field name="name">mrp.bom.tree</field>
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<!--field name="field_parent">child_complete_ids</field-->
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Bill of Materials">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="code"/>
|
||||
<field name="type"/>
|
||||
|
@ -455,32 +454,12 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="mrp_bom_component_tree_view" model="ir.ui.view">
|
||||
<field name="name">mrp.bom.component.tree</field>
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="BoM Structure">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="name" groups="base.group_no_one"/>
|
||||
<field name="code"/>
|
||||
<field name="product_id"/>
|
||||
<field name="bom_id" groups="product.group_mrp_properties"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="type"/>
|
||||
<field name="routing_id" groups="mrp.group_mrp_routings"/>
|
||||
<field name="date_start" groups="product.group_mrp_properties"/>
|
||||
<field name="date_stop" groups="product.group_mrp_properties"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_form_action" model="ir.actions.act_window">
|
||||
<field name="name">Bill of Materials</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.bom</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('bom_id','=',False)]</field>
|
||||
<field name="search_view_id" ref="view_mrp_bom_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
|
@ -495,13 +474,56 @@
|
|||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_component_tree_view" model="ir.ui.view">
|
||||
<field name="name">mrp.bom.component.tree</field>
|
||||
<field name="model">mrp.bom.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Components" editable="top">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="bom_id"/>
|
||||
<field name="product_id" on_change="onchange_product_id(product_id)"/>
|
||||
<field name="type"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_rounding"/>
|
||||
<field name="product_efficiency"/>
|
||||
<field name="product_uom" on_change="onchange_uom(product_id, product_uom)" groups="product.group_uom"/>
|
||||
<field name="product_uos_qty" groups="product.group_uos"/>
|
||||
<field name="product_uos" groups="product.group_uos"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="routing_id"/>
|
||||
<field name="attribute_value_ids" widget="many2many_tags"/>
|
||||
<field name="property_ids" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_mrp_bom_line_filter" model="ir.ui.view">
|
||||
<field name="name">mrp.bom.line.select</field>
|
||||
<field name="model">mrp.bom.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Bill Of Material Components">
|
||||
<field name="bom_id"/>
|
||||
<field name="product_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Bill Of Material" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'bom_id'}"/>
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'product_uom'}"/>
|
||||
<filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
|
||||
<filter string=" Valid From Month" icon="terp-go-month" domain="[]" context="{'group_by':'date_start'}" help="Valid From Date by Month"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_form_action2" model="ir.actions.act_window">
|
||||
<field name="name">Bill of Material Components</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.bom</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="mrp_bom_component_tree_view"/>
|
||||
<field name="domain">[]</field>
|
||||
<field name="res_model">mrp.bom.line</field>
|
||||
<field name="view_type">tree</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a component to a bill of material.
|
||||
|
@ -512,47 +534,32 @@
|
|||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_search_form_view_procurment" model="ir.ui.view">
|
||||
<field name="name">product.search.bom</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_search_form_view"/>
|
||||
|
||||
<record id="product_template_search_view_procurment" model="ir.ui.view">
|
||||
<field name="name">product.template.search.bom</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_search_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@string='Consumable']" position="after">
|
||||
<separator/>
|
||||
<filter string="Components" name="components" icon="terp-accessories-archiver" domain="[('bom_ids','not in',[]),('bom_ids.bom_id','!=',False)]"/>
|
||||
<filter string="Components" name="components" icon="terp-accessories-archiver" domain="[('bom_ids','not in',[])]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view_inherit" model="ir.ui.view">
|
||||
<field name="name">product.template.form.view.inherited</field>
|
||||
<field name="name">product.product.form.view.inherited</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='warranty']" position="before">
|
||||
<label for="produce_delay"/>
|
||||
<div>
|
||||
<group name="sale_condition" position="inside">
|
||||
<label for="produce_delay" attrs="{'invisible':[('type','=','service')]}"/>
|
||||
<div attrs="{'invisible':[('type','=','service')]}">
|
||||
<field name="produce_delay" class="oe_inline"/> days
|
||||
</div>
|
||||
</xpath>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_normal_procurement_locations_form_inherited" model="ir.ui.view">
|
||||
<field name="name">product.normal.procurement.locations.inherited</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='procurement_uom']" position="after">
|
||||
<group name="delay" string="Delays" attrs="{'invisible':[('type','=','service')]}">
|
||||
<label for="produce_delay" />
|
||||
<div attrs="{'invisible':[('type','=','service')]}">
|
||||
<field name="produce_delay" class="oe_inline" style="vertical-align:baseline"/> days
|
||||
</div>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_mrp_product_form_inherited" model="ir.ui.view">
|
||||
<field name="name">product.form.mrp.inherited</field>
|
||||
|
@ -686,7 +693,7 @@
|
|||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id" on_change="product_id_change(product_id, product_qty)" domain="[('bom_ids','!=',False),('bom_ids.bom_id','=',False),('bom_ids.type','!=','phantom')]" class="oe_inline" context='{"default_type": "product"}'/>
|
||||
<field name="product_id" on_change="product_id_change(product_id, product_qty)" domain="[('bom_ids','!=',False),('bom_ids.type','!=','phantom')]" class="oe_inline" context='{"default_type": "product"}'/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline" on_change="product_id_change(product_id, product_qty)"/>
|
||||
|
@ -980,7 +987,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//field[@name='origin']" position="before">
|
||||
<field name="bom_id" domain="[('product_id','=',product_id),('bom_id','=',False)]"/>
|
||||
<field name="bom_id" domain="[('product_id','=',product_id)]"/>
|
||||
<field name="production_id" attrs="{'invisible': [('production_id','=',False)]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='origin']" position="after">
|
||||
|
@ -992,7 +999,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Menu for Resource for MRP-->
|
||||
|
||||
<record id="mrp_workcenter_action" model="ir.actions.act_window">
|
||||
|
@ -1027,16 +1033,9 @@
|
|||
id="menu_mrp_production_order_action" name="Order Planning"
|
||||
parent="menu_mrp_planning" sequence="1"/>
|
||||
|
||||
<record id="act_product_mrp_bom_open" model="ir.actions.act_window">
|
||||
<field name="name">BoM Structure</field>
|
||||
<field name="context">{'default_product_id': active_id}</field>
|
||||
<field name="domain">[('product_id', 'in', active_ids),('bom_id','=',False)]</field>
|
||||
<field name="res_model">mrp.bom</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="product_open_bom">
|
||||
<field name="context">{'default_product_id': active_id, 'search_default_product_id': active_id}</field>
|
||||
<field name="context">{'default_product_tmpl_id': active_id, 'search_default_product_tmpl_id': active_id}</field>
|
||||
<field name="name">Bill of Materials</field>
|
||||
<field name="domain">[('bom_id','=',False)]</field>
|
||||
<field name="res_model">mrp.bom</field>
|
||||
<field name="view_type">form</field>
|
||||
</record>
|
||||
|
@ -1046,25 +1045,21 @@
|
|||
<field name="res_model">mrp.production</field>
|
||||
<field name="view_id" ref="mrp_production_tree_view"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="product_form_view_bom_button">
|
||||
<field name="name">product.product.procurement</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<record model="ir.ui.view" id="product_template_form_view_bom_button">
|
||||
<field name="name">product.template.procurement</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<div name="buttons" position="inside">
|
||||
<button class="oe_inline oe_stat_button" name="%(product_open_bom)d" type="action"
|
||||
groups="mrp.group_mrp_user" attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-flask">
|
||||
<field string="Bill of Materials" name="bom_count" widget="statinfo" />
|
||||
</button>
|
||||
<button class="oe_inline oe_stat_button" name="%(act_product_mrp_bom_open)d" type="action"
|
||||
groups="mrp.group_mrp_user" attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-flask">
|
||||
<field string="BoM Structure" name="bom_strct" widget="statinfo" />
|
||||
</button>
|
||||
<button class="oe_inline oe_stat_button" name="%(act_product_mrp_production)d" type="action"
|
||||
groups="mrp.group_mrp_user" attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-list-alt">
|
||||
<field string="Manufacturing" name="mo_count" widget="statinfo" />
|
||||
</button>
|
||||
</xpath>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ class procurement_order(osv.osv):
|
|||
"""
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
properties = [x.id for x in procurement.property_ids]
|
||||
bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, procurement.product_id.id, procurement.product_uom.id, properties)
|
||||
bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, procurement.product_uom.id,
|
||||
product_id=procurement.product_id.id, properties=properties)
|
||||
if not bom_id:
|
||||
return False
|
||||
return True
|
||||
|
@ -83,7 +84,8 @@ class procurement_order(osv.osv):
|
|||
routing_id = procurement.bom_id.routing_id.id
|
||||
else:
|
||||
properties = [x.id for x in procurement.property_ids]
|
||||
bom_id = bom_obj._bom_find(cr, uid, procurement.product_id.id, procurement.product_uom.id, properties)
|
||||
bom_id = bom_obj._bom_find(cr, uid, procurement.product_uom.id,
|
||||
product_id=procurement.product_id.id, properties=properties)
|
||||
bom = bom_obj.browse(cr, uid, bom_id, context=context)
|
||||
routing_id = bom.routing_id.id
|
||||
|
||||
|
|
|
@ -20,19 +20,30 @@
|
|||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
class product_template(osv.osv):
|
||||
_inherit = "product.template"
|
||||
def _bom_orders_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
Bom = self.pool('mrp.bom')
|
||||
res = {}
|
||||
for product_tmpl_id in ids:
|
||||
nb = Bom.search_count(cr, uid, [('product_tmpl_id', '=', product_tmpl_id)], context=context)
|
||||
res[product_tmpl_id] = {
|
||||
'bom_count': nb,
|
||||
}
|
||||
return res
|
||||
|
||||
def _bom_orders_count_mo(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for product_tmpl_id in self.browse(cr, uid, ids):
|
||||
res[product_tmpl_id.id] = sum([p.mo_count for p in product_tmpl_id.product_variant_ids])
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
"bom_ids": fields.one2many('mrp.bom', 'product_id','Bill of Materials', domain=[('bom_id','=',False)]),
|
||||
"produce_delay": fields.float('Manufacturing Lead Time', help="Average delay in days to produce this product. In the case of multi-level BOM, the manufacturing lead times of the components will be added."),
|
||||
'track_production': fields.boolean('Track Manufacturing Lots', help="Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
"produce_delay": 1,
|
||||
"bom_ids": fields.one2many('mrp.bom', 'product_tmpl_id','Bill of Materials'),
|
||||
'bom_count': fields.function(_bom_orders_count, string='# Bill of Material', type='integer', multi="_bom_order_count"),
|
||||
'mo_count': fields.function(_bom_orders_count_mo, string='# Manufacturing Orders', type='integer'),
|
||||
}
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if not default:
|
||||
|
@ -40,7 +51,26 @@ class product_product(osv.osv):
|
|||
default.update({
|
||||
'bom_ids': []
|
||||
})
|
||||
return super(product_product, self).copy(cr, uid, id, default, context=context)
|
||||
return super(product_template, self).copy(cr, uid, id, default, context=context)
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
def _bom_orders_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
Production = self.pool('mrp.production')
|
||||
res = {}
|
||||
for product_id in ids:
|
||||
res[product_id] = Production.search_count(cr,uid, [('product_id', '=', product_id)], context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
"produce_delay": fields.float('Manufacturing Lead Time', help="Average delay in days to produce this product. In the case of multi-level BOM, the manufacturing lead times of the components will be added."),
|
||||
'track_production': fields.boolean('Track Manufacturing Lots', help="Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order"),
|
||||
'mo_count': fields.function(_bom_orders_count, string='# Manufacturing Orders', type='integer'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
"produce_delay": 1,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ class report_custom(report_rml):
|
|||
|
||||
for product in product_pool.browse(cr, uid, ids, context=context):
|
||||
product_uom_name = to_xml(product.uom_id.name)
|
||||
bom_id = bom_pool._bom_find(cr, uid, product.id, product.uom_id.id)
|
||||
bom_id = bom_pool._bom_find(cr, uid, product.uom_id.id, product_id=product.id)
|
||||
title = "<title>%s</title>" %(_("Cost Structure"))
|
||||
title += "<title>%s</title>" % (to_xml(product.name))
|
||||
xml += "<lines style='header'>" + title + prod_header + "</lines>"
|
||||
|
@ -168,7 +168,7 @@ class report_custom(report_rml):
|
|||
else:
|
||||
bom = bom_pool.browse(cr, uid, bom_id, context=context)
|
||||
factor = number * product.uom_id.factor / bom.product_uom.factor
|
||||
sub_boms = bom_pool._bom_explode(cr, uid, bom, factor / bom.product_qty)
|
||||
sub_boms = bom_pool._bom_explode(cr, uid, bom, product, factor / bom.product_qty)
|
||||
total = 0
|
||||
total_strd = 0
|
||||
parent_bom = {
|
||||
|
|
|
@ -4,6 +4,7 @@ access_mrp_workcenter,mrp.workcenter,model_mrp_workcenter,mrp.group_mrp_user,1,0
|
|||
access_mrp_routing,mrp.routing,model_mrp_routing,mrp.group_mrp_user,1,0,0,0
|
||||
access_mrp_routing_workcenter,mrp.routing.workcenter,model_mrp_routing_workcenter,mrp.group_mrp_user,1,0,0,0
|
||||
access_mrp_bom,mrp.bom,model_mrp_bom,group_mrp_user,1,0,0,0
|
||||
access_mrp_bom_line,mrp.bom.line,model_mrp_bom_line,group_mrp_user,1,0,0,0
|
||||
access_mrp_production,mrp.production user,model_mrp_production,mrp.group_mrp_user,1,1,1,1
|
||||
access_mrp_production_salesman,mrp.production salesman,model_mrp_production,base.group_sale_salesman,1,1,1,0
|
||||
access_mrp_production_product_line_salesman,mrp.production.product.line salesman,model_mrp_production_product_line,base.group_sale_salesman,1,0,1,0
|
||||
|
@ -14,6 +15,7 @@ access_mrp_workcenter_manager,mrp.workcenter.manager,model_mrp_workcenter,mrp.gr
|
|||
access_mrp_routing_manager,mrp.routing.manager,model_mrp_routing,mrp.group_mrp_manager,1,1,1,1
|
||||
access_mrp_routing_workcenter_manager,mrp.routing.workcenter.manager,model_mrp_routing_workcenter,mrp.group_mrp_manager,1,1,1,1
|
||||
access_mrp_bom_manager,mrp.bom.manager,model_mrp_bom,mrp.group_mrp_manager,1,1,1,1
|
||||
access_mrp_bom_line_manager,mrp.bom.line.manager,model_mrp_bom_line,mrp.group_mrp_manager,1,1,1,1
|
||||
access_stock_location_mrp_worker,stock.location mrp_worker,stock.model_stock_location,mrp.group_mrp_user,1,0,0,0
|
||||
access_stock_move_mrp_worker,stock.move mrp_worker,stock.model_stock_move,mrp.group_mrp_user,1,1,1,0
|
||||
access_stock_picking_mrp_worker,stock.picking mrp_worker,stock.model_stock_picking,mrp.group_mrp_user,1,1,1,1
|
||||
|
@ -55,6 +57,8 @@ access_report_mrp_inout_user,report.mrp.inout user,model_report_mrp_inout,mrp.gr
|
|||
access_report_workcenter_load_user,report.workcenter.load.user,model_report_workcenter_load,mrp.group_mrp_user,1,0,0,0
|
||||
access_mrp_bom_salesman,mrp.bom,model_mrp_bom,base.group_sale_salesman,1,0,0,0
|
||||
access_mrp_bom_stockuser,mrp.bom,model_mrp_bom,stock.group_stock_user,1,0,0,0
|
||||
access_mrp_bom_line_salesman,mrp.bom.line,model_mrp_bom_line,base.group_sale_salesman,1,0,0,0
|
||||
access_mrp_bom_line_stockuser,mrp.bom.line,model_mrp_bom_line,stock.group_stock_user,1,0,0,0
|
||||
access_product_uom_categ_mrp_manager,product.uom.categ mrp_manager,product.model_product_uom_categ,mrp.group_mrp_manager,1,1,1,1
|
||||
access_product_uom_mrp_manager,product.uom mrp_manager,product.model_product_uom,mrp.group_mrp_manager,1,1,1,1
|
||||
access_product_ul_mrp_manager,product.ul mrp_manager,product.model_product_ul,mrp.group_mrp_manager,1,1,1,1
|
||||
|
|
|
|
@ -55,13 +55,14 @@ class StockMove(osv.osv):
|
|||
user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
||||
#doing the search as SUPERUSER because a user with the permission to write on a stock move should be able to explode it
|
||||
#without giving him the right to read the boms.
|
||||
return self.pool.get('mrp.bom').search(cr, SUPERUSER_ID, [
|
||||
('product_id', '=', move.product_id.id),
|
||||
('bom_id', '=', False),
|
||||
domain = [
|
||||
'|', ('product_id', '=', move.product_id.id),
|
||||
'&', ('product_id', '=', False), ('product_tmpl_id.product_variant_ids', '=', move.product_id.id),
|
||||
('type', '=', 'phantom'),
|
||||
'|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
('company_id', '=', user_company)], context=context)
|
||||
('company_id', '=', user_company)]
|
||||
return self.pool.get('mrp.bom').search(cr, SUPERUSER_ID, domain, context=context)
|
||||
|
||||
def _action_explode(self, cr, uid, move, context=None):
|
||||
""" Explodes pickings.
|
||||
|
@ -76,7 +77,7 @@ class StockMove(osv.osv):
|
|||
if bis:
|
||||
factor = move.product_qty
|
||||
bom_point = bom_obj.browse(cr, SUPERUSER_ID, bis[0], context=context)
|
||||
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, factor, [])
|
||||
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, move.product_id, factor, [])
|
||||
state = 'confirmed'
|
||||
if move.state == 'assigned':
|
||||
state = 'assigned'
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
!record {model: mrp.bom, id: mrp_bom_test1}:
|
||||
company_id: base.main_company
|
||||
name: PC Assemble SC234
|
||||
product_tmpl_id: product.product_product_3_product_template
|
||||
product_id: product.product_product_3
|
||||
product_uom: product.product_uom_unit
|
||||
product_qty: 1.0
|
||||
type: normal
|
||||
bom_lines:
|
||||
- company_id: base.main_company
|
||||
name: On Site Assistance
|
||||
product_id: product.product_product_2
|
||||
bom_line_ids:
|
||||
- product_id: product.product_product_2
|
||||
product_uom: product.product_uom_unit
|
||||
product_qty: 1.0
|
||||
- company_id: base.main_company
|
||||
name: GrapWorks Software
|
||||
product_id: product.product_product_44
|
||||
- product_id: product.product_product_44
|
||||
product_uom: product.product_uom_unit
|
||||
product_qty: 1.0
|
||||
-
|
||||
I make the production order using BoM having one service type product and one consumable product.
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
I create Production Order of PC Assemble SC349 to produce 5.0 Unit.
|
||||
-
|
||||
!record {model: mrp.production, id: mrp_production_test1}:
|
||||
product_id: product.product_product_4
|
||||
product_id: product.product_product_3
|
||||
product_qty: 5.0
|
||||
location_src_id: stock.stock_location_14
|
||||
location_dest_id: stock.stock_location_output
|
||||
bom_id: mrp_bom_24
|
||||
bom_id: mrp_bom_9
|
||||
routing_id: mrp.mrp_routing_1
|
||||
|
||||
|
||||
|
|
|
@ -27,10 +27,9 @@
|
|||
</td>
|
||||
<td><span t-field="o.code"/></td>
|
||||
</tr>
|
||||
<tr t-foreach="get_children(o.bom_lines)" t-as="l">
|
||||
<tr t-foreach="get_children(o.bom_line_ids)" t-as="l">
|
||||
<td>
|
||||
<span style="color: white;" t-esc="'... '*(l['level'])"/>
|
||||
- <span t-esc="l['name']"/>
|
||||
</td>
|
||||
<td>
|
||||
[ <span t-esc="l['pcode']"/> ]
|
||||
|
|
|
@ -78,7 +78,7 @@ class change_production_qty(osv.osv_memory):
|
|||
bom_point = prod.bom_id
|
||||
bom_id = prod.bom_id.id
|
||||
if not bom_point:
|
||||
bom_id = bom_obj._bom_find(cr, uid, prod.product_id.id, prod.product_uom.id)
|
||||
bom_id = bom_obj._bom_find(cr, uid, prod.product_uom.id, product_id=prod.product_id.id)
|
||||
if not bom_id:
|
||||
raise osv.except_osv(_('Error!'), _("Cannot find bill of material for this product."))
|
||||
prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id})
|
||||
|
@ -89,7 +89,7 @@ class change_production_qty(osv.osv_memory):
|
|||
|
||||
factor = prod.product_qty * prod.product_uom.factor / bom_point.product_uom.factor
|
||||
product_details, workcenter_details = \
|
||||
bom_obj._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, [])
|
||||
bom_obj._bom_explode(cr, uid, bom_point, prod.product_id, factor / bom_point.product_qty, [])
|
||||
for r in product_details:
|
||||
if r['product_id'] == move.product_id.id:
|
||||
move_obj.write(cr, uid, [move.id], {'product_uom_qty': r['product_qty']})
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
-
|
||||
I add a sub product in Bill of material for product External Hard Disk.
|
||||
-
|
||||
!record {model: mrp.bom, id: mrp.mrp_bom_24}:
|
||||
!record {model: mrp.bom, id: mrp.mrp_bom_9}:
|
||||
product_id: product.product_product_28
|
||||
name: External Hard Disk + Subproduct
|
||||
product_uom: product.product_uom_unit
|
||||
|
@ -20,7 +20,7 @@
|
|||
product_id: product.product_product_28
|
||||
product_qty: 2.0
|
||||
product_uom: product.product_uom_unit
|
||||
bom_id: mrp.mrp_bom_24
|
||||
bom_id: mrp.mrp_bom_9
|
||||
location_src_id: stock.stock_location_stock
|
||||
-
|
||||
I compute the data of production order.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<div class="col-xs-5 col-xs-offset-1">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
</div>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
|
@ -16,4 +16,7 @@ class AccountPaymentConfig(osv.TransientModel):
|
|||
'module_payment_adyen': fields.boolean(
|
||||
'Manage Payments Using Adyen',
|
||||
help='-It installs the module payment_adyen.'),
|
||||
'module_payment_buckaroo': fields.boolean(
|
||||
'Manage Payments Using Buckaroo',
|
||||
help='-It installs the module payment_buckaroo.'),
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
<field name="module_payment_adyen" class="oe_inline"/>
|
||||
<label for="module_payment_adyen"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="module_payment_buckaroo" class="oe_inline"/>
|
||||
<label for="module_payment_buckaroo"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2014-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -18,7 +19,5 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import product_manufacturer
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
import models
|
||||
import controllers
|
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
{
|
||||
'name': 'Buckaroo Payment Acquirer',
|
||||
'category': 'Hidden',
|
||||
'summary': 'Payment Acquirer: Buckaroo Implementation',
|
||||
'version': '1.0',
|
||||
'description': """Buckaroo Payment Acquirer""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['payment'],
|
||||
'data': [
|
||||
'views/buckaroo.xml',
|
||||
'views/payment_acquirer.xml',
|
||||
'data/buckaroo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import main
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
import logging
|
||||
import pprint
|
||||
import werkzeug
|
||||
|
||||
from openerp import http, SUPERUSER_ID
|
||||
from openerp.http import request
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BuckarooController(http.Controller):
|
||||
_return_url = '/payment/buckaroo/return'
|
||||
_cancel_url = '/payment/buckaroo/cancel'
|
||||
_exception_url = '/payment/buckaroo/error'
|
||||
_reject_url = '/payment/buckaroo/reject'
|
||||
|
||||
@http.route([
|
||||
'/payment/buckaroo/return',
|
||||
'/payment/buckaroo/cancel',
|
||||
'/payment/buckaroo/error',
|
||||
'/payment/buckaroo/reject',
|
||||
], type='http', auth='none')
|
||||
def buckaroo_return(self, **post):
|
||||
""" Buckaroo."""
|
||||
_logger.info('Buckaroo: entering form_feedback with post data %s', pprint.pformat(post)) # debug
|
||||
request.registry['payment.transaction'].form_feedback(request.cr, SUPERUSER_ID, post, 'buckaroo', context=request.context)
|
||||
return_url = post.pop('return_url', '')
|
||||
if not return_url:
|
||||
data ='' + post.pop('ADD_RETURNDATA', '{}').replace("'", "\"")
|
||||
custom = json.loads(data)
|
||||
return_url = custom.pop('return_url', '/')
|
||||
return werkzeug.utils.redirect(return_url)
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="payment_acquirer_buckaroo" model="payment.acquirer">
|
||||
<field name="name">Buckaroo</field>
|
||||
<field name="provider">buckaroo</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="view_template_id" ref="buckaroo_acquirer_button"/>
|
||||
<field name="environment">test</field>
|
||||
<field name="pre_msg"><![CDATA[
|
||||
<p>You will be redirected to the Buckaroo website after cliking on the payment button.</p>]]></field>
|
||||
<field name="brq_websitekey">dummy</field>
|
||||
<field name="brq_secretkey">dummy</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import buckaroo
|
|
@ -0,0 +1,191 @@
|
|||
# -*- coding: utf-'8' "-*-"
|
||||
from hashlib import sha1
|
||||
import logging
|
||||
import urlparse
|
||||
|
||||
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
||||
from openerp.addons.payment_buckaroo.controllers.main import BuckarooController
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.float_utils import float_compare
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AcquirerBuckaroo(osv.Model):
|
||||
_inherit = 'payment.acquirer'
|
||||
|
||||
def _get_buckaroo_urls(self, cr, uid, environment, context=None):
|
||||
""" Buckaroo URLs
|
||||
"""
|
||||
if environment == 'prod':
|
||||
return {
|
||||
'buckaroo_form_url': 'https://checkout.buckaroo.nl/html/',
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'buckaroo_form_url': 'https://testcheckout.buckaroo.nl/html/',
|
||||
}
|
||||
|
||||
def _get_providers(self, cr, uid, context=None):
|
||||
providers = super(AcquirerBuckaroo, self)._get_providers(cr, uid, context=context)
|
||||
providers.append(['buckaroo', 'Buckaroo'])
|
||||
return providers
|
||||
|
||||
_columns = {
|
||||
'brq_websitekey': fields.char('WebsiteKey', required_if_provider='buckaroo'),
|
||||
'brq_secretkey': fields.char('SecretKey', required_if_provider='buckaroo'),
|
||||
}
|
||||
|
||||
def _buckaroo_generate_digital_sign(self, acquirer, inout, values):
|
||||
""" Generate the shasign for incoming or outgoing communications.
|
||||
|
||||
:param browse acquirer: the payment.acquirer browse record. It should
|
||||
have a shakey in shaky out
|
||||
:param string inout: 'in' (openerp contacting buckaroo) or 'out' (buckaroo
|
||||
contacting openerp).
|
||||
:param dict values: transaction values
|
||||
|
||||
:return string: shasign
|
||||
"""
|
||||
assert inout in ('in', 'out')
|
||||
assert acquirer.provider == 'buckaroo'
|
||||
|
||||
keys = "add_returndata Brq_amount Brq_culture Brq_currency Brq_invoicenumber Brq_return Brq_returncancel Brq_returnerror Brq_returnreject brq_test Brq_websitekey".split()
|
||||
|
||||
def get_value(key):
|
||||
if values.get(key):
|
||||
return values[key]
|
||||
return ''
|
||||
|
||||
if inout == 'out':
|
||||
if 'BRQ_SIGNATURE' in values:
|
||||
del values['BRQ_SIGNATURE']
|
||||
items = sorted((k.upper(), v) for k, v in values.items())
|
||||
sign = ''.join('%s=%s' % (k, v) for k, v in items)
|
||||
else:
|
||||
sign = ''.join('%s=%s' % (k,get_value(k)) for k in keys)
|
||||
#Add the pre-shared secret key at the end of the signature
|
||||
sign = sign + acquirer.brq_secretkey
|
||||
if isinstance(sign, str):
|
||||
sign = urlparse.parse_qsl(sign)
|
||||
shasign = sha1(sign).hexdigest()
|
||||
return shasign
|
||||
|
||||
|
||||
def buckaroo_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None):
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
||||
acquirer = self.browse(cr, uid, id, context=context)
|
||||
buckaroo_tx_values = dict(tx_values)
|
||||
buckaroo_tx_values.update({
|
||||
'Brq_websitekey': acquirer.brq_websitekey,
|
||||
'Brq_amount': tx_values['amount'],
|
||||
'Brq_currency': tx_values['currency'] and tx_values['currency'].name or '',
|
||||
'Brq_invoicenumber': tx_values['reference'],
|
||||
'brq_test' : True,
|
||||
'Brq_return': '%s' % urlparse.urljoin(base_url, BuckarooController._return_url),
|
||||
'Brq_returncancel': '%s' % urlparse.urljoin(base_url, BuckarooController._cancel_url),
|
||||
'Brq_returnerror': '%s' % urlparse.urljoin(base_url, BuckarooController._exception_url),
|
||||
'Brq_returnreject': '%s' % urlparse.urljoin(base_url, BuckarooController._reject_url),
|
||||
'Brq_culture': 'en-US',
|
||||
})
|
||||
if buckaroo_tx_values.get('return_url'):
|
||||
buckaroo_tx_values['add_returndata'] = {'return_url': '%s' % buckaroo_tx_values.pop('return_url')}
|
||||
else:
|
||||
buckaroo_tx_values['add_returndata'] = ''
|
||||
buckaroo_tx_values['Brq_signature'] = self._buckaroo_generate_digital_sign(acquirer, 'in', buckaroo_tx_values)
|
||||
return partner_values, buckaroo_tx_values
|
||||
|
||||
def buckaroo_get_form_action_url(self, cr, uid, id, context=None):
|
||||
acquirer = self.browse(cr, uid, id, context=context)
|
||||
return self._get_buckaroo_urls(cr, uid, acquirer.environment, context=context)['buckaroo_form_url']
|
||||
|
||||
class TxBuckaroo(osv.Model):
|
||||
_inherit = 'payment.transaction'
|
||||
|
||||
# buckaroo status
|
||||
_buckaroo_valid_tx_status = [190]
|
||||
_buckaroo_pending_tx_status = [790, 791, 792, 793]
|
||||
_buckaroo_cancel_tx_status = [890, 891]
|
||||
_buckaroo_error_tx_status = [490, 491, 492]
|
||||
_buckaroo_reject_tx_status = [690]
|
||||
|
||||
_columns = {
|
||||
'buckaroo_txnid': fields.char('Transaction ID'),
|
||||
}
|
||||
|
||||
|
||||
# --------------------------------------------------
|
||||
# FORM RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def _buckaroo_form_get_tx_from_data(self, cr, uid, data, context=None):
|
||||
""" Given a data dict coming from buckaroo, verify it and find the related
|
||||
transaction record. """
|
||||
reference, pay_id, shasign = data.get('BRQ_INVOICENUMBER'), data.get('BRQ_PAYMENT'), data.get('BRQ_SIGNATURE')
|
||||
if not reference or not pay_id or not shasign:
|
||||
error_msg = 'Buckaroo: received data with missing reference (%s) or pay_id (%s) or shashign (%s)' % (reference, pay_id, shasign)
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
tx_ids = self.search(cr, uid, [('reference', '=', reference)], context=context)
|
||||
if not tx_ids or len(tx_ids) > 1:
|
||||
error_msg = 'Buckaroo: received data for reference %s' % (reference)
|
||||
if not tx_ids:
|
||||
error_msg += '; no order found'
|
||||
else:
|
||||
error_msg += '; multiple order found'
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
|
||||
|
||||
#verify shasign
|
||||
shasign_check = self.pool['payment.acquirer']._buckaroo_generate_digital_sign(tx.acquirer_id, 'out' ,data)
|
||||
if shasign_check.upper() != shasign.upper():
|
||||
error_msg = 'Buckaroo: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data)
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
return tx
|
||||
|
||||
def _buckaroo_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
|
||||
invalid_parameters = []
|
||||
|
||||
if tx.acquirer_reference and data.get('BRQ_TRANSACTIONS') != tx.acquirer_reference:
|
||||
invalid_parameters.append(('Transaction Id', data.get('BRQ_TRANSACTIONS'), tx.acquirer_reference))
|
||||
# check what is buyed
|
||||
if float_compare(float(data.get('BRQ_AMOUNT', '0.0')), tx.amount, 2) != 0:
|
||||
invalid_parameters.append(('Amount', data.get('BRQ_AMOUNT'), '%.2f' % tx.amount))
|
||||
if data.get('BRQ_CURRENCY') != tx.currency_id.name:
|
||||
invalid_parameters.append(('Currency', data.get('BRQ_CURRENCY'), tx.currency_id.name))
|
||||
|
||||
return invalid_parameters
|
||||
|
||||
def _buckaroo_form_validate(self, cr, uid, tx, data, context=None):
|
||||
status_code = int(data.get('BRQ_STATUSCODE','0'))
|
||||
if status_code in self._buckaroo_valid_tx_status:
|
||||
tx.write({
|
||||
'state': 'done',
|
||||
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
||||
})
|
||||
return True
|
||||
elif status_code in self._buckaroo_pending_tx_status:
|
||||
tx.write({
|
||||
'state': 'pending',
|
||||
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
||||
})
|
||||
return True
|
||||
elif status_code in self._buckaroo_cancel_tx_status:
|
||||
tx.write({
|
||||
'state': 'cancel',
|
||||
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
||||
})
|
||||
return True
|
||||
else:
|
||||
error = 'Buckaroo: feedback error'
|
||||
_logger.info(error)
|
||||
tx.write({
|
||||
'state': 'error',
|
||||
'state_message': error,
|
||||
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
||||
})
|
||||
return False
|
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.addons.payment_buckaroo.tests import test_buckaroo
|
||||
|
||||
checks = [
|
||||
test_buckaroo,
|
||||
]
|
|
@ -0,0 +1,178 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from lxml import objectify
|
||||
import urlparse
|
||||
|
||||
import openerp
|
||||
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
||||
from openerp.addons.payment.tests.common import PaymentAcquirerCommon
|
||||
from openerp.addons.payment_buckaroo.controllers.main import BuckarooController
|
||||
from openerp.tools import mute_logger
|
||||
|
||||
|
||||
@openerp.tests.common.at_install(False)
|
||||
@openerp.tests.common.post_install(False)
|
||||
class BuckarooCommon(PaymentAcquirerCommon):
|
||||
|
||||
def setUp(self):
|
||||
super(BuckarooCommon, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||
|
||||
# get the buckaroo account
|
||||
model, self.buckaroo_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_buckaroo', 'payment_acquirer_buckaroo')
|
||||
|
||||
|
||||
@openerp.tests.common.at_install(False)
|
||||
@openerp.tests.common.post_install(False)
|
||||
class BuckarooForm(BuckarooCommon):
|
||||
|
||||
def test_10_Buckaroo_form_render(self):
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
# be sure not to do stupid things
|
||||
buckaroo = self.payment_acquirer.browse(self.cr, self.uid, self.buckaroo_id, None)
|
||||
self.assertEqual(buckaroo.environment, 'test', 'test without test environment')
|
||||
|
||||
# ----------------------------------------
|
||||
# Test: button direct rendering
|
||||
# ----------------------------------------
|
||||
|
||||
form_values = {
|
||||
'add_returndata': None,
|
||||
'Brq_websitekey': buckaroo.brq_websitekey,
|
||||
'Brq_amount': '2240.0',
|
||||
'Brq_currency': 'EUR',
|
||||
'Brq_invoicenumber': 'SO004',
|
||||
'Brq_signature': '1b8c10074c622d965272a91a9e88b5b3777d2474', # update me
|
||||
'brq_test': 'True',
|
||||
'Brq_return': '%s' % urlparse.urljoin(self.base_url, BuckarooController._return_url),
|
||||
'Brq_returncancel': '%s' % urlparse.urljoin(self.base_url, BuckarooController._cancel_url),
|
||||
'Brq_returnerror': '%s' % urlparse.urljoin(self.base_url, BuckarooController._exception_url),
|
||||
'Brq_returnreject': '%s' % urlparse.urljoin(self.base_url, BuckarooController._reject_url),
|
||||
'Brq_culture': 'en-US',
|
||||
}
|
||||
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, self.buckaroo_id,
|
||||
'SO004', 2240.0, self.currency_euro_id,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
self.assertEqual(tree.get('action'), 'https://testcheckout.buckaroo.nl/html/', 'Buckaroo: wrong form POST url')
|
||||
for form_input in tree.input:
|
||||
if form_input.get('name') in ['submit']:
|
||||
continue
|
||||
self.assertEqual(
|
||||
form_input.get('value'),
|
||||
form_values[form_input.get('name')],
|
||||
'Buckaroo: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
|
||||
)
|
||||
|
||||
# ----------------------------------------
|
||||
# Test2: button using tx + validation
|
||||
# ----------------------------------------
|
||||
|
||||
# create a new draft tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 2240.0,
|
||||
'acquirer_id': self.buckaroo_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'SO004',
|
||||
'partner_id': self.buyer_id,
|
||||
}, context=context
|
||||
)
|
||||
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, self.buckaroo_id,
|
||||
'should_be_erased', 2240.0, self.currency_euro,
|
||||
tx_id=tx_id,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
self.assertEqual(tree.get('action'), 'https://testcheckout.buckaroo.nl/html/', 'Buckaroo: wrong form POST url')
|
||||
for form_input in tree.input:
|
||||
if form_input.get('name') in ['submit']:
|
||||
continue
|
||||
self.assertEqual(
|
||||
form_input.get('value'),
|
||||
form_values[form_input.get('name')],
|
||||
'Buckaroo: wrong value for form input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
|
||||
)
|
||||
|
||||
@mute_logger('openerp.addons.payment_buckaroo.models.buckaroo', 'ValidationError')
|
||||
def test_20_buckaroo_form_management(self):
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
# be sure not to do stupid thing
|
||||
buckaroo = self.payment_acquirer.browse(self.cr, self.uid, self.buckaroo_id, None)
|
||||
self.assertEqual(buckaroo.environment, 'test', 'test without test environment')
|
||||
|
||||
# typical data posted by buckaroo after client has successfully paid
|
||||
buckaroo_post_data = {
|
||||
'BRQ_RETURNDATA': u'',
|
||||
'BRQ_AMOUNT': u'2240.00',
|
||||
'BRQ_CURRENCY': u'EUR',
|
||||
'BRQ_CUSTOMER_NAME': u'Jan de Tester',
|
||||
'BRQ_INVOICENUMBER': u'SO004',
|
||||
'BRQ_PAYMENT': u'573311D081B04069BD6336001611DBD4',
|
||||
'BRQ_PAYMENT_METHOD': u'paypal',
|
||||
'BRQ_SERVICE_PAYPAL_PAYERCOUNTRY': u'NL',
|
||||
'BRQ_SERVICE_PAYPAL_PAYEREMAIL': u'fhe@openerp.com',
|
||||
'BRQ_SERVICE_PAYPAL_PAYERFIRSTNAME': u'Jan',
|
||||
'BRQ_SERVICE_PAYPAL_PAYERLASTNAME': u'Tester',
|
||||
'BRQ_SERVICE_PAYPAL_PAYERMIDDLENAME': u'de',
|
||||
'BRQ_SERVICE_PAYPAL_PAYERSTATUS': u'verified',
|
||||
'BRQ_SIGNATURE': u'175d82dd53a02bad393fee32cb1eafa3b6fbbd91',
|
||||
'BRQ_STATUSCODE': u'190',
|
||||
'BRQ_STATUSCODE_DETAIL': u'S001',
|
||||
'BRQ_STATUSMESSAGE': u'Transaction successfully processed',
|
||||
'BRQ_TEST': u'true',
|
||||
'BRQ_TIMESTAMP': u'2014-05-08 12:41:21',
|
||||
'BRQ_TRANSACTIONS': u'D6106678E1D54EEB8093F5B3AC42EA7B',
|
||||
'BRQ_WEBSITEKEY': u'5xTGyGyPyl',
|
||||
}
|
||||
|
||||
# should raise error about unknown tx
|
||||
with self.assertRaises(ValidationError):
|
||||
self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
|
||||
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 2240.0,
|
||||
'acquirer_id': self.buckaroo_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'SO004',
|
||||
'partner_name': 'Norbert Buyer',
|
||||
'partner_country_id': self.country_france_id,
|
||||
}, context=context
|
||||
)
|
||||
# validate it
|
||||
self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
|
||||
# check state
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
self.assertEqual(tx.state, 'done', 'Buckaroo: validation did not put tx into done state')
|
||||
self.assertEqual(tx.buckaroo_txnid, buckaroo_post_data.get('BRQ_TRANSACTIONS'), 'Buckaroo: validation did not update tx payid')
|
||||
|
||||
# reset tx
|
||||
tx.write({'state': 'draft', 'date_validate': False, 'buckaroo_txnid': False})
|
||||
|
||||
# now buckaroo post is ok: try to modify the SHASIGN
|
||||
buckaroo_post_data['BRQ_SIGNATURE'] = '54d928810e343acf5fb0c3ee75fd747ff159ef7a'
|
||||
with self.assertRaises(ValidationError):
|
||||
self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
|
||||
|
||||
# simulate an error
|
||||
buckaroo_post_data['BRQ_STATUSCODE'] = 2
|
||||
buckaroo_post_data['BRQ_SIGNATURE'] = '4164b52adb1e6a2221d3d8a39d8c3e18a9ecb90b'
|
||||
self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
|
||||
# check state
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
self.assertEqual(tx.state, 'error', 'Buckaroo: erroneous validation did not put tx into error state')
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<template id="buckaroo_acquirer_button">
|
||||
<form t-if="acquirer.brq_websitekey" t-att-action="tx_url" method="post" target="_self">
|
||||
<input type="hidden" name="Brq_websitekey" t-att-value="tx_values['Brq_websitekey']"/>
|
||||
<input type="hidden" name="Brq_amount" t-att-value="tx_values['Brq_amount'] or '0.0'"/>
|
||||
<input type="hidden" name="Brq_currency" t-att-value="tx_values['Brq_currency']"/>
|
||||
<input type="hidden" name="Brq_invoicenumber" t-att-value="tx_values['Brq_invoicenumber']"/>
|
||||
<input type="hidden" name="Brq_signature" t-att-value="tx_values['Brq_signature']"/>
|
||||
<input type="hidden" name="brq_test" t-att-value="tx_values['brq_test']"/>
|
||||
<input type="hidden" name="Brq_culture" t-att-value="tx_values['Brq_culture']"/>
|
||||
<!-- URLs -->
|
||||
<input t-if="tx_values.get('Brq_return')" type='hidden' name='Brq_return'
|
||||
t-att-value="tx_values.get('Brq_return')"/>
|
||||
<input t-if="tx_values.get('Brq_returncancel')" type='hidden' name='Brq_returncancel'
|
||||
t-att-value="tx_values.get('Brq_returncancel')"/>
|
||||
<input t-if="tx_values.get('Brq_returnerror')" type='hidden' name='Brq_returnerror'
|
||||
t-att-value="tx_values.get('Brq_returnerror')"/>
|
||||
<input t-if="tx_values.get('Brq_returnreject')" type='hidden' name='Brq_returnreject'
|
||||
t-att-value="tx_values.get('Brq_returnreject')"/>
|
||||
<input type='hidden' name='add_returndata' t-att-value="tx_values.get('add_returndata')"/>
|
||||
<!-- submit -->
|
||||
<button type="submit" width="100px"
|
||||
t-att-class="submit_class">
|
||||
<img t-if="not submit_txt" src="/payment_buckaroo/static/src/img/buckaroo_icon.png"/>
|
||||
<span t-if="submit_txt"><t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/></span>
|
||||
</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="acquirer_form_buckaroo" model="ir.ui.view">
|
||||
<field name="name">acquirer.form.buckaroo</field>
|
||||
<field name="model">payment.acquirer</field>
|
||||
<field name="inherit_id" ref="payment.acquirer_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr='//group[@name="acquirer_display"]' position='after'>
|
||||
<group attrs="{'invisible': [('provider', '!=', 'buckaroo')]}">
|
||||
<field name="brq_websitekey"/>
|
||||
<field name="brq_secretkey"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="transaction_form_buckaroo" model="ir.ui.view">
|
||||
<field name="name">acquirer.transaction.form.buckaroo</field>
|
||||
<field name="model">payment.transaction</field>
|
||||
<field name="inherit_id" ref="payment.transaction_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr='//notebook' position='inside'>
|
||||
<page string="Buckaroo TX Details">
|
||||
<group>
|
||||
<field name="buckaroo_txnid"/>
|
||||
</group>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -95,9 +95,12 @@ class AcquirerPaypal(osv.Model):
|
|||
return 0.0
|
||||
country = self.pool['res.country'].browse(cr, uid, country_id, context=context)
|
||||
if country and acquirer.company_id.country_id.id == country.id:
|
||||
fees = amount * (1 + acquirer.fees_dom_var / 100.0) + acquirer.fees_dom_fixed - amount
|
||||
percentage = acquirer.fees_dom_var
|
||||
fixed = acquirer.fees_dom_fixed
|
||||
else:
|
||||
fees = amount * (1 + acquirer.fees_int_var / 100.0) + acquirer.fees_int_fixed - amount
|
||||
percentage = acquirer.fees_int_var
|
||||
fixed = acquirer.fees_int_fixed
|
||||
fees = (percentage / 100.0 * amount + fixed ) / (1 - percentage / 100.0)
|
||||
return fees
|
||||
|
||||
def paypal_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None):
|
||||
|
|
|
@ -148,7 +148,7 @@ class PaypalForm(PaypalCommon):
|
|||
for form_input in tree.input:
|
||||
if form_input.get('name') in ['handling']:
|
||||
handling_found = True
|
||||
self.assertEqual(form_input.get('value'), '1.56', 'paypal: wrong computed fees')
|
||||
self.assertEqual(form_input.get('value'), '1.57', 'paypal: wrong computed fees')
|
||||
self.assertTrue(handling_found, 'paypal: fees_active did not add handling input in rendered form')
|
||||
|
||||
@mute_logger('openerp.addons.payment_paypal.models.paypal', 'ValidationError')
|
||||
|
|
|
@ -1316,30 +1316,80 @@ class ean_wizard(osv.osv_memory):
|
|||
self.pool[m].write(cr,uid,[m_id],{'ean13':ean13})
|
||||
return { 'type' : 'ir.actions.act_window_close' }
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = 'product.product'
|
||||
class pos_category(osv.osv):
|
||||
_name = "pos.category"
|
||||
_description = "Public Category"
|
||||
_order = "sequence, name"
|
||||
|
||||
_constraints = [
|
||||
(osv.osv._check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
|
||||
]
|
||||
|
||||
#def _get_small_image(self, cr, uid, ids, prop, unknow_none, context=None):
|
||||
# result = {}
|
||||
# for obj in self.browse(cr, uid, ids, context=context):
|
||||
# if not obj.product_image:
|
||||
# result[obj.id] = False
|
||||
# continue
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not len(ids):
|
||||
return []
|
||||
reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
|
||||
res = []
|
||||
for record in reads:
|
||||
name = record['name']
|
||||
if record['parent_id']:
|
||||
name = record['parent_id'][1]+' / '+name
|
||||
res.append((record['id'], name))
|
||||
return res
|
||||
|
||||
# image_stream = io.BytesIO(obj.product_image.decode('base64'))
|
||||
# img = Image.open(image_stream)
|
||||
# img.thumbnail((120, 100), Image.ANTIALIAS)
|
||||
# img_stream = StringIO.StringIO()
|
||||
# img.save(img_stream, "JPEG")
|
||||
# result[obj.id] = img_stream.getvalue().encode('base64')
|
||||
# return result
|
||||
def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
|
||||
res = self.name_get(cr, uid, ids, context=context)
|
||||
return dict(res)
|
||||
|
||||
def _get_image(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = tools.image_get_resized_images(obj.image)
|
||||
return result
|
||||
|
||||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True),
|
||||
'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
|
||||
'parent_id': fields.many2one('pos.category','Parent Category', select=True),
|
||||
'child_id': fields.one2many('pos.category', 'parent_id', string='Children Categories'),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
|
||||
|
||||
# NOTE: there is no 'default image', because by default we don't show thumbnails for categories. However if we have a thumbnail
|
||||
# for at least one category, then we display a default image on the other, so that the buttons have consistent styling.
|
||||
# In this case, the default image is set by the js code.
|
||||
# NOTE2: image: all image fields are base64 encoded and PIL-supported
|
||||
'image': fields.binary("Image",
|
||||
help="This field holds the image used as image for the cateogry, limited to 1024x1024px."),
|
||||
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Medium-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'pos.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Medium-sized image of the category. It is automatically "\
|
||||
"resized as a 128x128px image, with aspect ratio preserved. "\
|
||||
"Use this field in form views or some kanban views."),
|
||||
'image_small': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Smal-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'pos.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Small-sized image of the category. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
}
|
||||
|
||||
class product_template(osv.osv):
|
||||
_inherit = 'product.template'
|
||||
|
||||
_columns = {
|
||||
'income_pdt': fields.boolean('Point of Sale Cash In', help="Check if, this is a product you can use to put cash into a statement for the point of sale backend."),
|
||||
'expense_pdt': fields.boolean('Point of Sale Cash Out', help="Check if, this is a product you can use to take cash from a statement for the point of sale backend, example: money lost, transfer to bank, etc."),
|
||||
'available_in_pos': fields.boolean('Available in the Point of Sale', help='Check if you want this product to appear in the Point of Sale'),
|
||||
'to_weight' : fields.boolean('To Weigh', help="Check if the product should be weighted (mainly used with self check-out interface)."),
|
||||
'pos_categ_id': fields.many2one('pos.category','Point of Sale Category', help="Those categories are used to group similar products for point of sale."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -477,13 +477,68 @@
|
|||
|
||||
|
||||
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product.normal.form.inherit</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="stock.view_normal_procurement_locations_form"/>
|
||||
<!-- Product Public Categories -->
|
||||
<record id="product_pos_category_form_view" model="ir.ui.view">
|
||||
<field name="name">pos.category.form</field>
|
||||
<field name="model">pos.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<group name="sale" position="inside">
|
||||
<form string="Pos Categories" version="7.0">
|
||||
<sheet>
|
||||
<field name="image_medium" widget='image' class="oe_avatar oe_right"/>
|
||||
<div class="oe_left">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="sequence"/>
|
||||
</group>
|
||||
</div>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_pos_category_tree_view" model="ir.ui.view">
|
||||
<field name="name">pos.category.tree</field>
|
||||
<field name="model">pos.category</field>
|
||||
<field name="field_parent" eval="False"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Product Product Categories">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="complete_name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_pos_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Pos Product Categories</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">pos.category</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new category.
|
||||
</p><p>
|
||||
Categories are used to browse your products through the
|
||||
touchscreen interface.
|
||||
</p><p>
|
||||
If you put a photo on the category, the layout of the
|
||||
touchscreen interface will automatically. We suggest not to put
|
||||
a photo on categories for small (1024x768) screens.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem action="product_pos_category_action" id="menu_product_pos_category" parent="menu_point_of_sale_product" sequence="0" />
|
||||
<!-- END -->
|
||||
|
||||
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.form.inherit</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="website_and_pos" position="inside">
|
||||
<group name="pos" string="Point of Sale">
|
||||
<field name="pos_categ_id"/>
|
||||
<field name="available_in_pos"/>
|
||||
<field name="to_weight" />
|
||||
<field name="income_pdt"/>
|
||||
|
@ -491,13 +546,10 @@
|
|||
</group>
|
||||
</group>
|
||||
<field name="ean13" position="after">
|
||||
<button name="edit_ean" type="object" string="Set a Custom EAN" class="oe_link oe_edit_only"/>
|
||||
<button colspan="2" name="edit_ean" type="object" string="Set a Custom EAN" class="oe_link oe_edit_only"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Categories tree view -->
|
||||
<menuitem action="product.product_public_category_action" id="menu_product_public_category" parent="menu_point_of_sale_product" sequence="0" />
|
||||
<!-- END -->
|
||||
|
||||
<menuitem name="Configuration" parent="menu_point_root"
|
||||
|
|
|
@ -57,5 +57,5 @@ access_product_pricelist_manager,product.pricelist manager,product.model_product
|
|||
access_pos_session_user,pos.session user,model_pos_session,group_pos_user,1,1,1,0
|
||||
access_pos_config_user,pos.config user,model_pos_config,group_pos_user,1,1,1,0
|
||||
access_ir_sequence_manager,ir.sequence manager,base.model_ir_sequence,group_pos_manager,1,1,1,1
|
||||
access_product_category_pos_manager,product.public.category manager,product.model_product_public_category,group_pos_manager,1,1,1,1
|
||||
access_product_category_pos_user,product.public.category user,product.model_product_public_category,group_pos_user,1,0,0,0
|
||||
access_product_category_pos_manager,pos.category manager,model_pos_category,group_pos_manager,1,1,1,1
|
||||
access_product_category_pos_user,pos.category user,model_pos_category,group_pos_user,1,0,0,0
|
||||
|
|
|
|
@ -145,7 +145,7 @@ function openerp_pos_db(instance, module){
|
|||
for(var i = 0, len = products.length; i < len; i++){
|
||||
var product = products[i];
|
||||
var search_string = this._product_search_string(product);
|
||||
var categ_id = product.public_categ_id ? product.public_categ_id[0] : this.root_category_id;
|
||||
var categ_id = product.pos_categ_id ? product.pos_categ_id[0] : this.root_category_id;
|
||||
if (product.variants){
|
||||
product.name = product.name+" ("+product.variants+")";
|
||||
}
|
||||
|
|
|
@ -208,13 +208,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}).then(function(packagings){
|
||||
self.db.add_packagings(packagings);
|
||||
|
||||
return self.fetch('product.public.category', ['id','name','parent_id','child_id','image'])
|
||||
return self.fetch('pos.category', ['id','name','parent_id','child_id','image'])
|
||||
}).then(function(categories){
|
||||
self.db.add_categories(categories);
|
||||
|
||||
return self.fetch(
|
||||
'product.product',
|
||||
['name', 'list_price','price','public_categ_id', 'taxes_id', 'ean13', 'default_code', 'variants',
|
||||
['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code', 'variants',
|
||||
'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'],
|
||||
[['sale_ok','=',true],['available_in_pos','=',true]],
|
||||
{pricelist: self.pricelist.id} // context for price
|
||||
|
|
|
@ -436,7 +436,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
|
||||
get_image_url: function(category){
|
||||
return window.location.origin + '/web/binary/image?model=product.public.category&field=image_medium&id='+category.id;
|
||||
return window.location.origin + '/web/binary/image?model=pos.category&field=image_medium&id='+category.id;
|
||||
},
|
||||
|
||||
render_category: function( category, with_image ){
|
||||
|
|
|
@ -188,10 +188,13 @@ class product_pricelist(osv.osv):
|
|||
|
||||
products = map(lambda x: x[0], products_by_qty_by_partner)
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
product_obj = self.pool.get('product.product')
|
||||
product_obj = self.pool.get('product.template')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
price_type_obj = self.pool.get('product.price.type')
|
||||
|
||||
if not products:
|
||||
return {}
|
||||
|
||||
version = False
|
||||
for v in pricelist.version_id:
|
||||
if ((v.date_start is False) or (v.date_start <= date)) and ((v.date_end is False) or (v.date_end >= date)):
|
||||
|
@ -207,8 +210,13 @@ class product_pricelist(osv.osv):
|
|||
categ = categ.parent_id
|
||||
categ_ids = categ_ids.keys()
|
||||
|
||||
prod_ids = [x.id for x in products]
|
||||
prod_tmpl_ids = [x.product_tmpl_id.id for x in products]
|
||||
is_product_template = products[0]._name == "product.template"
|
||||
if is_product_template:
|
||||
prod_tmpl_ids = [tmpl.id for tmpl in products]
|
||||
prod_ids = [product.id for product in tmpl.product_variant_ids for tmpl in products]
|
||||
else:
|
||||
prod_ids = [product.id for product in products]
|
||||
prod_tmpl_ids = [product.product_tmpl_id.id for product in products]
|
||||
|
||||
# Load all rules
|
||||
cr.execute(
|
||||
|
@ -234,10 +242,17 @@ class product_pricelist(osv.osv):
|
|||
for rule in items:
|
||||
if rule.min_quantity and qty<rule.min_quantity:
|
||||
continue
|
||||
if rule.product_tmpl_id and product.product_tmpl_id.id<>rule.product_tmpl_id.id:
|
||||
continue
|
||||
if rule.product_id and product.id<>rule.product_id.id:
|
||||
continue
|
||||
if is_product_template:
|
||||
if rule.product_tmpl_id and product.id<>rule.product_tmpl_id.id:
|
||||
continue
|
||||
if rule.product_id:
|
||||
continue
|
||||
else:
|
||||
if rule.product_tmpl_id and product.product_tmpl_id.id<>rule.product_tmpl_id.id:
|
||||
continue
|
||||
if rule.product_id and product.id<>rule.product_id.id:
|
||||
continue
|
||||
|
||||
if rule.categ_id:
|
||||
cat = product.categ_id
|
||||
while cat:
|
||||
|
|
|
@ -29,6 +29,7 @@ from openerp import tools
|
|||
from openerp.osv import osv, fields
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
import psycopg2
|
||||
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
@ -273,7 +274,7 @@ class product_category(osv.osv):
|
|||
|
||||
|
||||
_defaults = {
|
||||
'type' : lambda *a : 'normal',
|
||||
'type' : 'normal',
|
||||
}
|
||||
|
||||
_parent_name = "parent_id"
|
||||
|
@ -316,69 +317,78 @@ class produce_price_history(osv.osv):
|
|||
}
|
||||
|
||||
|
||||
class product_public_category(osv.osv):
|
||||
_name = "product.public.category"
|
||||
_description = "Public Category"
|
||||
_order = "sequence, name"
|
||||
#----------------------------------------------------------
|
||||
# Product Attributes
|
||||
#----------------------------------------------------------
|
||||
class product_attribute(osv.osv):
|
||||
_name = "product.attribute"
|
||||
_description = "Product Attribute"
|
||||
_columns = {
|
||||
'name': fields.char('Name', translate=True, required=True),
|
||||
'value_ids': fields.one2many('product.attribute.value', 'attribute_id', 'Values'),
|
||||
}
|
||||
|
||||
_constraints = [
|
||||
(osv.osv._check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
|
||||
]
|
||||
class product_attribute_value(osv.osv):
|
||||
_name = "product.attribute.value"
|
||||
_order = 'sequence'
|
||||
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, 0)
|
||||
if not context.get('active_id'):
|
||||
return result
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not len(ids):
|
||||
return []
|
||||
reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
|
||||
res = []
|
||||
for record in reads:
|
||||
name = record['name']
|
||||
if record['parent_id']:
|
||||
name = record['parent_id'][1]+' / '+name
|
||||
res.append((record['id'], name))
|
||||
return res
|
||||
|
||||
def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
|
||||
res = self.name_get(cr, uid, ids, context=context)
|
||||
return dict(res)
|
||||
|
||||
def _get_image(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = tools.image_get_resized_images(obj.image)
|
||||
for price_id in obj.price_ids:
|
||||
if price_id.product_tmpl_id.id == context.get('active_id'):
|
||||
result[obj.id] = price_id.price_extra
|
||||
break
|
||||
return result
|
||||
|
||||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||
|
||||
def _set_price_extra(self, cr, uid, id, name, value, args, context=None):
|
||||
if 'active_id' not in context:
|
||||
return None
|
||||
p_obj = self.pool['product.attribute.price']
|
||||
p_ids = p_obj.search(cr, uid, [('value_id', '=', id), ('product_tmpl_id', '=', context['active_id'])], context=context)
|
||||
if p_ids:
|
||||
p_obj.write(cr, uid, p_ids, {'price_extra': value}, context=context)
|
||||
else:
|
||||
p_obj.create(cr, uid, p_ids, {
|
||||
'product_tmpl_id': context['active_id'],
|
||||
'value_id': id,
|
||||
'price_extra': value,
|
||||
}, context=context)
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True),
|
||||
'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
|
||||
'parent_id': fields.many2one('product.public.category','Parent Category', select=True),
|
||||
'child_id': fields.one2many('product.public.category', 'parent_id', string='Children Categories'),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
|
||||
|
||||
# NOTE: there is no 'default image', because by default we don't show thumbnails for categories. However if we have a thumbnail
|
||||
# for at least one category, then we display a default image on the other, so that the buttons have consistent styling.
|
||||
# In this case, the default image is set by the js code.
|
||||
# NOTE2: image: all image fields are base64 encoded and PIL-supported
|
||||
'image': fields.binary("Image",
|
||||
help="This field holds the image used as image for the cateogry, limited to 1024x1024px."),
|
||||
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Medium-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'product.public.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Medium-sized image of the category. It is automatically "\
|
||||
"resized as a 128x128px image, with aspect ratio preserved. "\
|
||||
"Use this field in form views or some kanban views."),
|
||||
'image_small': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Smal-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'product.public.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Small-sized image of the category. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
'sequence': fields.integer('Sequence', help="Determine the display order"),
|
||||
'name': fields.char('Value', translate=True, required=True),
|
||||
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True),
|
||||
'product_ids': fields.many2many('product.product', id1='att_id', id2='prod_id', string='Variants', readonly=True),
|
||||
'price_extra': fields.function(_get_price_extra, type='float', string='Attribute Price Extra',
|
||||
fnct_inv=_set_price_extra,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="Price Extra: Extra price for the variant with this attribute value on sale price. eg. 200 price extra, 1000 + 200 = 1200."),
|
||||
'price_ids': fields.one2many('product.attribute.price', 'value_id', string='Attribute Prices', readonly=True),
|
||||
}
|
||||
_sql_constraints = [
|
||||
('value_company_uniq', 'unique (name,attribute_id)', 'This attribute value already exists !')
|
||||
]
|
||||
_defaults = {
|
||||
'price_extra': 0.0,
|
||||
}
|
||||
|
||||
class product_attribute_price(osv.osv):
|
||||
_name = "product.attribute.price"
|
||||
_columns = {
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True),
|
||||
'value_id': fields.many2one('product.attribute.value', 'Product Attribute Value', required=True),
|
||||
'price_extra': fields.float('Price Extra', digits_compute=dp.get_precision('Product Price')),
|
||||
}
|
||||
|
||||
class product_attribute_line(osv.osv):
|
||||
_name = "product.attribute.line"
|
||||
_columns = {
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True),
|
||||
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True),
|
||||
'value_ids': fields.many2many('product.attribute.value', id1='line_id', id2='val_id', string='Product Attribute Value'),
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,6 +409,42 @@ class product_template(osv.osv):
|
|||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||
|
||||
def _is_product_variant(self, cr, uid, ids, name, arg, context=None):
|
||||
return self.is_product_variant(cr, uid, ids, name, arg, context=context)
|
||||
|
||||
def is_product_variant(self, cr, uid, ids, name, arg, context=None):
|
||||
prod = self.pool.get('product.product')
|
||||
res = dict.fromkeys(ids, False)
|
||||
ctx = dict(context, active_test=True)
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
res[product.id] = prod.search(cr, uid, [('product_tmpl_id','=',product.id)], context=ctx, count=True) == 1
|
||||
return res
|
||||
|
||||
|
||||
def _product_template_price(self, cr, uid, ids, name, arg, context=None):
|
||||
plobj = self.pool.get('product.pricelist')
|
||||
res = {}
|
||||
quantity = context.get('quantity') or 1.0
|
||||
pricelist = context.get('pricelist', False)
|
||||
partner = context.get('partner', False)
|
||||
if pricelist:
|
||||
# Support context pricelists specified as display_name or ID for compatibility
|
||||
if isinstance(pricelist, basestring):
|
||||
pricelist_ids = plobj.name_search(
|
||||
cr, uid, pricelist, operator='=', context=context, limit=1)
|
||||
pricelist = pricelist_ids[0][0] if pricelist_ids else pricelist
|
||||
|
||||
if isinstance(pricelist, (int, long)):
|
||||
products = self.browse(cr, uid, ids, context=context)
|
||||
qtys = map(lambda x: (x, quantity, partner), products)
|
||||
pl = plobj.browse(cr, uid, pricelist, context=context)
|
||||
price = plobj._price_get_multi(cr,uid, pl, qtys, context=context)
|
||||
for id in ids:
|
||||
res[id] = price.get(id, 0.0)
|
||||
for id in ids:
|
||||
res.setdefault(id, 0.0)
|
||||
return res
|
||||
|
||||
def get_history_price(self, cr, uid, product_tmpl, company_id, date=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -421,6 +467,12 @@ class product_template(osv.osv):
|
|||
'company_id': company_id,
|
||||
}, context=context)
|
||||
|
||||
def _get_product_variant_count(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for product in self.browse(cr, uid, ids):
|
||||
res[product.id] = len(product.product_variant_ids)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True, select=True),
|
||||
'product_manager': fields.many2one('res.users','Product Manager'),
|
||||
|
@ -434,9 +486,10 @@ class product_template(osv.osv):
|
|||
"This description will be copied to every Sale Order, Delivery Order and Customer Invoice/Refund"),
|
||||
'type': fields.selection([('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Consumable are product where you don't manage stock, a service is a non-material product provided by a company or an individual."),
|
||||
'rental': fields.boolean('Can be Rent'),
|
||||
'categ_id': fields.many2one('product.category','Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"),
|
||||
'public_categ_id': fields.many2one('product.public.category','Public Category', help="Those categories are used to group similar products for public sales (eg.: point of sale, e-commerce)."),
|
||||
'categ_id': fields.many2one('product.category','Internal Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"),
|
||||
'price': fields.function(_product_template_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'list_price': fields.float('Sale Price', digits_compute=dp.get_precision('Product Price'), help="Base price to compute the customer price. Sometimes called the catalog price."),
|
||||
'lst_price' : fields.related('list_price', type="float", string='Public Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'standard_price': fields.property(type = 'float', digits_compute=dp.get_precision('Product Price'),
|
||||
help="Cost price of the product template used for standard stock valuation in accounting and used as a base price on purchase orders.",
|
||||
groups="base.group_user", string="Cost Price"),
|
||||
|
@ -445,6 +498,7 @@ class product_template(osv.osv):
|
|||
'weight_net': fields.float('Net Weight', digits_compute=dp.get_precision('Stock Weight'), help="The net weight in Kg."),
|
||||
'warranty': fields.float('Warranty'),
|
||||
'sale_ok': fields.boolean('Can be Sold', help="Specify if the product can be selected in a sales order line."),
|
||||
'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'),
|
||||
'state': fields.selection([('',''),
|
||||
('draft', 'In Development'),
|
||||
('sellable','Normal'),
|
||||
|
@ -458,13 +512,12 @@ class product_template(osv.osv):
|
|||
help='Coefficient to convert default Unit of Measure to Unit of Sale\n'
|
||||
' uos = uom * coeff'),
|
||||
'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type'),
|
||||
'seller_ids': fields.one2many('product.supplierinfo', 'product_tmpl_id', 'Supplier'),
|
||||
'company_id': fields.many2one('res.company', 'Company', select=1),
|
||||
# image: all image fields are base64 encoded and PIL-supported
|
||||
'image': fields.binary("Image",
|
||||
help="This field holds the image used as image for the product, limited to 1024x1024px."),
|
||||
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Medium-sized image", type="binary", multi="_get_image",
|
||||
string="Medium-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'product.template': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
|
@ -479,13 +532,64 @@ class product_template(osv.osv):
|
|||
help="Small-sized image of the product. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
'product_variant_ids': fields.one2many('product.product', 'product_tmpl_id', 'Product Variants', required=True),
|
||||
|
||||
'packaging' : fields.one2many('product.packaging', 'product_id', 'Logistical Units',
|
||||
help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."),
|
||||
|
||||
'seller_ids': fields.one2many('product.supplierinfo', 'product_tmpl_id', 'Supplier'),
|
||||
'seller_delay': fields.related('seller_ids','delay', type='integer', string='Supplier Lead Time',
|
||||
help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
|
||||
'seller_qty': fields.related('seller_ids','qty', type='float', string='Supplier Quantity',
|
||||
help="This is minimum quantity to purchase from Main Supplier."),
|
||||
'seller_id': fields.related('seller_ids','name', type='many2one', relation='res.partner', string='Main Supplier',
|
||||
help="Main Supplier who has highest priority in Supplier List."),
|
||||
|
||||
'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."),
|
||||
'color': fields.integer('Color Index'),
|
||||
'is_product_variant': fields.function( _is_product_variant, type='boolean', string='Only one product variant'),
|
||||
|
||||
'attribute_line_ids': fields.one2many('product.attribute.line', 'product_tmpl_id', 'Product Attributes'),
|
||||
'product_variant_ids': fields.one2many('product.product', 'product_tmpl_id', 'Products', required=True),
|
||||
'product_variant_count': fields.function( _get_product_variant_count, type='integer', string='# of Product Variants'),
|
||||
|
||||
# related to display product product information if is_product_variant
|
||||
'ean13': fields.related('product_variant_ids', 'ean13', type='char', string='EAN13 Barcode'),
|
||||
'default_code': fields.related('product_variant_ids', 'default_code', type='char', string='Internal Reference'),
|
||||
}
|
||||
|
||||
def _price_get_list_price(self, product):
|
||||
return 0.0
|
||||
|
||||
def _price_get(self, cr, uid, products, ptype='list_price', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if 'currency_id' in context:
|
||||
pricetype_obj = self.pool.get('product.price.type')
|
||||
price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
|
||||
price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id
|
||||
|
||||
res = {}
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for product in products:
|
||||
res[product.id] = product[ptype] or 0.0
|
||||
if ptype == 'list_price':
|
||||
res[product.id] += product._name == "product.product" and product.price_extra or 0.0
|
||||
if 'uom' in context:
|
||||
uom = product.uom_id or product.uos_id
|
||||
res[product.id] = product_uom_obj._compute_price(cr, uid,
|
||||
uom.id, res[product.id], context['uom'])
|
||||
# Convert from price_type currency to asked one
|
||||
if 'currency_id' in context:
|
||||
# Take the price_type currency from the product field
|
||||
# This is right cause a field cannot be in more than one currency
|
||||
res[product.id] = self.pool.get('res.currency').compute(cr, uid, price_type_currency_id,
|
||||
context['currency_id'], res[product.id],context=context)
|
||||
|
||||
return res
|
||||
|
||||
def _get_uom_id(self, cr, uid, *args):
|
||||
cr.execute('select id from product_uom order by id limit 1')
|
||||
res = cr.fetchone()
|
||||
return res and res[0] or False
|
||||
return self.pool["product.uom"].search(cr, uid, [], limit=1, order='id')[0]
|
||||
|
||||
def _default_category(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
|
@ -505,9 +609,68 @@ class product_template(osv.osv):
|
|||
return {'value': {'uom_po_id': uom_id}}
|
||||
return {}
|
||||
|
||||
def create_variant_ids(self, cr, uid, ids, context=None):
|
||||
product_obj = self.pool.get("product.product")
|
||||
ctx = context and context.copy() or {}
|
||||
|
||||
if ctx.get("create_product_variant"):
|
||||
return None
|
||||
|
||||
ctx.update(active_test=False, create_product_variant=True)
|
||||
|
||||
tmpl_ids = self.browse(cr, uid, ids, context=ctx)
|
||||
for tmpl_id in tmpl_ids:
|
||||
|
||||
# list of values combination
|
||||
all_variants = [[]]
|
||||
for variant_id in tmpl_id.attribute_line_ids:
|
||||
if len(variant_id.value_ids) > 1:
|
||||
temp_variants = []
|
||||
for value_id in variant_id.value_ids:
|
||||
for variant in all_variants:
|
||||
temp_variants.append(variant + [int(value_id)])
|
||||
all_variants = temp_variants
|
||||
|
||||
# check product
|
||||
variant_ids_to_active = []
|
||||
variants_active_ids = []
|
||||
variants_inactive = []
|
||||
for product_id in tmpl_id.product_variant_ids:
|
||||
variants = map(int,product_id.attribute_value_ids)
|
||||
if variants in all_variants:
|
||||
variants_active_ids.append(product_id.id)
|
||||
all_variants.pop(all_variants.index(variants))
|
||||
if not product_id.active:
|
||||
variant_ids_to_active.append(product_id.id)
|
||||
else:
|
||||
variants_inactive.append(product_id)
|
||||
if variant_ids_to_active:
|
||||
product_obj.write(cr, uid, variant_ids_to_active, {'active': True}, context=ctx)
|
||||
|
||||
# create new product
|
||||
for variant_ids in all_variants:
|
||||
values = {
|
||||
'product_tmpl_id': tmpl_id.id,
|
||||
'attribute_value_ids': [(6, 0, variant_ids)]
|
||||
}
|
||||
id = product_obj.create(cr, uid, values, context=ctx)
|
||||
variants_active_ids.append(id)
|
||||
|
||||
# unlink or inactive product
|
||||
for variant_id in map(int,variants_inactive):
|
||||
try:
|
||||
with cr.savepoint():
|
||||
product_obj.unlink(cr, uid, [variant_id], context=ctx)
|
||||
except (psycopg2.Error, osv.except_osv):
|
||||
product_obj.write(cr, uid, [variant_id], {'active': False}, context=ctx)
|
||||
pass
|
||||
return True
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
''' Store the initial standard price in order to be able to retrieve the cost of a product template for a given date'''
|
||||
product_template_id = super(product_template, self).create(cr, uid, vals, context=context)
|
||||
if not context or "create_product_product" not in context:
|
||||
self.create_variant_ids(cr, uid, [product_template_id], context=context)
|
||||
self._set_standard_price(cr, uid, product_template_id, vals.get('standard_price', 0.0), context=context)
|
||||
return product_template_id
|
||||
|
||||
|
@ -524,7 +687,17 @@ class product_template(osv.osv):
|
|||
if 'standard_price' in vals:
|
||||
for prod_template_id in ids:
|
||||
self._set_standard_price(cr, uid, prod_template_id, vals['standard_price'], context=context)
|
||||
return super(product_template, self).write(cr, uid, ids, vals, context=context)
|
||||
res = super(product_template, self).write(cr, uid, ids, vals, context=context)
|
||||
if 'attribute_line_ids' in vals or vals.get('active'):
|
||||
self.create_variant_ids(cr, uid, ids, context=context)
|
||||
if 'active' in vals and not vals.get('active'):
|
||||
ctx = context and context.copy() or {}
|
||||
ctx.update(active_test=False)
|
||||
product_ids = []
|
||||
for product in self.browse(cr, uid, ids, context=ctx):
|
||||
product_ids = map(int,product.product_variant_ids)
|
||||
self.pool.get("product.product").write(cr, uid, product_ids, {'active': vals.get('active')}, context=ctx)
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
|
@ -544,6 +717,7 @@ class product_template(osv.osv):
|
|||
'mes_type': 'fixed',
|
||||
'categ_id' : _default_category,
|
||||
'type' : 'consu',
|
||||
'active': True,
|
||||
}
|
||||
|
||||
def _check_uom(self, cursor, user, ids, context=None):
|
||||
|
@ -579,14 +753,6 @@ class product_product(osv.osv):
|
|||
_inherit = ['mail.thread']
|
||||
_order = 'default_code,name_template'
|
||||
|
||||
def view_header_get(self, cr, uid, view_id, view_type, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = super(product_product, self).view_header_get(cr, uid, view_id, view_type, context)
|
||||
if (context.get('categ_id', False)):
|
||||
return _('Products: ') + self.pool.get('product.category').browse(cr, uid, context['categ_id'], context=context).name
|
||||
return res
|
||||
|
||||
def _product_price(self, cr, uid, ids, name, arg, context=None):
|
||||
plobj = self.pool.get('product.pricelist')
|
||||
res = {}
|
||||
|
@ -613,11 +779,19 @@ class product_product(osv.osv):
|
|||
res.setdefault(id, 0.0)
|
||||
return res
|
||||
|
||||
def view_header_get(self, cr, uid, view_id, view_type, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = super(product_product, self).view_header_get(cr, uid, view_id, view_type, context)
|
||||
if (context.get('categ_id', False)):
|
||||
return _('Products: ') + self.pool.get('product.category').browse(cr, uid, context['categ_id'], context=context).name
|
||||
return res
|
||||
|
||||
def _product_lst_price(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for id in ids:
|
||||
res.setdefault(id, 0.0)
|
||||
res = dict.fromkeys(ids, 0.0)
|
||||
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
if 'uom' in context:
|
||||
uom = product.uos_id or product.uom_id
|
||||
|
@ -625,20 +799,17 @@ class product_product(osv.osv):
|
|||
uom.id, product.list_price, context['uom'])
|
||||
else:
|
||||
res[product.id] = product.list_price
|
||||
res[product.id] = (res[product.id] or 0.0) * (product.price_margin or 1.0) + product.price_extra
|
||||
price_extra = 0.0
|
||||
for variant_id in product.attribute_value_ids:
|
||||
price_extra += variant_id.price_extra
|
||||
res[product.id] = (res[product.id] or 0.0) + price_extra
|
||||
return res
|
||||
|
||||
def _save_product_lst_price(self, cr, uid, product_id, field_name, field_value, arg, context=None):
|
||||
field_value = field_value or 0.0
|
||||
product = self.browse(cr, uid, product_id, context=context)
|
||||
list_price = (field_value - product.price_extra) / (product.price_margin or 1.0)
|
||||
return self.write(cr, uid, [product_id], {'list_price': list_price}, context=context)
|
||||
|
||||
def _get_partner_code_name(self, cr, uid, ids, product, partner_id, context=None):
|
||||
for supinfo in product.seller_ids:
|
||||
if supinfo.name.id == partner_id:
|
||||
return {'code': supinfo.product_code or product.default_code, 'name': supinfo.product_name or product.name, 'variants': ''}
|
||||
res = {'code': product.default_code, 'name': product.name, 'variants': product.variants}
|
||||
return {'code': supinfo.product_code or product.default_code, 'name': supinfo.product_name or product.name}
|
||||
res = {'code': product.default_code, 'name': product.name}
|
||||
return res
|
||||
|
||||
def _product_code(self, cr, uid, ids, name, arg, context=None):
|
||||
|
@ -655,48 +826,15 @@ class product_product(osv.osv):
|
|||
context = {}
|
||||
for p in self.browse(cr, uid, ids, context=context):
|
||||
data = self._get_partner_code_name(cr, uid, [], p, context.get('partner_id', None), context=context)
|
||||
if not data['variants']:
|
||||
data['variants'] = p.variants
|
||||
if not data['code']:
|
||||
data['code'] = p.code
|
||||
if not data['name']:
|
||||
data['name'] = p.name
|
||||
res[p.id] = (data['code'] and ('['+data['code']+'] ') or '') + \
|
||||
(data['name'] or '') + (data['variants'] and (' - '+data['variants']) or '')
|
||||
res[p.id] = (data['code'] and ('['+data['code']+'] ') or '') + (data['name'] or '')
|
||||
return res
|
||||
|
||||
def _is_only_child(self, cr, uid, ids, name, arg, context=None):
|
||||
res = dict.fromkeys(ids, True)
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
if product.product_tmpl_id and len(product.product_tmpl_id.product_variant_ids) > 1:
|
||||
res[product.id] = False
|
||||
return res
|
||||
|
||||
def _get_main_product_supplier(self, cr, uid, product, context=None):
|
||||
"""Determines the main (best) product supplier for ``product``,
|
||||
returning the corresponding ``supplierinfo`` record, or False
|
||||
if none were found. The default strategy is to select the
|
||||
supplier with the highest priority (i.e. smallest sequence).
|
||||
|
||||
:param browse_record product: product to supply
|
||||
:rtype: product.supplierinfo browse_record or False
|
||||
"""
|
||||
sellers = [(seller_info.sequence, seller_info)
|
||||
for seller_info in product.seller_ids or []
|
||||
if seller_info and isinstance(seller_info.sequence, (int, long))]
|
||||
return sellers and sellers[0][1] or False
|
||||
|
||||
def _calc_seller(self, cr, uid, ids, fields, arg, context=None):
|
||||
result = {}
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
main_supplier = self._get_main_product_supplier(cr, uid, product, context=context)
|
||||
result[product.id] = {
|
||||
'seller_info_id': main_supplier and main_supplier.id or False,
|
||||
'seller_delay': main_supplier.delay if main_supplier else 1,
|
||||
'seller_qty': main_supplier and main_supplier.qty or 0.0,
|
||||
'seller_id': main_supplier and main_supplier.name.id or False
|
||||
}
|
||||
return result
|
||||
def is_product_variant(self, cr, uid, ids, name, arg, context=None):
|
||||
return dict.fromkeys(ids, True)
|
||||
|
||||
def _get_name_template_ids(self, cr, uid, ids, context=None):
|
||||
result = set()
|
||||
|
@ -705,39 +843,68 @@ class product_product(osv.osv):
|
|||
result.add(el)
|
||||
return list(result)
|
||||
|
||||
def _get_image_variant(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = obj.image_variant or getattr(obj.product_tmpl_id, name)
|
||||
return result
|
||||
|
||||
def _set_image_variant(self, cr, uid, id, name, value, args, context=None):
|
||||
image = tools.image_resize_image_big(value)
|
||||
res = self.write(cr, uid, [id], {'image_variant': image}, context=context)
|
||||
product = self.browse(cr, uid, id, context=context)
|
||||
if not product.product_tmpl_id.image:
|
||||
product.write({'image_variant': None}, context=context)
|
||||
product.product_tmpl_id.write({'image': image}, context=context)
|
||||
return res
|
||||
|
||||
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
price_extra = 0.0
|
||||
for variant_id in product.attribute_value_ids:
|
||||
for price_id in variant_id.price_ids:
|
||||
if price_id.product_tmpl_id.id == product.product_tmpl_id.id:
|
||||
price_extra += price_id.price_extra
|
||||
result[product.id] = price_extra
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'price': fields.function(_product_price, fnct_inv=_save_product_lst_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'lst_price' : fields.function(_product_lst_price, fnct_inv=_save_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'price': fields.function(_product_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'price_extra': fields.function(_get_price_extra, type='float', string='Variant Extra Price', help="This is le sum of the extra price of all attributes"),
|
||||
'lst_price': fields.function(_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
|
||||
'code': fields.function(_product_code, type='char', string='Internal Reference'),
|
||||
'partner_ref' : fields.function(_product_partner_ref, type='char', string='Customer ref'),
|
||||
'default_code' : fields.char('Internal Reference', select=True),
|
||||
'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."),
|
||||
'variants': fields.char('Variants', translate=True),
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True),
|
||||
'is_only_child': fields.function(
|
||||
_is_only_child, type='boolean', string='Sole child of the parent template'),
|
||||
'ean13': fields.char('EAN13 Barcode', size=13, help="International Article Number used for product identification."),
|
||||
'packaging': fields.one2many('product.packaging', 'product_id', 'Packaging', help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."),
|
||||
'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price'), help="Price Extra: Extra price for the variant on sale price. eg. 200 price extra, 1000 + 200 = 1200."),
|
||||
'price_margin': fields.float('Variant Price Margin', digits_compute=dp.get_precision('Product Price'), help="Price Margin: Margin in percentage amount on sale price for the variant. eg. 10 price margin, 1000 * 1.1 = 1100."),
|
||||
'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'),
|
||||
'name_template': fields.related('product_tmpl_id', 'name', string="Template Name", type='char', store={
|
||||
'product.template': (_get_name_template_ids, ['name'], 10),
|
||||
'product.product': (lambda self, cr, uid, ids, c=None: ids, [], 10),
|
||||
}, select=True),
|
||||
'color': fields.integer('Color Index'),
|
||||
'seller_info_id': fields.function(_calc_seller, type='many2one', relation="product.supplierinfo", string="Supplier Info", multi="seller_info"),
|
||||
'seller_delay': fields.function(_calc_seller, type='integer', string='Supplier Lead Time', multi="seller_info", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
|
||||
'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."),
|
||||
'seller_id': fields.function(_calc_seller, type='many2one', relation="res.partner", string='Main Supplier', help="Main Supplier who has highest priority in Supplier List.", multi="seller_info"),
|
||||
'attribute_value_ids': fields.many2many('product.attribute.value', id1='prod_id', id2='att_id', string='Attributes', readonly=True),
|
||||
|
||||
# image: all image fields are base64 encoded and PIL-supported
|
||||
'image_variant': fields.binary("Variant Image",
|
||||
help="This field holds the image used as image for the product variant, limited to 1024x1024px."),
|
||||
|
||||
'image': fields.function(_get_image_variant, fnct_inv=_set_image_variant,
|
||||
string="Big-sized image", type="binary",
|
||||
help="Image of the product variant (Big-sized image of product template if false). It is automatically "\
|
||||
"resized as a 1024x1024px image, with aspect ratio preserved."),
|
||||
'image_small': fields.function(_get_image_variant, fnct_inv=_set_image_variant,
|
||||
string="Small-sized image", type="binary",
|
||||
help="Image of the product variant (Small-sized image of product template if false)."),
|
||||
'image_medium': fields.function(_get_image_variant, fnct_inv=_set_image_variant,
|
||||
string="Medium-sized image", type="binary",
|
||||
help="Image of the product variant (Medium-sized image of product template if false)."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'price_extra': lambda *a: 0.0,
|
||||
'price_margin': lambda *a: 1.0,
|
||||
'active': 1,
|
||||
'color': 0,
|
||||
'is_only_child': True,
|
||||
}
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
|
@ -767,8 +934,9 @@ class product_product(osv.osv):
|
|||
|
||||
def _check_ean_key(self, cr, uid, ids, context=None):
|
||||
for product in self.read(cr, uid, ids, ['ean13'], context=context):
|
||||
res = check_ean(product['ean13'])
|
||||
return res
|
||||
if not check_ean(product['ean13']):
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [(_check_ean_key, 'You provided an invalid "EAN13 Barcode" reference. You may use the "Internal Reference" field instead.', ['ean13'])]
|
||||
|
||||
|
@ -782,13 +950,12 @@ class product_product(osv.osv):
|
|||
ids = [ids]
|
||||
if not len(ids):
|
||||
return []
|
||||
|
||||
def _name_get(d):
|
||||
name = d.get('name','')
|
||||
code = d.get('default_code',False)
|
||||
if code:
|
||||
name = '[%s] %s' % (code,name)
|
||||
if d.get('variants'):
|
||||
name = name + ' - %s' % (d['variants'],)
|
||||
return (d['id'], name)
|
||||
|
||||
partner_id = context.get('partner_id', False)
|
||||
|
@ -800,6 +967,8 @@ class product_product(osv.osv):
|
|||
|
||||
result = []
|
||||
for product in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
variant = ", ".join([v.name for v in product.attribute_value_ids])
|
||||
name = variant and "%s (%s)" % (product.name, variant) or product.name
|
||||
sellers = []
|
||||
if partner_id:
|
||||
sellers = filter(lambda x: x.name.id == partner_id, product.seller_ids)
|
||||
|
@ -807,17 +976,15 @@ class product_product(osv.osv):
|
|||
for s in sellers:
|
||||
mydict = {
|
||||
'id': product.id,
|
||||
'name': s.product_name or product.name,
|
||||
'name': s.product_name or name,
|
||||
'default_code': s.product_code or product.default_code,
|
||||
'variants': product.variants
|
||||
}
|
||||
result.append(_name_get(mydict))
|
||||
else:
|
||||
mydict = {
|
||||
'id': product.id,
|
||||
'name': product.name,
|
||||
'name': name,
|
||||
'default_code': product.default_code,
|
||||
'variants': product.variants
|
||||
}
|
||||
result.append(_name_get(mydict))
|
||||
return result
|
||||
|
@ -855,44 +1022,7 @@ class product_product(osv.osv):
|
|||
#
|
||||
def price_get(self, cr, uid, ids, ptype='list_price', context=None):
|
||||
products = self.browse(cr, uid, ids, context=context)
|
||||
return self._price_get(cr, uid, products, ptype=ptype, context=context)
|
||||
|
||||
def _price_get(self, cr, uid, products, ptype='list_price', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if 'currency_id' in context:
|
||||
pricetype_obj = self.pool.get('product.price.type')
|
||||
price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
|
||||
price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id
|
||||
|
||||
res = {}
|
||||
# standard_price field can only be seen by users in base.group_user
|
||||
# Thus, in order to compute the sale price from the cost price for users not in this group
|
||||
# We fetch the standard price as the superuser
|
||||
for product in products:
|
||||
if ptype != 'standard_price':
|
||||
res[product.id] = product[ptype] or 0.0
|
||||
else:
|
||||
res[product.id] = self.read(cr, SUPERUSER_ID, product.id, [ptype], context=context)[ptype] or 0.0
|
||||
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for product in products:
|
||||
if ptype == 'list_price':
|
||||
res[product.id] = (res[product.id] * (product.price_margin or 1.0)) + \
|
||||
product.price_extra
|
||||
if 'uom' in context:
|
||||
uom = product.uom_id or product.uos_id
|
||||
res[product.id] = product_uom_obj._compute_price(cr, uid,
|
||||
uom.id, res[product.id], context['uom'])
|
||||
# Convert from price_type currency to asked one
|
||||
if 'currency_id' in context:
|
||||
# Take the price_type currency from the product field
|
||||
# This is right cause a field cannot be in more than one currency
|
||||
res[product.id] = self.pool.get('res.currency').compute(cr, uid, price_type_currency_id,
|
||||
context['currency_id'], res[product.id],context=context)
|
||||
|
||||
return res
|
||||
return self.pool.get("product.template")._price_get(cr, uid, products, ptype=ptype, context=context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if context is None:
|
||||
|
@ -923,6 +1053,12 @@ class product_product(osv.osv):
|
|||
'res_id': product.product_tmpl_id.id,
|
||||
'target': 'new'}
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = dict(context or {}, create_product_product=True)
|
||||
return super(product_product, self).create(cr, uid, vals, context=ctx)
|
||||
|
||||
|
||||
class product_packaging(osv.osv):
|
||||
_name = "product.packaging"
|
||||
|
@ -948,8 +1084,9 @@ class product_packaging(osv.osv):
|
|||
|
||||
def _check_ean_key(self, cr, uid, ids, context=None):
|
||||
for pack in self.browse(cr, uid, ids, context=context):
|
||||
res = check_ean(pack.ean)
|
||||
return res
|
||||
if not check_ean(pack.ean):
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [(_check_ean_key, 'Error: Invalid ean code', ['ean'])]
|
||||
|
||||
|
@ -969,8 +1106,8 @@ class product_packaging(osv.osv):
|
|||
return (res and res[0]) or False
|
||||
|
||||
_defaults = {
|
||||
'rows' : lambda *a : 3,
|
||||
'sequence' : lambda *a : 1,
|
||||
'rows' : 3,
|
||||
'sequence' : 1,
|
||||
'ul' : _get_1st_ul,
|
||||
}
|
||||
|
||||
|
@ -1010,9 +1147,9 @@ class product_supplierinfo(osv.osv):
|
|||
'company_id':fields.many2one('res.company','Company',select=1),
|
||||
}
|
||||
_defaults = {
|
||||
'qty': lambda *a: 0.0,
|
||||
'sequence': lambda *a: 1,
|
||||
'delay': lambda *a: 1,
|
||||
'qty': 0.0,
|
||||
'sequence': 1,
|
||||
'delay': 1,
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.supplierinfo', context=c),
|
||||
}
|
||||
def price_get(self, cr, uid, supplier_ids, product_id, product_qty=1, context=None):
|
||||
|
|
|
@ -255,10 +255,5 @@ parameter) will see those record just disappear.
|
|||
<field name="type">service</field>
|
||||
<field name="sale_ok" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Product Public Categories -->
|
||||
<record id="categ_others" model="product.public.category">
|
||||
<field name="name">Others</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,198 +1,140 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<menuitem id="prod_config_main" name="Products" parent="base.menu_base_config" sequence="70"/>
|
||||
<menuitem id="base.menu_product" name="Product Variants" parent="base.menu_base_partner" sequence="9"/>
|
||||
|
||||
<record id="product_search_form_view" model="ir.ui.view">
|
||||
<field name="name">product.search.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<!-- templates -->
|
||||
|
||||
<record id="product_template_search_view" model="ir.ui.view">
|
||||
<field name="name">product.template.search</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Product">
|
||||
<field name="name" string="Product" filter_domain="['|','|',('name','ilike',self),('default_code','ilike',self),('variants','ilike',self)]"/>
|
||||
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
|
||||
<filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/>
|
||||
<separator/>
|
||||
<filter string="Can be Sold" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>
|
||||
<field name="categ_id" operator="child_of"/>
|
||||
<group expand="0" string="Context...">
|
||||
<field name="pricelist_id" widget="selection" context="{'pricelist': self}" filter_domain="[]" groups="product.group_sale_pricelist"/> <!-- Keep widget=selection on this field to pass numeric `self` value, which is not the case for regular m2o widgets! -->
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group expand='0' string='Group by...'>
|
||||
<filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}"/>
|
||||
<field name="name" string="Product"/>
|
||||
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
|
||||
<filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/>
|
||||
<separator/>
|
||||
<filter string="Can be Sold" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>
|
||||
<field string="Product Variant" name="product_variant_ids" filter_domain="['|', ('product_variant_ids.name','ilike',self), ('product_variant_ids.attribute_value_ids.name','ilike',self)]"/>
|
||||
<field name="company_id"/>
|
||||
<field name="pricelist_id" widget="selection" context="{'pricelist': self}" filter_domain="[]" groups="product.group_sale_pricelist"/> <!-- Keep widget=selection on this field to pass numeric `self` value, which is not the case for regular m2o widgets! -->
|
||||
<group expand='0' string='Group by...'>
|
||||
<filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
|
||||
<filter string='Company' icon="terp-go-home" domain="[]" context="{'group_by' : 'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string='Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}" groups="product.group_product_variant"/>
|
||||
</group>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_product_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.product.tree</field>
|
||||
<field name="model">product.product</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<record id="product_template_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.tree</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Products">
|
||||
<field name="default_code"/>
|
||||
<tree string="Product">
|
||||
<field name="name"/>
|
||||
<field name="variants" groups="product.group_product_variant"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="uom_id" string="Unit of Measure" groups="product.group_uom"/>
|
||||
<field name="lst_price"/>
|
||||
<field name="price" invisible="not context.get('pricelist',False)"/>
|
||||
<field name="standard_price" invisible="1"/>
|
||||
<field name="categ_id"/>
|
||||
<field name="type"/>
|
||||
<field name="state"/>
|
||||
<field name="company_id" groups="base.group_multi_company" invisible="1"/>
|
||||
<field name="product_tmpl_id" invisible="1"/>
|
||||
<field name="uom_id" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product.normal.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Product" version="7.0">
|
||||
<field name="is_product_variant" invisible="1"/>
|
||||
<sheet>
|
||||
<field name="is_only_child" invisible="1"/>
|
||||
<field name="image_medium" widget="image" class="oe_avatar oe_left"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name" name='label_name' string="Product Name"
|
||||
attrs="{'invisible': [('is_only_child', '=', False)]}"/>
|
||||
<label for="name" name='label_name' string="Product Template"
|
||||
attrs="{'invisible': [('is_only_child', '=', True)]}"/>
|
||||
</div>
|
||||
<h1>
|
||||
<field name="name" class="oe_inline"
|
||||
attrs="{'required': [('is_only_child', '=', True)],
|
||||
'invisible': [('is_only_child', '=', False)]}"/>
|
||||
<field name="product_tmpl_id" class="oe_inline" readonly="1" required="0"
|
||||
attrs="{'invisible': [('is_only_child', '=', True)]}"/>
|
||||
<span groups="product.group_product_variant"
|
||||
attrs="{'invisible': [('is_only_child', '=', True), ('variants', '=', False)]}">
|
||||
- <field name="variants" placeholder="Variant Name" class="oe_inline"/>
|
||||
</span>
|
||||
</h1>
|
||||
<span attrs="{'invisible': [('is_only_child', '=', True)]}">
|
||||
<p>Generic product settings are managed on
|
||||
<button name="open_product_template" type="object" string="the template" class="oe_link"/>
|
||||
</p>
|
||||
</span>
|
||||
<label for="categ_id" class="oe_edit_only"/>
|
||||
<h2><field name="categ_id" attrs="{'readonly': [('is_only_child', '=', False)]}"/></h2>
|
||||
<label for="public_categ_id" class="oe_edit_only"/>
|
||||
<h3><field name="public_categ_id" attrs="{'readonly': [('is_only_child', '=', False)]}"/></h3>
|
||||
<div name="options" groups="base.group_user">
|
||||
<field name="sale_ok"/>
|
||||
<label for="sale_ok"/>
|
||||
</div>
|
||||
<field name="id" invisible="True"/>
|
||||
<div class="oe_right oe_button_box" style="width: 300px;" name="buttons">
|
||||
</div>
|
||||
<div class="oe_right oe_button_box" name="buttons">
|
||||
<div class="oe_left" style="width: 500px;">
|
||||
<field name="image_medium" widget="image" class="oe_avatar oe_left"/>
|
||||
<div class="oe_title" style="width: 390px;">
|
||||
<label class="oe_edit_only" for="name" string="Product Name"/>
|
||||
<h1><field name="name" class="oe_inline"/></h1>
|
||||
</div>
|
||||
<div class="oe_left" name="options" groups="base.group_user">
|
||||
<div>
|
||||
<field name="sale_ok"/>
|
||||
<label for="sale_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Information">
|
||||
<group>
|
||||
<group colspan="4">
|
||||
<group>
|
||||
<field name="type"
|
||||
attrs="{'invisible': [('is_only_child', '=', False)]}"/>
|
||||
<field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"
|
||||
attrs="{'invisible': [('is_only_child', '=', False)]}"/>
|
||||
<field name="lst_price" string="Public Sale Price"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="price_extra"
|
||||
attrs="{'invisible': [('is_only_child', '=', True)]}"/>
|
||||
<field name="type"/>
|
||||
<field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/>
|
||||
<field name="lst_price"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="active"/>
|
||||
<field name="ean13"/>
|
||||
<field name="default_code"/>
|
||||
<label for="ean13"/>
|
||||
<div name="ean">
|
||||
<field name="ean13" placeholder="e.g. 5901234123457"/>
|
||||
</div>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"
|
||||
attrs="{'invisible': [('is_only_child', '=', False)]}"/>
|
||||
<field name="active" />
|
||||
</group>
|
||||
</group>
|
||||
<field name="description" placeholder="describe the product characteristics..."
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<group colspan="4">
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
<field name="description" placeholder="describe the product characteristics..."/>
|
||||
</page>
|
||||
<page string="Procurements" groups="base.group_user">
|
||||
<group name="procurement">
|
||||
<group name="general">
|
||||
<field name="standard_price" attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="standard_price"/>
|
||||
</group>
|
||||
<group name="procurement_uom" groups="product.group_uom" string="Purchase">
|
||||
<field name="uom_po_id"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="uom_po_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Suppliers"/>
|
||||
<field name="seller_ids"/>
|
||||
<separator string="Description for Suppliers"/>
|
||||
<field name="description_purchase" placeholder="This note will be displayed on requests for quotation..."/>
|
||||
</page>
|
||||
<page string="Inventory" groups="base.group_user">
|
||||
<page string="Inventory">
|
||||
<group name="inventory">
|
||||
<group name="status" string="Status">
|
||||
<field name="state"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="product_manager"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"
|
||||
context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_manager']}"/>
|
||||
<group name="status" string="Status">
|
||||
<field name="state"/>
|
||||
<field name="product_manager"/>
|
||||
</group>
|
||||
<group name="Weights" groups="product.group_stock_packaging" string="Weights">
|
||||
<field digits="(14, 3)" name="volume"
|
||||
attrs="{'readonly': ['|', ('type','=','service'), ('is_only_child', '=', False)]}"/>
|
||||
<field name="weight"
|
||||
attrs="{'readonly': ['|', ('type','=','service'), ('is_only_child', '=', False)]}"/>
|
||||
<field name="weight_net"
|
||||
attrs="{'readonly': ['|', ('type','=','service'), ('is_only_child', '=', False)]}"/>
|
||||
<group name="weight" string="Weights">
|
||||
<field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}">
|
||||
<group name="sale">
|
||||
<group string="Sale Conditions">
|
||||
<group name="sale_condition" string="Sale Conditions" colspan="3">
|
||||
<label for="warranty"/>
|
||||
<div attrs="{'readonly': [('is_only_child', '=', False)]}">
|
||||
<div>
|
||||
<field name="warranty" class="oe_inline"/> months
|
||||
</div>
|
||||
</group>
|
||||
<group groups="product.group_uos" string="Unit of Measure">
|
||||
<field name="uos_id"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="uos_coeff"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="mes_type"
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="uos_id"/>
|
||||
<field name="uos_coeff"/>
|
||||
<field name="mes_type"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Packages" groups="product.group_stock_packaging"/>
|
||||
<field name="packaging" groups="product.group_stock_packaging" attrs="{'readonly': [('is_only_child', '=', False)]}">
|
||||
<form string="Packaging" version="7.0">
|
||||
<group col="4">
|
||||
<field name="ean"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
<newline/>
|
||||
<field name="qty"/>
|
||||
<field name="ul"/>
|
||||
<separator colspan="4" string="Palletization"/>
|
||||
<field name="ul_qty"/>
|
||||
<field name="ul_container" domain="[('type', '=', 'pallet')]" context="{'default_type': 'pallet'}"/>
|
||||
<field name="rows"/>
|
||||
<field name="weight"/>
|
||||
</group>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field name="name"/>
|
||||
</form>
|
||||
</field>
|
||||
<group name="website_and_pos" col="2">
|
||||
</group>
|
||||
<separator string="Description for Quotations"/>
|
||||
<field name="description_sale" placeholder="note to be displayed on quotations..."
|
||||
attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
<field name="description_sale" placeholder="note to be displayed on quotations..."/>
|
||||
</page>
|
||||
<page name="variants" string="Variants">
|
||||
<field name="attribute_line_ids" widget="one2many_list">
|
||||
<tree string="Variants" editable="bottom">
|
||||
<field name="attribute_id"/>
|
||||
<field name="value_ids" widget="many2many_tags" domain="[('attribute_id', '=', attribute_id)]" context="{'default_attribute_id': attribute_id}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
|
@ -204,24 +146,21 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Product Kanban View -->
|
||||
|
||||
<record model="ir.ui.view" id="product.product_kanban_view">
|
||||
<field name="name">Product Kanban</field>
|
||||
<field name="model">product.product</field>
|
||||
<record id="product_template_kanban_view" model="ir.ui.view">
|
||||
<field name="name">Product.template.product.kanban</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="color"/>
|
||||
<field name="type"/>
|
||||
<field name="list_price"/>
|
||||
<field name="image_small"/>
|
||||
<field name="lst_price"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_vignette oe_semantic_html_override">
|
||||
<a type="open"><img t-att-src="kanban_image('product.product', 'image_small', record.id.value)" class="oe_kanban_image"/></a>
|
||||
<a type="open"><img t-att-src="kanban_image('product.template', 'image_small', record.id.value)" class="oe_kanban_image"/></a>
|
||||
<div class="oe_kanban_details">
|
||||
<h4>
|
||||
<a type="open">
|
||||
<t t-if="record.code.raw_value">[<field name="code"/>]</t> <field name="name"/> <t t-if="record.variants.raw_value">(<field name="variants"/>)</t>
|
||||
<field name="name"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div name="tags"/>
|
||||
|
@ -236,13 +175,134 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_normal_action" model="ir.actions.act_window">
|
||||
<record id="product_template_action" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="res_model">product.template</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="product_template_kanban_view"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="product_template_action"
|
||||
id="menu_product_template_action"
|
||||
parent="base.menu_product" sequence="1" />
|
||||
|
||||
<!-- variants -->
|
||||
|
||||
<record id="variants_template_tree_view" model="ir.ui.view">
|
||||
<field name="name">variants.template.tree</field>
|
||||
<field name="model">product.attribute.value</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Variant Values" editable="top">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="attribute_id"/>
|
||||
<field name="name"/>
|
||||
<field name="price_extra"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="variants_template_action" model="ir.actions.act_window">
|
||||
<field name="name">Variant Values</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.attribute.value</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('product_ids.product_tmpl_id', '=', active_id)]</field>
|
||||
<field name="context">{'default_product_tmpl_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
<!-- product product -->
|
||||
|
||||
<menuitem id="prod_config_main" name="Product Variants" parent="base.menu_base_config" sequence="70" groups="base.group_no_one"/>
|
||||
|
||||
<record id="product_search_form_view" model="ir.ui.view">
|
||||
<field name="name">product.product.search</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="product.product_template_search_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="replace">
|
||||
<field name="name" string="Product" filter_domain="['|',('default_code','ilike',self),('name','ilike',self)]"/>
|
||||
</field>
|
||||
<field name="product_variant_ids" position="replace">
|
||||
<field name="attribute_value_ids"/>
|
||||
</field>
|
||||
<field name="name" position="after">
|
||||
<field name="product_tmpl_id" string="Product Template"/>
|
||||
</field>
|
||||
<xpath expr="//group[@string='Group by...']" position="inside">
|
||||
<filter string='Product Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_product_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.product.tree</field>
|
||||
<field name="model">product.product</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
|
||||
<tree string="Product Variants">
|
||||
<field name="default_code"/>
|
||||
<field name="name"/>
|
||||
<field name="attribute_value_ids" widget="many2many_tags"/>
|
||||
<field name="lst_price"/>
|
||||
<field name="price" invisible="not context.get('pricelist',False)"/>
|
||||
<field name="uom_id"/>
|
||||
<field name="ean13"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="product_tmpl_id" invisible="1"/>
|
||||
</tree>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product.product.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="mode">primary</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<form position="attributes">
|
||||
<attribute name="string">Product Variant</attribute>
|
||||
</form>
|
||||
<field name="name" position="replace">
|
||||
<field name="name" attrs="{'invisible': [('id', '!=', False)]}"/>
|
||||
<field name="product_tmpl_id" class="oe_inline" readonly="1" attrs="{'invisible': [('id', '=', False)]}"/>
|
||||
</field>
|
||||
<xpath expr="//div[@class='oe_title']" position="inside">
|
||||
<field name="attribute_value_ids" widget="many2many_tags"/>
|
||||
</xpath>
|
||||
<page name="variants" position="replace">
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_kanban_view" model="ir.ui.view">
|
||||
<field name="name">Product Kanban</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="product.product_template_kanban_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="attribute_value_ids"/>
|
||||
</field>
|
||||
<xpath expr="//img[@class='oe_kanban_image']" position="replace">
|
||||
<img t-att-src="kanban_image('product.product', 'image_small', record.id.value)" class="oe_kanban_image"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<record id="product_normal_action" model="ir.actions.act_window">
|
||||
<field name="name">Product Variants</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_mode">tree,form,kanban</field>
|
||||
<field name="view_id" ref="product_product_tree_view"/>
|
||||
<field name="view_type">form</field>
|
||||
<field name="search_view_id" ref="product_search_form_view"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
|
@ -253,8 +313,65 @@
|
|||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<record id="product_variant_action" model="ir.actions.act_window">
|
||||
<field name="name">Product Variants</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_mode">tree,form,kanban</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{'search_default_product_tmpl_id': [active_id], 'default_product_tmpl_id': active_id}</field>
|
||||
<field name="search_view_id" ref="product_search_form_view"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new product.
|
||||
</p><p>
|
||||
You must define a product for everything you buy or sell,
|
||||
whether it's a physical product, a consumable or service.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view_variant_button" model="ir.ui.view">
|
||||
<field name="name">product.template.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="attribute_line_ids" position="before">
|
||||
<div class="oe_right">
|
||||
<button class="oe_inline oe_stat_button" string="Variant Prices" name="%(product.variants_template_action)d" type="action" icon="fa-strikethrough"/>
|
||||
<button class="oe_inline oe_stat_button" name="%(product.product_variant_action)d" type="action" icon="fa-sitemap">
|
||||
<field string="List of Variants" name="product_variant_count" widget="statinfo" />
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_kanban_view_variant_button" model="ir.ui.view">
|
||||
<field name="name">product.template.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_kanban_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="lst_price" position="after">
|
||||
<field name="is_product_variant"/>
|
||||
<field name="product_variant_count"/>
|
||||
<field name="product_variant_ids"/>
|
||||
</field>
|
||||
<h4 position="after">
|
||||
<a name="%(product.product_variant_action)d" type="action" t-if="!record.is_product_variant.raw_value & record.product_variant_count.raw_value>1">
|
||||
<t t-esc="record.product_variant_count.value"/> Variants
|
||||
</a>
|
||||
</h4>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<record id="product_normal_action_sell" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
<field name="name">Product Variants</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
|
@ -277,53 +394,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_view_product_tree1" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="product_product_tree_view"/>
|
||||
<field name="act_window_id" ref="product_normal_action_sell"/>
|
||||
</record>
|
||||
|
||||
<record id="open_view_product_form1" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="product_normal_form_view"/>
|
||||
<field name="act_window_id" ref="product_normal_action_sell"/>
|
||||
</record>
|
||||
|
||||
<record id="open_view_product_kanban1" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="product_kanban_view"/>
|
||||
<field name="act_window_id" ref="product_normal_action_sell"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="base.menu_product" name="Products" parent="base.menu_base_partner" sequence="9"/>
|
||||
<menuitem id="product.menu_products" action="product.product_normal_action_sell" parent="base.menu_product" sequence="1"/>
|
||||
|
||||
<record id="product_normal_action_puchased" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{"search_default_filter_to_purchase":1}</field>
|
||||
<field name="view_id" ref="product_kanban_view"/>
|
||||
<field name="search_view_id" ref="product_search_form_view"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new product.
|
||||
</p><p>
|
||||
You must define a product for everything you purchase, whether
|
||||
it's a physical product, a consumable or services you buy to
|
||||
subcontractants.
|
||||
</p><p>
|
||||
The product form contains detailed information to improve the
|
||||
purchase process: prices, procurement logistics, accounting data,
|
||||
available suppliers, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem id="product.menu_products" action="product.product_normal_action_sell" parent="base.menu_product" groups="base.group_no_one" sequence="10"/>
|
||||
|
||||
<record id="product_category_search_view" model="ir.ui.view">
|
||||
<field name="name">product.category.search</field>
|
||||
|
@ -412,7 +483,7 @@
|
|||
|
||||
|
||||
<record id="product_normal_action_tree" model="ir.actions.act_window">
|
||||
<field name="name">Products</field>
|
||||
<field name="name">Product Variants</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_type">form</field>
|
||||
|
@ -426,60 +497,6 @@
|
|||
<field eval="'ir.actions.act_window,%d'%product_normal_action_tree" name="value"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Product Public Categories -->
|
||||
<record id="product_public_category_form_view" model="ir.ui.view">
|
||||
<field name="name">product.public.category.form</field>
|
||||
<field name="model">product.public.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Pos/Public Categories" version="7.0">
|
||||
<sheet>
|
||||
<field name="image_medium" widget='image' class="oe_avatar oe_right"/>
|
||||
<div class="oe_left">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="sequence"/>
|
||||
</group>
|
||||
</div>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_public_category_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.public.category.tree</field>
|
||||
<field name="model">product.public.category</field>
|
||||
<field name="field_parent" eval="False"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Product Product Categories">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="complete_name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_public_category_action" model="ir.actions.act_window">
|
||||
<field name="name">Pos/Public Product Categories</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.public.category</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new category.
|
||||
</p><p>
|
||||
Categories are used to browse your products through the
|
||||
touchscreen interface.
|
||||
</p><p>
|
||||
If you put a photo on the category, the layout of the
|
||||
touchscreen interface will automatically. We suggest not to put
|
||||
a photo on categories for small (1024x768) screens.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem action="product_public_category_action" id="menu_product_public_category" parent="prod_config_main" sequence="10" />
|
||||
<!-- END -->
|
||||
|
||||
<!-- Unit of Measure -->
|
||||
|
||||
<record id="product_uom_tree_view" model="ir.ui.view">
|
||||
|
@ -704,261 +721,5 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Variants -->
|
||||
<record id="product_variant_search_form_view" model="ir.ui.view">
|
||||
<field name="name">product.variant.search.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Product Variant">
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="name" string="Product" filter_domain="['|','|',('name','ilike',self),('default_code','ilike',self),('variants','ilike',self)]"/>
|
||||
<group expand='0' string='Group by...'>
|
||||
<filter string='Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_variant_form_view" model="ir.ui.view">
|
||||
<field name="name">product.variant.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Product Variant" version="7.0">
|
||||
<group col="4">
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="active"/>
|
||||
<field name="variants" required="1"/>
|
||||
<field name="default_code"/>
|
||||
<field name="price_margin"/>
|
||||
<field name="price_extra"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_variant_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.variant.tree</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Product Variant">
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="variants"/>
|
||||
<field name="default_code"/>
|
||||
<field name="price_margin"/>
|
||||
<field name="price_extra"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="uom_id" invisible="1"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="product_variant_action" model="ir.actions.act_window">
|
||||
<field name="name">Product Variants</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="domain">[('variants','!=', '')]</field>
|
||||
<field name="res_model">product.product</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,kanban</field>
|
||||
<field name="view_id" ref="product_variant_tree_view"/>
|
||||
<field name="search_view_id" ref="product_variant_search_form_view"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new variant of product.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record id="tree_view_product_variant" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="product_variant_tree_view"/>
|
||||
<field name="act_window_id" ref="product_variant_action"/>
|
||||
</record>
|
||||
<record id="form_view_product_variant" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="product_variant_form_view"/>
|
||||
<field name="act_window_id" ref="product_variant_action"/>
|
||||
</record>
|
||||
<menuitem action="product.product_variant_action" id="product.menu_variant_product" parent="prod_config_main" sequence="4" groups="product.group_product_variant"/>
|
||||
|
||||
<!-- templates -->
|
||||
|
||||
<record id="product_template_search_view" model="ir.ui.view">
|
||||
<field name="name">product.template.search</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Product Template">
|
||||
<field name="name" string="Product"/>
|
||||
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
|
||||
<filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/>
|
||||
<separator/>
|
||||
<filter string="Can be Sold" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>
|
||||
<field name="categ_id"/>
|
||||
<group expand='0' string='Group by...'>
|
||||
<filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}"/>
|
||||
<filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.tree</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Product Template">
|
||||
<field name="name"/>
|
||||
<field name="categ_id"/>
|
||||
<field name="type"/>
|
||||
<field name="state"/>
|
||||
<field name="uom_id" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.product.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Product Template" version="7.0">
|
||||
<sheet>
|
||||
<field name="image_medium" widget="image" class="oe_avatar oe_left"/>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name" string="Product Name"/>
|
||||
</div>
|
||||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
<label for="categ_id" class="oe_edit_only"/>
|
||||
<h2><field name="categ_id"/></h2>
|
||||
<label for="public_categ_id" class="oe_edit_only"/>
|
||||
<h3><field name="public_categ_id"/></h3>
|
||||
<div name="options" groups="base.group_user">
|
||||
<field name="sale_ok"/>
|
||||
<label for="sale_ok"/>
|
||||
</div>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Information">
|
||||
<group colspan="4">
|
||||
<group>
|
||||
<field name="type"/>
|
||||
<field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/>
|
||||
<field name="list_price"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
</group>
|
||||
<group colspan="4" string="Product Variants" groups="product.group_product_variant">
|
||||
<field colspan="4" name="product_variant_ids" nolabel="1" >
|
||||
<tree string="Product Variants" editable="bottom">
|
||||
<field name="variants" required="1"/>
|
||||
<field name="price_margin" string="Variant Price Margin"/>
|
||||
<field name="price_extra"/>
|
||||
<field name="lst_price" string="Sale Price" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<field name="description" placeholder="describe the product characteristics..."/>
|
||||
</page>
|
||||
<page string="Procurements" groups="base.group_user">
|
||||
<group name="procurement">
|
||||
<group name="general">
|
||||
<field name="standard_price" attrs="{'readonly': [('is_only_child', '=', False)]}"/>
|
||||
</group>
|
||||
<group name="procurement_uom" groups="product.group_uom" string="Purchase">
|
||||
<field name="uom_po_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Suppliers"/>
|
||||
<field name="seller_ids"/>
|
||||
<separator string="Description for Suppliers"/>
|
||||
<field name="description_purchase" placeholder="This note will be displayed on requests for quotation..."/>
|
||||
</page>
|
||||
<page string="Inventory">
|
||||
<group name="inventory">
|
||||
<group name="status" string="Status">
|
||||
<field name="state"/>
|
||||
<field name="product_manager"/>
|
||||
</group>
|
||||
<group name ="weight" string="Weights">
|
||||
<field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}">
|
||||
<group name="sale">
|
||||
<group name="sale_condition" string="Sale Conditions">
|
||||
<label for="warranty"/>
|
||||
<div>
|
||||
<field name="warranty" class="oe_inline" style="vertical-align:baseline"/> months
|
||||
</div>
|
||||
</group>
|
||||
<group groups="product.group_uos" string="Unit of Measure">
|
||||
<field name="uos_id"/>
|
||||
<field name="uos_coeff"/>
|
||||
<field name="mes_type"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Description for Quotations"/>
|
||||
<field name="description_sale" placeholder="note to be displayed on quotations..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_template_kanban_view">
|
||||
<field name="name">Product Template Kanban</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="image_small"/>
|
||||
<field name="list_price"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_vignette oe_semantic_html_override">
|
||||
<a type="open"><img t-att-src="kanban_image('product.template', 'image_small', record.id.value)" class="oe_kanban_image"/></a>
|
||||
<div class="oe_kanban_details">
|
||||
<h4>
|
||||
<a type="open">
|
||||
<field name="name"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div name="tags"/>
|
||||
<ul>
|
||||
<li>Price: <field name="list_price"></field></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_action" model="ir.actions.act_window">
|
||||
<field name="name">Templates</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">product.template</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="product_template_kanban_view"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="product_template_action"
|
||||
id="menu_product_template_action"
|
||||
parent="base.menu_product" sequence="20"
|
||||
groups="product.group_product_variant"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<lot-line type="fields" name="id">
|
||||
<code type="field" name="code"/>
|
||||
<product type="field" name="name"/>
|
||||
<variant type="field" name="variants"/>
|
||||
<variant type="field" name="attribute_value_ids"/>
|
||||
<price type="field" name="list_price"/>
|
||||
<ean13 type="field" name="ean13"/>
|
||||
<currency type="field" name="company_id.currency_id.name"/>
|
||||
|
|
|
@ -19,5 +19,11 @@ access_product_price_history_employee,prices.history employee,model_product_pric
|
|||
access_product_template_sale_manager,product.template salemanager,model_product_template,base.group_sale_manager,1,1,1,1
|
||||
access_product_product_sale_manager,product.product salemanager,model_product_product,base.group_sale_manager,1,1,1,1
|
||||
access_product_category_sale_manager,product.category salemanager,product.model_product_category,base.group_sale_manager,1,1,1,1
|
||||
access_product_category_pos_manager,product.public.category manager,model_product_public_category,base.group_sale_manager,1,1,1,1
|
||||
access_product_category_pos_user,product.public.category user,model_product_public_category,base.group_user,1,0,0,0
|
||||
access_product_attribute,product.attribute,model_product_attribute,base.group_user,1,0,0,0
|
||||
access_product_attribute_value,product.attribute value,model_product_attribute_value,base.group_user,1,0,0,0
|
||||
access_product_attribute_price,product.attribute price,model_product_attribute_price,base.group_user,1,0,0,0
|
||||
access_product_attribute_line,product.attribute line,model_product_attribute_line,base.group_user,1,0,0,0
|
||||
access_product_attribute_sale_manager,product.attribute manager,model_product_attribute,base.group_sale_manager,1,1,1,1
|
||||
access_product_attribute_value_sale_manager,product.attribute manager value,model_product_attribute_value,base.group_sale_manager,1,1,1,1
|
||||
access_product_attribute_price_sale_manager,product.attribute manager price,model_product_attribute_price,base.group_sale_manager,1,1,1,1
|
||||
access_product_attribute_line_sale_manager,product.attribute manager line,model_product_attribute_line,base.group_sale_manager,1,1,1,1
|
||||
|
|
|
|
@ -1,21 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
<!-- Change name of group for 7.0 users since product variant module doesn't exist anymore
|
||||
DO NOT CHANGE IT IN TRUNK -->
|
||||
|
||||
<record id="group_product_variant" model="res.groups">
|
||||
<field name="name">Manage Product Variants</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="group_product_mono" model="res.groups">
|
||||
<field name="name">Do Not Manage Product Variants</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
<record id="base.group_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('product.group_product_mono'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="group_sale_pricelist" model="res.groups">
|
||||
<field name="name">Sales Pricelists</field>
|
||||
|
|
|
@ -6,19 +6,19 @@
|
|||
!python {model: product.product}: |
|
||||
context.update({'pricelist': ref("customer_pricelist"), 'quantity':1})
|
||||
product = self.browse(cr, uid, ref("product_product_4"), context=context)
|
||||
assert product.price == (product.lst_price-product.lst_price*(0.10)), "Wrong sale price."
|
||||
assert product.price == (product.lst_price-product.lst_price*(0.10)), "Wrong sale price: Assemble Computer."
|
||||
-
|
||||
I check sale price of Laptop.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref("product_product_25"), context=context)
|
||||
assert product.price == product.lst_price + 1, "Wrong sale price."
|
||||
assert product.price == product.lst_price + 1, "Wrong sale price: Laptop."
|
||||
-
|
||||
I check sale price of IT component.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref("product_product_7"), context=context)
|
||||
assert product.price == product.lst_price, "Wrong sale price."
|
||||
assert product.price == product.lst_price, "Wrong sale price: IT component."
|
||||
|
||||
-
|
||||
I check sale price of IT component if more than 3 Unit.
|
||||
|
@ -26,14 +26,14 @@
|
|||
!python {model: product.product}: |
|
||||
context.update({'quantity':5})
|
||||
product = self.browse(cr, uid, ref("product_product_26"), context=context)
|
||||
assert product.price == product.lst_price-product.lst_price*(0.05), "Wrong sale price."
|
||||
assert product.price == product.lst_price-product.lst_price*(0.05), "Wrong sale price: IT component if more than 3 Unit."
|
||||
-
|
||||
I check sale price of LCD Monitor.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
context.update({'quantity':1})
|
||||
product = self.browse(cr, uid, ref("product_product_6"), context=context)
|
||||
assert product.price == product.lst_price, "Wrong sale price."
|
||||
assert product.price == product.lst_price, "Wrong sale price: LCD Monitor."
|
||||
|
||||
-
|
||||
I check sale price of LCD Monitor on end of year.
|
||||
|
@ -41,7 +41,7 @@
|
|||
!python {model: product.product}: |
|
||||
context.update({'quantity':1, 'date': '2011-12-31'})
|
||||
product = self.browse(cr, uid, ref("product_product_6"), context=context)
|
||||
assert product.price == product.lst_price-product.lst_price*(0.30), "Wrong sale price."
|
||||
assert product.price == product.lst_price-product.lst_price*(0.30), "Wrong sale price: LCD Monitor on end of year."
|
||||
|
||||
-
|
||||
I check cost price of LCD Monitor.
|
||||
|
@ -49,14 +49,14 @@
|
|||
!python {model: product.product}: |
|
||||
context.update({'quantity':1, 'date': False, 'partner': ref('base.res_partner_4'), 'pricelist': ref("supplier_pricelist")})
|
||||
product = self.browse(cr, uid, ref("product_product_6"), context=context)
|
||||
assert product.price == 792, "wrong cost price."
|
||||
assert product.price == 792, "wrong cost price: LCD Monitor."
|
||||
-
|
||||
I check cost price of LCD Monitor if more than 3 Unit.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
context.update({'quantity':3})
|
||||
product = self.browse(cr, uid, ref("product_product_6"), context=context)
|
||||
assert product.price == 787, "wrong cost price."
|
||||
assert product.price == 787, "wrong cost price: LCD Monitor if more than 3 Unit."
|
||||
|
||||
-
|
||||
I print the sale prices report.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="product_normal_form_view_template" model="ir.ui.view">
|
||||
<field name="name">product.normal.procurement.locations.inherit</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<record id="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">product.template.form.inherit</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="after">
|
||||
<field name="email_template_id"
|
||||
|
@ -15,7 +15,7 @@
|
|||
'default_subject': name,
|
||||
'default_name': name,
|
||||
}"
|
||||
attrs="{'invisible': [('is_only_child', '=', False)]}"
|
||||
attrs="{'invisible': [('is_product_variant', '=', False)]}"
|
||||
/>
|
||||
</field>
|
||||
</field>
|
||||
|
|
|
@ -98,7 +98,7 @@ class stock_quant(osv.osv):
|
|||
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = 'product.product'
|
||||
_inherit = 'product.template'
|
||||
_columns = {
|
||||
'life_time': fields.integer('Product Life Time',
|
||||
help='When a new a Serial Number is issued, this is the number of days before the goods may become dangerous and must not be consumed.'),
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
|
||||
<record model="ir.ui.view" id="view_product_form_expiry">
|
||||
<field name="name">product.normal.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="stock.view_normal_procurement_locations_form" />
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="Weights" position="after">
|
||||
<group name="weight" position="after">
|
||||
<group string="Dates">
|
||||
<field name="life_time" />
|
||||
<field name="use_time" />
|
||||
|
|
|
@ -36,7 +36,7 @@ class product_product(osv.osv):
|
|||
testdict = {}
|
||||
for prod_id in ids:
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
bom_ids = bom_obj.search(cr, uid, [('bom_id', '=', False), ('product_id','=', prod_id), ('bom_lines', '!=', False)], context=context)
|
||||
bom_ids = bom_obj.search(cr, uid, [('product_id','=', prod_id), ('bom_line_ids', '!=', False)], context=context)
|
||||
if bom_ids:
|
||||
bom_id = bom_ids[0]
|
||||
# In recursive mode, it will first compute the prices of child boms
|
||||
|
@ -63,9 +63,9 @@ class product_product(osv.osv):
|
|||
context={}
|
||||
price = 0
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
if bom.bom_lines:
|
||||
for sbom in bom.bom_lines:
|
||||
my_qty = sbom.bom_lines and 1.0 or sbom.product_qty
|
||||
if bom.bom_line_ids:
|
||||
for sbom in bom.bom_line_ids:
|
||||
my_qty = sbom.bom_line_ids and 1.0 or sbom.product_qty
|
||||
price += uom_obj._compute_price(cr, uid, sbom.product_id.uom_id.id, sbom.product_id.standard_price, sbom.product_uom.id) * my_qty
|
||||
|
||||
if bom.routing_id:
|
||||
|
@ -98,7 +98,7 @@ class product_bom(osv.osv):
|
|||
_inherit = 'mrp.bom'
|
||||
|
||||
_columns = {
|
||||
'standard_price': fields.related('product_id','standard_price',type="float",relation="product.product",string="Standard Price",store=False)
|
||||
'standard_price': fields.related('product_tmpl_id','standard_price',type="float",relation="product.product",string="Standard Price",store=False)
|
||||
}
|
||||
|
||||
product_bom()
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
{
|
||||
'name': 'Products Manufacturers',
|
||||
'version': '1.0',
|
||||
'author': 'OpenERP SA',
|
||||
'category': 'Purchase Management',
|
||||
'depends': ['stock'],
|
||||
'demo': [],
|
||||
'description': """
|
||||
A module that adds manufacturers and attributes on the product form.
|
||||
====================================================================
|
||||
|
||||
You can now define the following for a product:
|
||||
-----------------------------------------------
|
||||
* Manufacturer
|
||||
* Manufacturer Product Name
|
||||
* Manufacturer Product Code
|
||||
* Product Attributes
|
||||
""",
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'product_manufacturer_view.xml'
|
||||
],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
'images': ['images/products_manufacturer.jpeg'],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -1,75 +0,0 @@
|
|||
# Arabic translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2012-01-12 22:07+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Arabic <ar@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "كود تصنيع المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "اسم قالب المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "سمات المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "سمات المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "الخاصية"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "قيمة"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "صفات"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "اسم مصنع المنتج"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "مصنّع"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "خطأ: كود إين غير صالح"
|
|
@ -1,81 +0,0 @@
|
|||
# Bulgarian translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2011-02-10 23:42+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Bulgarian <bg@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Код на производител"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Продукт"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Име на шаблона на продукта"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Атрибути на продукта"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Атрибути на продукта"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Атрибут"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Стойност"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Атрибути"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Име на производител"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Производител"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Грешка: Невалиден европейски баркод"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr "Модул, който добавя производители и атрибути във формата на продукта"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Продуктови атрибути и производители"
|
|
@ -1,72 +0,0 @@
|
|||
# Bosnian translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-10-30 00:09+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Bosnian <bs@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Proizvođačka šifra artikla"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Proizvod"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Naziv predloška proizvoda"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributi proizvoda"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributi proizvoda"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atribut"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Vrijednost"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Proizvođački naziv proizvoda"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Proizvođač"
|
|
@ -1,82 +0,0 @@
|
|||
# Catalan translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2011-02-12 21:08+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Catalan <ca@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Codi de producte del fabricant"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producte"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nom de plantilla de producte"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributs de producte"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributs del producte"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atribut"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributs"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Nom del producte del fabricant"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricant"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr ""
|
||||
#~ "Un mòdul que afegeix fabricants i atributs en el formulari de producte"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Error: Codi EAN no vàlid"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Fabricants i atributs dels productes"
|
|
@ -1,72 +0,0 @@
|
|||
# Czech translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2012-12-31 10:46+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Czech <cs@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Kód výrobku od výrobce"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Výrobek"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Název šalony výrobku"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Vlastnosti výrobku"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Vlastnosti výrobku"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Vlastnost"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Hodnota"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Vlastnosti"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Název výrobku od výrobce"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Výrobce"
|
|
@ -1,72 +0,0 @@
|
|||
# Danish translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2012-01-27 06:25+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Danish <da@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Producent varenummer"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Vare"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Vare skabelon navn"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Vare egenskaber"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Vare Egenskaber"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Egenskab"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Værdi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Egenskaber"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Producent Vare Navn"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Producent"
|
|
@ -1,83 +0,0 @@
|
|||
# German translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2011-02-12 20:19+0000\n"
|
||||
"Last-Translator: Steffi Frank (Bremskerl, DE) <Unknown>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Hersteller-Artikelnummer"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Produkt"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Produkt Vorlagenname"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Produkteigenschaften"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Produkteigenschaften"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Eigenschaft"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Wert"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Eigenschaften"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Hersteller-Produktname"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Hersteller"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Fehler: Falscher EAN code"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Produkt-Eigenschaften und -Produzenten"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr ""
|
||||
#~ "Ein Modul, durch das einem Produkt Produzenten und Merkmale hinzgefügt "
|
||||
#~ "werden können"
|
|
@ -1,75 +0,0 @@
|
|||
# Greek translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2010-11-11 15:58+0000\n"
|
||||
"Last-Translator: Dimitris Andavoglou <dimitrisand@gmail.com>\n"
|
||||
"Language-Team: Greek <el@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Κωδικός Κατασκευαστή"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Προϊόν"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Όνομα Προτύπου Προϊόντος"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Ιδιότητες προϊόντος"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Χαρακτηριστικά Προϊόντος"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Χαρακτηριστικό"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Τιμή"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Ιδιότητες"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Όνομα Προϊόντος Κατασκευαστή"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Κατασκευαστής"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Ιδιότητες Προϊόντος και Κατασκευαστές"
|
|
@ -1,83 +0,0 @@
|
|||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2010-12-08 21:40+0000\n"
|
||||
"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
|
||||
"<jesteve@zikzakmedia.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Código producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nombre de plantilla de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributos de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributos del producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Nombre producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricante"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr ""
|
||||
#~ "Un módulo que añade fabricantes y atributos en el formulario de producto"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Fabricantes y atributos de los productos"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Error: Código EAN no válido"
|
|
@ -1,84 +0,0 @@
|
|||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2012-02-17 00:27+0000\n"
|
||||
"Last-Translator: Carlos Vásquez (CLEARCORP) "
|
||||
"<carlos.vasquez@clearcorp.co.cr>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
"Language: es\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Código producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nombre de plantilla de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributos de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributos del producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Nombre producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricante"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Error: Código EAN no válido"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr ""
|
||||
#~ "Un módulo que añade fabricantes y atributos en el formulario de producto"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Fabricantes y atributos de los productos"
|
|
@ -1,79 +0,0 @@
|
|||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2010-09-19 00:08+0000\n"
|
||||
"Last-Translator: Borja López Soilán (NeoPolus) <borjalopezsoilan@gmail.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nombre de plantilla de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributos de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricante"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr ""
|
||||
#~ "Un módulo que añade fabricantes y atributos en el formulario de producto"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Fabricantes y atributos de los productos"
|
|
@ -1,89 +0,0 @@
|
|||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
|
||||
"PO-Revision-Date: 2010-12-08 21:40+0000\n"
|
||||
"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
|
||||
"<jesteve@zikzakmedia.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-09-05 05:46+0000\n"
|
||||
"X-Generator: Launchpad (build 13830)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.module.module,description:product_manufacturer.module_meta_information
|
||||
msgid "A module that add manufacturers and attributes on the product form"
|
||||
msgstr ""
|
||||
"Un módulo que añade fabricantes y atributos en el formulario de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Código producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nombre de plantilla de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributos de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributos del producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: constraint:product.product:0
|
||||
msgid "Error: Invalid ean code"
|
||||
msgstr "Error: Código EAN no válido"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.module.module,shortdesc:product_manufacturer.module_meta_information
|
||||
msgid "Products Attributes & Manufacturers"
|
||||
msgstr "Fabricantes y atributos de los productos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Nombre producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricante"
|
|
@ -1,89 +0,0 @@
|
|||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
|
||||
"PO-Revision-Date: 2010-12-08 21:40+0000\n"
|
||||
"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
|
||||
"<jesteve@zikzakmedia.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-09-05 05:46+0000\n"
|
||||
"X-Generator: Launchpad (build 13830)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.module.module,description:product_manufacturer.module_meta_information
|
||||
msgid "A module that add manufacturers and attributes on the product form"
|
||||
msgstr ""
|
||||
"Un módulo que añade fabricantes y atributos en el formulario de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Código producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Nombre de plantilla de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Atributos de producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Atributos del producto"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: constraint:product.product:0
|
||||
msgid "Error: Invalid ean code"
|
||||
msgstr "Error: Código EAN no válido"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Atributos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.module.module,shortdesc:product_manufacturer.module_meta_information
|
||||
msgid "Products Attributes & Manufacturers"
|
||||
msgstr "Fabricantes y atributos de los productos"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Nombre producto fabricante"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Fabricante"
|
|
@ -1,72 +0,0 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2010-06-25 18:10+0000\n"
|
||||
"Last-Translator: lyyser <Unknown>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Tootja tootekood"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Toode"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Toote malli nimi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Toote omadused"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Toote omadused"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Atribuut"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Väärtus"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Omadused"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Tootja tootenimi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Tootja"
|
|
@ -1,81 +0,0 @@
|
|||
# Finnish translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2011-06-20 10:09+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Finnish <fi@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-22 07:26+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pref:0
|
||||
msgid "Manufacturer Product Code"
|
||||
msgstr "Valmistajan tuotekoodi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_product
|
||||
#: field:product.manufacturer.attribute,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Tuote"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
msgid "Product Template Name"
|
||||
msgstr "Tuotemallipohjan nimi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: model:ir.model,name:product_manufacturer.model_product_manufacturer_attribute
|
||||
msgid "Product attributes"
|
||||
msgstr "Tuotteen attribuutit"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.manufacturer.attribute:0
|
||||
#: view:product.product:0
|
||||
msgid "Product Attributes"
|
||||
msgstr "Tuotteen attribuutit"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,name:0
|
||||
msgid "Attribute"
|
||||
msgstr "Attribuutti"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.manufacturer.attribute,value:0
|
||||
msgid "Value"
|
||||
msgstr "Arvo"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,attribute_ids:0
|
||||
msgid "Attributes"
|
||||
msgstr "Attribuutit"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: field:product.product,manufacturer_pname:0
|
||||
msgid "Manufacturer Product Name"
|
||||
msgstr "Valmistajan tuotenimi"
|
||||
|
||||
#. module: product_manufacturer
|
||||
#: view:product.product:0
|
||||
#: field:product.product,manufacturer:0
|
||||
msgid "Manufacturer"
|
||||
msgstr "Valmistaja"
|
||||
|
||||
#~ msgid "A module that add manufacturers and attributes on the product form"
|
||||
#~ msgstr "Moduuli jo lisää valmistajia ja attribuutteja tuotelomakkeelle"
|
||||
|
||||
#~ msgid "Error: Invalid ean code"
|
||||
#~ msgstr "Virhe: Väärä EAN-koodi"
|
||||
|
||||
#~ msgid "Products Attributes & Manufacturers"
|
||||
#~ msgstr "Tuotteen attribuutit ja valmistajat"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue