The following modules are merged::

addons-extra/product_procurement -> mrp module
addons-extra/inventory_merge -> stock
addons-extra/product_pricelist_print -> product
addons-extra/invoice_payment -> account

bzr revid: sahibsofia@gmail.com-20080916114513-7an9yz59hucjmjk8
This commit is contained in:
Sofia 2008-09-16 17:15:13 +05:30
parent 05f980e2a6
commit a268fad012
40 changed files with 2116 additions and 10 deletions

17
addons/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>addons</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>

View File

@ -209,8 +209,17 @@
<field colspan="4" name="comment" nolabel="1"/>
</page>
<page string="Payments">
<field name="move_lines" colspan="4"/>
</page>
<field name="payment_ids" colspan="4" nolabel="1">
<tree string="Payments">
<field name="date"/>
<field name="ref"/>
<field name="name"/>
<field name="journal_id"/>
<field name="debit"/>
<field name="credit"/>
</tree>
</field>
</page>
</notebook>
</form>
</field>
@ -283,8 +292,17 @@
<field colspan="4" name="comment" nolabel="1"/>
</page>
<page string="Payments">
<field name="move_lines" colspan="4" nolabel="1"/>
</page>
<field name="payment_ids" colspan="4" nolabel="1">
<tree string="Payments">
<field name="date"/>
<field name="ref"/>
<field name="name"/>
<field name="journal_id"/>
<field name="debit"/>
<field name="credit"/>
</tree>
</field>
</page>
</notebook>
</form>
</field>

View File

@ -126,6 +126,26 @@ class account_invoice(osv.osv):
l = map(lambda x: x.id, ids_line)
res[id]=[x for x in l if x <> line.id]
return res
def _compute_lines(self, cr, uid, ids, name, args, context={}):
result = {}
print 'ICI 0'
for invoice in self.browse(cr, uid, ids, context):
moves = self.move_line_id_payment_get(cr, uid, [invoice.id])
src = []
print 'ICI 1'
lines = []
for m in self.pool.get('account.move.line').browse(cr, uid, moves, context):
print 'ICI 2'
if m.reconcile_id:
lines += map(lambda x: x.id, m.reconcile_id.line_id)
elif m.reconcile_partial_id:
lines += map(lambda x: x.id, m.reconcile_partial_id.line_partial_ids)
src.append(m.id)
print 'ICI 3'
lines = filter(lambda x: x not in src, lines)
result[invoice.id] = lines
return result
_name = "account.invoice"
_description = 'Invoice'
@ -182,7 +202,7 @@ class account_invoice(osv.osv):
help='The bank account to pay to or to be paid from'),
'move_lines':fields.function(_get_lines , method=True,type='many2many' , relation='account.move.line',string='Move Lines'),
'residual': fields.function(_amount_residual, method=True, digits=(16,2),string='Residual', store=True),
'payment_ids': fields.function(_compute_lines, method=True, relation='account.move.line', type="many2many", string='Payments'),
}
_defaults = {
'type': _get_type,

View File

@ -0,0 +1,4 @@
# -*- encoding: utf-8 -*-
import analytic_journal_billing_rate
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
{
"name" : "Analytic Journal Billing Rate",
"version" : "1.0",
"depends" : ["analytic_user_function", "account", "hr_timesheet_invoice"],
"author" : "Tiny",
"description": """
This module allows you to define what is the defaut invoicing rate for a specific journal on a given account. This is mostly used when a user encode his timesheet: the values are retrieved and the fields are auto-filled... but the possibility to change these values is still available.
Obviously if no data has been recorded for the current account, the default value is given as usual by the account data so that this module is perfectly compatible with older configurations.
""",
"website" : "http://tinyerp.com/",
"category" : "Generic Modules/Others",
"init_xml" : [],
"demo_xml" : [],
"update_xml" : [
"analytic_journal_billing_rate_view.xml",
],
"active": False,
"installable": True
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,103 @@
# -*- encoding: utf-8 -*-
from osv import fields,osv
from osv import orm
class analytic_journal_rate_grid(osv.osv):
_name="analytic_journal_rate_grid"
_description= "Relation table between journals and billing rates"
_columns={
'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal',required=True,),
'account_id': fields.many2one("account.analytic.account", "Analytic Account",required=True,),
'rate_id': fields.many2one("hr_timesheet_invoice.factor", "Invoicing Rate",),
}
analytic_journal_rate_grid()
class account_analytic_account(osv.osv):
_inherit = "account.analytic.account"
_columns = {
'journal_rate_ids' : fields.one2many('analytic_journal_rate_grid', 'account_id', 'Invoicing Rate per Journal'),
}
account_analytic_account()
class hr_analytic_timesheet(osv.osv):
_inherit = "hr.analytic.timesheet"
def on_change_account_id(self, cr, uid, ids,user_id, account_id, journal_id,unit_amount=0):
res = {}
if not (account_id):
#avoid a useless call to super
return res
if not (journal_id):
return super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,user_id, account_id, unit_amount)
#get the browse record related to journal_id and account_id
temp = self.pool.get('analytic_journal_rate_grid').search(cr, uid, [('journal_id', '=', journal_id),('account_id', '=', account_id) ])
if not temp:
#if there isn't any record for this journal_id and account_id
return super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,user_id, account_id, unit_amount)
else:
#get the old values from super and add the value from the new relation analytic_journal_rate_grid
r = self.pool.get('analytic_journal_rate_grid').browse(cr, uid, temp)[0]
res.setdefault('value',{})
res['value']= super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,user_id, account_id,unit_amount)['value']
if r.rate_id.id:
res['value']['to_invoice'] = r.rate_id.id
return res
def on_change_journal_id(self, cr, uid, ids,journal_id, account_id):
res = {}
if not (journal_id and account_id):
return res
#get the browse record related to journal_id and account_id
temp = self.pool.get('analytic_journal_rate_grid').search(cr, uid, [('journal_id', '=', journal_id),('account_id', '=', account_id) ])
if temp:
#add the value from the new relation analytic_user_funct_grid
r = self.pool.get('analytic_journal_rate_grid').browse(cr, uid, temp)[0]
res.setdefault('value',{})
if r.rate_id.id:
res['value']['to_invoice'] = r.rate_id.id
return res
to_invoice = self.pool.get('account.analytic.account').read(cr, uid, [account_id], ['to_invoice'])[0]['to_invoice']
if to_invoice:
res.setdefault('value',{})
res['value']['to_invoice'] = to_invoice[0]
return res
hr_analytic_timesheet()
class account_invoice(osv.osv):
_inherit = "account.invoice"
def _get_analityc_lines(self, cr, uid, id):
iml = super(account_invoice, self)._get_analityc_lines(cr, uid, id)
inv = self.browse(cr, uid, [id])[0]
for il in iml:
if il['account_analytic_id']:
#get the browse record related to journal_id and account_id
journal_id = il['analytic_lines'][0][2]['journal_id']
account_id = il['analytic_lines'][0][2]['account_id']
if journal_id and account_id:
temp = self.pool.get('analytic_journal_rate_grid').search(cr, uid, [('journal_id', '=', journal_id),('account_id', '=', account_id) ])
if temp:
r = self.pool.get('analytic_journal_rate_grid').browse(cr, uid, temp)[0]
il['analytic_lines'][0][2]['to_invoice'] = r.rate_id.id
return iml
account_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,83 @@
<?xml version="1.0" ?>
<openerp>
<data>
<!-- analytic_journal_rate_grid views -->
<record model="ir.ui.view" id="analytic_journal_rate_grid_tree">
<field name="name">analytic_journal_rate_grid.tree</field>
<field name="model">analytic_journal_rate_grid</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Billing Rate per Journal for this Analytic Account" editable="bottom">
<field name="journal_id" required="1"/>
<field name="rate_id" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="analytic_journal_rate_grid_form">
<field name="name">analytic_journal_rate_grid.form</field>
<field name="model">analytic_journal_rate_grid</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Billing Rate per Journal for this Analytic Account" editable="bottom">
<field name="journal_id" required="1"/>
<field name="rate_id" />
</form>
</field>
</record>
<!-- account.analytic.account inherited view -->
<record model="ir.ui.view" id="view_account_analytic_account_form_inherit">
<field name="name">account.analytic.account.form</field>
<field name="model">account.analytic.account</field>
<field name="type">form</field>
<field name="inherit_id" ref="account.view_account_analytic_account_form"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='to_invoice']" position="after">
<!--<field name="to_invoice" string="Default Invoicing Percentage"/>-->
<field name="journal_rate_ids" colspan="4"/>
</xpath>
</field>
</record>
<!-- hr_timesheet_sheet.sheet inherited view -->
<record model="ir.ui.view" id="hr_timesheet_sheet_form_inherit">
<field name="name">hr.timesheet.sheet.form</field>
<field name="model">hr_timesheet_sheet.sheet</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr_timesheet_sheet.hr_timesheet_sheet_form"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='timesheet_ids']/tree/field[@name='account_id']" position="replace">
<field name="account_id" domain="[('type','=','normal'),('state', '&lt;&gt;', 'close')]" on_change="on_change_account_id(user_id, account_id, journal_id, unit_amount)"/>
</xpath>
</field>
</record>
<!-- hr.analytic.timesheet inherited views -->
<record model="ir.ui.view" id="hr_timesheet_line_form_inherit">
<field name="name">hr.analytic.timesheet.form</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form"/>
<field name="arch" type="xml">
<xpath expr="/form/field[@name='account_id']" position="replace">
<field name="account_id" domain="[('type','=','normal'),('state', '&lt;&gt;', 'close')]" on_change="on_change_account_id(user_id, account_id, journal_id, unit_amount)" select="1"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="hr_timesheet_line_form_inherit_2">
<field name="name">hr.analytic.timesheet.form</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form"/>
<field name="arch" type="xml">
<xpath expr="/form/field[@name='journal_id']" position="replace">
<field name="journal_id" select="1" required="1" on_change="on_change_journal_id(journal_id, account_id)"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,5 @@
# -*- encoding: utf-8 -*-
import analytic_user_function
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
{
"name" : "Analytic User Function",
"version" : "1.0",
"depends" : ["hr_timesheet_sheet"],
"author" : "Tiny",
"description": """
This module allows you to define what is the defaut function of a specific user on a given account. This is mostly used when a user encode his timesheet: the values are retrieved and the fields are auto-filled... but the possibility to change these values is still available.
Obviously if no data has been recorded for the current account, the default value is given as usual by the employee data so that this module is perfectly compatible with older configurations.
""",
"website" : "http://tinyerp.com/",
"category" : "Generic Modules/Others",
"init_xml" : [],
"demo_xml" : [],
"update_xml" : [
"analytic_user_function_view.xml",
],
"active": False,
"installable": True
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,123 @@
# -*- encoding: utf-8 -*-
from osv import fields,osv
from osv import orm
class analytic_user_funct_grid(osv.osv):
_name="analytic_user_funct_grid"
_description= "Relation table between users and products on a analytic account"
_columns={
'user_id': fields.many2one("res.users","User",required=True,),
'product_id': fields.many2one("product.product","Product",required=True,),
'account_id': fields.many2one("account.analytic.account", "Analytic Account",required=True,),
}
analytic_user_funct_grid()
class account_analytic_account(osv.osv):
_inherit = "account.analytic.account"
_columns = {
'user_product_ids' : fields.one2many('analytic_user_funct_grid', 'account_id', 'Users/Products Rel.'),
}
account_analytic_account()
class hr_analytic_timesheet(osv.osv):
_inherit = "hr.analytic.timesheet"
# Look in account, if no value for the user => look in parent until there is no more parent to look
# Take the first found... if nothing found => return False
def _get_related_user_account_recursiv(self,cr,uid,user_id,account_id):
temp=self.pool.get('analytic_user_funct_grid').search(cr, uid, [('user_id', '=', user_id),('account_id', '=', account_id) ])
account=self.pool.get('account.analytic.account').browse(cr,uid,account_id)
if temp:
return temp
else:
if account.parent_id:
return self._get_related_user_account_recursiv(cr,uid,user_id,account.parent_id.id)
else:
return False
def on_change_account_id(self, cr, uid, ids,user_id, account_id, unit_amount=0):
#{'value': {'to_invoice': False, 'amount': (-162.0,), 'product_id': 7, 'general_account_id': (5,)}}
res = {}
if not (account_id):
#avoid a useless call to super
return res
if not (user_id):
return super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,account_id)
#get the browse record related to user_id and account_id
temp = self._get_related_user_account_recursiv(cr,uid,user_id,account_id)
# temp = self.pool.get('analytic_user_funct_grid').search(cr, uid, [('user_id', '=', user_id),('account_id', '=', account_id) ])
if not temp:
#if there isn't any record for this user_id and account_id
return super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,account_id)
else:
#get the old values from super and add the value from the new relation analytic_user_funct_grid
r = self.pool.get('analytic_user_funct_grid').browse(cr, uid, temp)[0]
res.setdefault('value',{})
res['value']= super(hr_analytic_timesheet, self).on_change_account_id(cr, uid, ids,account_id)['value']
res['value']['product_id'] = r.product_id.id
res['value']['product_uom_id'] = r.product_id.product_tmpl_id.uom_id.id
#the change of product has to impact the amount, uom and general_account_id
a = r.product_id.product_tmpl_id.property_account_expense.id
if not a:
a = r.product_id.categ_id.property_account_expense_categ.id
if not a:
raise osv.except_osv('Error !',
'There is no expense account define ' \
'for this product: "%s" (id:%d)' % \
(r.product_id.name, r.product_id.id,))
amount = unit_amount * r.product_id.uom_id._compute_price(cr, uid,
r.product_id.uom_id.id, r.product_id.standard_price, False)
res ['value']['amount']= - round(amount, 2)
res ['value']['general_account_id']= a
return res
def on_change_user_id(self, cr, uid, ids,user_id, account_id, unit_amount=0):
res = {}
if not (user_id):
#avoid a useless call to super
return res
#get the old values from super
res = super(hr_analytic_timesheet, self).on_change_user_id(cr, uid, ids,user_id)
if account_id:
#get the browse record related to user_id and account_id
# temp = self.pool.get('analytic_user_funct_grid').search(cr, uid, [('user_id', '=', user_id),('account_id', '=', account_id) ])
temp = self._get_related_user_account_recursiv(cr,uid,user_id,account_id)
if temp:
#add the value from the new relation analytic_user_funct_grid
r = self.pool.get('analytic_user_funct_grid').browse(cr, uid, temp)[0]
res['value']['product_id'] = r.product_id.id
#the change of product has to impact the amount, uom and general_account_id
a = r.product_id.product_tmpl_id.property_account_expense.id
if not a:
a = r.product_id.categ_id.property_account_expense_categ.id
if not a:
raise osv.except_osv('Error !',
'There is no expense account define ' \
'for this product: "%s" (id:%d)' % \
(r.product_id.name, r.product_id.id,))
amount = unit_amount * r.product_id.uom_id._compute_price(cr, uid,
r.product_id.uom_id.id, r.product_id.standard_price, False)
res ['value']['amount']= - round(amount, 2)
res ['value']['general_account_id']= a
return res
hr_analytic_timesheet()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,109 @@
<?xml version="1.0" ?>
<openerp>
<data>
<!-- analytic_user_funct_grid views -->
<record model="ir.ui.view" id="analytic_user_funct_grid_tree">
<field name="name">analytic_user_funct_grid.tree</field>
<field name="model">analytic_user_funct_grid</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="User's Product for this Analytic Account" editable="bottom">
<field name="user_id" required="1"/>
<field name="product_id" required="1" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="analytic_user_funct_grid_form">
<field name="name">analytic_user_funct_grid.form</field>
<field name="model">analytic_user_funct_grid</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="User's Product for this Analytic Account">
<field name="user_id" required="1"/>
<field name="product_id" required="1"/>
</form>
</field>
</record>
<!-- account.analytic.account inherited view -->
<record model="ir.ui.view" id="view_account_analytic_account_form_inherit">
<field name="name">account.analytic.account.form</field>
<field name="model">account.analytic.account</field>
<field name="type">form</field>
<field name="inherit_id" ref="account.view_account_analytic_account_form"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page" position="after">
<page string="Users/Products Rel.">
<field name="user_product_ids" colspan="4" nolabel="1"/>
</page>
</xpath>
</field>
</record>
<!-- hr_timesheet_sheet.sheet inherited view -->
<record model="ir.ui.view" id="hr_timesheet_sheet_form_inherit">
<field name="name">hr.timesheet.sheet.form</field>
<field name="model">hr_timesheet_sheet.sheet</field>
<field name="type">form</field>
<field name="priority" eval="18"/>
<field name="inherit_id" ref="hr_timesheet_sheet.hr_timesheet_sheet_form"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='timesheet_ids']/tree/field[@name='account_id']" position="replace">
<field name="account_id" domain="[('type','=','normal'),('state', '&lt;&gt;', 'close')]" on_change="on_change_account_id(user_id, account_id, unit_amount)"/>
</xpath>
</field>
</record>
<!-- hr.analytic.timesheet inherited views -->
<record model="ir.ui.view" id="hr_timesheet_line_form_inherit">
<field name="name">hr.analytic.timesheet.form</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form"/>
<field name="arch" type="xml">
<xpath expr="/form/field[@name='account_id']" position="replace">
<field name="account_id" domain="[('type','=','normal'),('state', '&lt;&gt;', 'close')]" on_change="on_change_account_id(user_id, account_id, unit_amount)" select="1"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="hr_timesheet_line_form_inherit_2">
<field name="name">hr.analytic.timesheet.form</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form"/>
<field name="arch" type="xml">
<xpath expr="/form/field[@name='user_id']" position="replace">
<field name="user_id" select="1" required="1" on_change="on_change_user_id(user_id, account_id, unit_amount)"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="hr_timesheet_line_tree_inherit">
<field name="name">hr.analytic.timesheet.tree</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">tree</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree"/>
<field name="arch" type="xml">
<xpath expr="/tree/field[@name='account_id']" position="replace">
<field name="account_id" domain="[('type','=','normal'),('state', '&lt;&gt;', 'close')]" on_change="on_change_account_id(user_id, account_id, unit_amount)" select="1"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="hr_timesheet_line_tree_inherit_2">
<field name="name">hr.analytic.timesheet.tree</field>
<field name="model">hr.analytic.timesheet</field>
<field name="type">tree</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree"/>
<field name="arch" type="xml">
<xpath expr="/tree/field[@name='user_id']" position="replace">
<field name="user_id" select="1" required="1" on_change="on_change_user_id(user_id, account_id, unit_amount)"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,5 @@
# -*- encoding: utf-8 -*-
import audittrail
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,20 @@
# -*- encoding: utf-8 -*-
#
# you must set the depends variable on modules you plan to audit !
#
{
"name" : "Audit Trail",
"version" : "1.0",
"depends" : ["base","account","purchase","mrp"],
"website" : "http://tinyerp.com",
"author" : "Tiny",
"init_xml" : [],
"description": "Allows the administrator to track every user operations on all objects of the system.",
"category" : "Generic Modules/Others",
"update_xml" : ["audittrail_view.xml"],
"demo_xml" : ["audittrail_demo.xml"],
"active" : False,
"installable": True
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,281 @@
# -*- encoding: utf-8 -*-
from osv import osv, fields
import time, pooler, copy
import ir
class audittrail_rule(osv.osv):
_name = 'audittrail.rule'
_columns = {
"name": fields.char("Rule Name", size=32, required=True),
"object_id": fields.many2one('ir.model', 'Object', required=True),
"user_id": fields.many2many('res.users', 'audittail_rules_users', 'user_id', 'rule_id', 'Users'),
"log_read": fields.boolean("Log reads"),
"log_write": fields.boolean("Log writes"),
"log_unlink": fields.boolean("Log deletes"),
"log_create": fields.boolean("Log creates"),
"state": fields.selection((("draft", "Draft"),("subscribed", "Subscribed")), "State", required=True),
"action_id":fields.many2one('ir.actions.act_window',"Action ID"),
}
_defaults = {
'state': lambda *a: 'draft',
'log_create': lambda *a: 1,
'log_unlink': lambda *a: 1,
'log_write': lambda *a: 1,
}
_sql_constraints = [
('model_uniq', 'unique (object_id)', """There is a rule defined on this object\n You can not define other on the same!""")
]
__functions = {}
def __init__(self,pool,cr=None):
for obj_name in pool.obj_list():
obj=pool.get(obj_name)
for field in ('read','write','create','unlink'):
setattr(obj, field, self.logging_fct(getattr(obj,field), obj))
super(audittrail_rule, self).__init__(pool,cr)
def subscribe(self, cr, uid, ids, *args):
for thisrule in self.browse(cr, uid, ids):
obj = self.pool.get(thisrule.object_id.model)
if not obj:
raise osv.except_osv(
'WARNING:audittrail is not part of the pool',
'Change audittrail depends -- Setting rule as DRAFT')
self.write(cr, uid, [thisrule.id], {"state": "draft"})
val={
"name":'View Log',
"res_model":'audittrail.log',
"src_model":thisrule.object_id.model,
"domain":"[('res_id', '=', active_id)]"
}
id=self.pool.get('ir.actions.act_window').create(cr, uid, val)
self.write(cr, uid, ids, {"state": "subscribed","action_id":id})
keyword = 'client_action_relate'
value = 'ir.actions.act_window,'+str(id)
res=self.pool.get('ir.model.data').ir_set(cr, uid, 'action', keyword,'View_log_'+thisrule.object_id.model, [thisrule.object_id.model], value, replace=True, isobject=True, xml_id=False)
return True
def logging_fct(self, fct_src, obj):
object_name=obj._name
object=None
logged_uids = []
def get_value_text(cr, uid, field_name,values,object, context={}):
f_id= self.pool.get('ir.model.fields').search(cr, uid,[('name','=',field_name),('model_id','=',object.id)])
if f_id:
field=self.pool.get('ir.model.fields').read(cr, uid,f_id)[0]
model=field['relation']
if field['ttype']=='many2one':
if values:
if type(values)==tuple:
values=values[0]
val=self.pool.get(model).read(cr,uid,[values],['name'])
if len(val):
return val[0]['name']
elif field['ttype'] == 'many2many':
value=[]
if values:
for id in values:
val=self.pool.get(model).read(cr,uid,[id],['name'])
if len(val):
value.append(val[0]['name'])
return value
elif field['ttype'] == 'one2many':
if values:
value=[]
for id in values:
val=self.pool.get(model).read(cr,uid,[id],['name'])
if len(val):
value.append(val[0]['name'])
return value
return values
def create_log_line(cr,uid,id,object,lines=[]):
for line in lines:
f_id= self.pool.get('ir.model.fields').search(cr, uid,[('name','=',line['name']),('model_id','=',object.id)])
if len(f_id):
fields=self.pool.get('ir.model.fields').read(cr, uid,f_id)
old_value='old_value' in line and line['old_value'] or ''
new_value='new_value' in line and line['new_value'] or ''
old_value_text='old_value_text' in line and line['old_value_text'] or ''
new_value_text='new_value_text' in line and line['new_value_text'] or ''
if fields[0]['ttype']== 'many2one':
if type(old_value)==tuple:
old_value=old_value[0]
if type(new_value)==tuple:
new_value=new_value[0]
self.pool.get('audittrail.log.line').create(cr, uid, {"log_id": id, "field_id": f_id[0] ,"old_value":old_value ,"new_value":new_value,"old_value_text":old_value_text ,"new_value_text":new_value_text,"field_description":fields[0]['field_description']})
return True
def my_fct( cr, uid, *args, **args2):
obj_ids= self.pool.get('ir.model').search(cr, uid,[('model','=',object_name)])
if not len(obj_ids):
return fct_src(cr, uid, *args, **args2)
object=self.pool.get('ir.model').browse(cr,uid,obj_ids)[0]
rule_ids=self.search(cr, uid, [('object_id','=',obj_ids[0]),('state','=','subscribed')])
if not len(rule_ids):
return fct_src(cr, uid, *args, **args2)
field=fct_src.__name__
for thisrule in self.browse(cr, uid, rule_ids):
if not getattr(thisrule, 'log_'+field):
return fct_src(cr, uid, *args, **args2)
self.__functions.setdefault(thisrule.id, [])
self.__functions[thisrule.id].append( (obj,field, getattr(obj,field)) )
for user in thisrule.user_id:
logged_uids.append(user.id)
if fct_src.__name__ in ('create'):
res_id =fct_src( cr, uid, *args, **args2)
new_value=self.pool.get(object.model).read(cr,uid,[res_id],args[0].keys())[0]
if 'id' in new_value:
del new_value['id']
if not len(logged_uids) or uid in logged_uids:
id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
lines=[]
for field in new_value:
if new_value[field]:
line={
'name':field,
'new_value':new_value[field],
'new_value_text':get_value_text(cr,uid,field,new_value[field],object)
}
lines.append(line)
create_log_line(cr,uid,id,object,lines)
return res_id
if fct_src.__name__ in ('write'):
res_ids=args[0]
for res_id in res_ids:
old_values=self.pool.get(object.model).read(cr,uid,res_id,args[1].keys())
old_values_text={}
for field in args[1].keys():
old_values_text[field]=get_value_text(cr,uid,field,old_values[field],object)
res =fct_src( cr, uid, *args, **args2)
if res:
new_values=self.pool.get(object.model).read(cr,uid,res_ids,args[1].keys())[0]
if not len(logged_uids) or uid in logged_uids:
id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
lines=[]
for field in args[1].keys():
if args[1].keys():
line={
'name':field,
'new_value':field in new_values and new_values[field] or '',
'old_value':field in old_values and old_values[field] or '',
'new_value_text':get_value_text(cr,uid,field,new_values[field],object),
'old_value_text':old_values_text[field]
}
lines.append(line)
create_log_line(cr,uid,id,object,lines)
return res
if fct_src.__name__ in ('read'):
res_ids=args[0]
old_values={}
res =fct_src( cr, uid,*args, **args2)
if type(res)==list:
for v in res:
old_values[v['id']]=v
else:
old_values[res['id']]=res
for res_id in old_values:
if not len(logged_uids) or uid in logged_uids:
id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
lines=[]
for field in old_values[res_id]:
if old_values[res_id][field]:
line={
'name':field,
'old_value':old_values[res_id][field],
'old_value_text':get_value_text(cr,uid,field,old_values[res_id][field],object)
}
lines.append(line)
create_log_line(cr,uid,id,object,lines)
return res
if fct_src.__name__ in ('unlink'):
res_ids=args[0]
old_values={}
for res_id in res_ids:
old_values[res_id]=self.pool.get(object.model).read(cr,uid,res_id,[])
for res_id in res_ids:
if not len(logged_uids) or uid in logged_uids:
id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
lines=[]
for field in old_values[res_id]:
if old_values[res_id][field]:
line={
'name':field,
'old_value':old_values[res_id][field],
'old_value_text':get_value_text(cr,uid,field,old_values[res_id][field],object)
}
lines.append(line)
create_log_line(cr,uid,id,object,lines)
res =fct_src( cr, uid,*args, **args2)
return res
return my_fct
def unsubscribe(self, cr, uid, ids, *args):
for thisrule in self.browse(cr, uid, ids):
if thisrule.id in self.__functions :
for function in self.__functions[thisrule.id]:
setattr(function[0], function[1], function[2])
w_id=self.pool.get('ir.actions.act_window').search(cr, uid, [('name','=','View Log'),('res_model','=','audittrail.log'),('src_model','=',thisrule.object_id.model)])
self.pool.get('ir.actions.act_window').unlink(cr, uid,w_id )
val_obj=self.pool.get('ir.values')
value="ir.actions.act_window"+','+str(w_id[0])
val_id=val_obj.search(cr, uid, [('model','=',thisrule.object_id.model),('value','=',value)])
if val_id:
res = ir.ir_del(cr, uid, val_id[0])
self.write(cr, uid, ids, {"state": "draft"})
return True
audittrail_rule()
class audittrail_log(osv.osv):
_name = 'audittrail.log'
_columns = {
"name": fields.char("Name", size=32),
"object_id": fields.many2one('ir.model', 'Object'),
"user_id": fields.many2one('res.users', 'User'),
"method": fields.selection((('read', 'Read'), ('write', 'Write'), ('unlink', 'Delete'), ('create', 'Create')), "Method"),
"timestamp": fields.datetime("Date"),
"res_id":fields.integer('Resource Id'),
"line_ids":fields.one2many('audittrail.log.line','log_id','Log lines')
}
_defaults = {
"timestamp": lambda *a: time.strftime("%Y-%m-%d %H:%M:%S")
}
audittrail_log()
class audittrail_log_line(osv.osv):
_name='audittrail.log.line'
_columns={
'field_id': fields.many2one('ir.model.fields','Fields', required=True),
'log_id':fields.many2one('audittrail.log','Log'),
'log':fields.integer("Log ID"),
'old_value':fields.text("Old Value"),
'new_value':fields.text("New Value"),
'old_value_text':fields.text('Old value Text' ),
'new_value_text':fields.text('New value Text' ),
'field_description':fields.char('Field Description' ,size=64),
}
audittrail_log_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,10 @@
<?xml version="1.0" ?>
<openerp>
<data noupdate="1">
<record model="audittrail.rule" id="demo_audittrail_rule">
<field name="name">Audit on Partners</field>
<field name="object_id" search="[('model','=','res.partner')]"/>
<field name="user_id" search="[]"/>
</record>
</data>
</openerp>

View File

@ -0,0 +1,126 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record model="ir.ui.view" id="view_audittrail_rule_form">
<field name="name">audittrail.rule.form</field>
<field name="model">audittrail.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="AuditTrail Rule">
<field name="name" select="1" required="1"/>
<field name="object_id" select="1"/>
<field name="log_read" />
<field name="log_write" />
<field name="log_unlink" />
<field name="log_create" />
<field name="action_id" colspan="4" readonly="1"/>
<field name="user_id" select="1" colspan="4"/>
<field name="state" select="1" readonly="1" />
<group colspan="2" col="2">
<button string="Subscribe" name="subscribe" type="object" states="draft"/>
<button string="UnSubscribe" name="unsubscribe" type="object" states="subscribed"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_audittrail_rule_tree">
<field name="name">audittrail.rule.tree</field>
<field name="model">audittrail.rule</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="AuditTrail Rules">
<field name="name" />
<field name="object_id"/>
<field name="user_id" />
<field name="log_read" />
<field name="log_write" />
<field name="log_unlink" />
<field name="log_create" />
<field name="state" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_audittrail_rule_tree">
<field name="res_model">audittrail.rule</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<!--<field name="view_id" ref="view_audittrail_rule_form" />-->
</record>
<menuitem name="Audittrails" id="menu_action_audittrail" parent="base.menu_administration"/>
<menuitem name="Rules" id="menu_action_audittrail_rule_tree" action="action_audittrail_rule_tree" parent="menu_action_audittrail"/>
<record model="ir.actions.act_window" id="action_audittrail_rule_tree_sub">
<field name="res_model">audittrail.rule</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','subscribed')]</field>
</record>
<menuitem name="Subscribed Rules" id="menu_action_audittrail_rule_tree_sub" action="action_audittrail_rule_tree_sub" parent="menu_action_audittrail_rule_tree"/>
<record model="ir.ui.view" id="view_audittrail_log_form">
<field name="name">audittrail.log.form</field>
<field name="model">audittrail.log</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="AuditTrail Logs">
<field name="timestamp" select="1" required="1" readonly="1"/>
<field name="object_id" select="1" readonly="1"/>
<field name="method" select="1" readonly="1"/>
<field name="user_id" select="1" readonly="1"/>
<field name="res_id" readonly="1" colspan="4"/>
<field name="line_ids" colspan="4" mode="tree,form" widget="one2many_list" readonly="1">
<form string="Log Lines">
<field name="field_id" colspan="4" readonly="1"/>
<newline/>
<field name="field_description" colspan="4" readonly="1"/>
<newline/>
<separator string="Old Value : " colspan="2" readonly="1"/>
<separator string="New Value : " colspan="2" readonly="1"/>
<newline/>
<field name="old_value" nolabel="1" colspan="2" readonly="1"/>
<field name="new_value" nolabel="1" colspan="2" readonly="1"/>
<newline/>
<separator string="Old Value Text : " colspan="2" readonly="1"/>
<separator string="New Value Text: " colspan="2" readonly="1"/>
<newline/>
<field name="old_value_text" nolabel="1" colspan="2" readonly="1"/>
<field name="new_value_text" nolabel="1" colspan="2" readonly="1"/>
</form>
<tree string="Log Lines">
<field name="field_description" />
<field name="old_value_text" />
<field name="new_value_text" />
</tree>
</field>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_audittrail_log_tree">
<field name="name">audittrail.log.tree</field>
<field name="model">audittrail.log</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="AuditTrail Logs">
<field name="timestamp" />
<field name="object_id" />
<field name="method" />
<field name="user_id" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_audittrail_log_tree">
<field name="res_model">audittrail.log</field>
<field name="view_type">form</field>
</record>
<menuitem name="Logs" id="menu_action_audittrail_log_tree" action="action_audittrail_log_tree" parent="menu_action_audittrail"/>
<wizard string="View log" menu="False" model="audittrail.log" name="audittrail.view.log" id="wizard_audittrail_log"/>
<menuitem name="View Logs" id="menu_action_log_tree2" action="wizard_audittrail_log" type="wizard" parent="menu_action_audittrail"/>
</data>
</openerp>

View File

@ -0,0 +1,4 @@
# -*- encoding: utf-8 -*-
import wizard_view_log
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,61 @@
# -*- encoding: utf-8 -*-
import wizard
import pooler
import time
class wizard_view_log(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="Audit Logs">
<field name="from" colspan="4"/>
<newline/>
<field name="to" colspan="4"/>
</form>'''
form1_fields = {
'from': {
'string': 'Log From',
'type': 'datetime',
},
'to': {
'string': 'Log To',
'type': 'datetime',
'default': lambda *a: time.strftime("%Y-%m-%d %H:%M:%S"),
'required':True
},
}
def _log_open_window(self, cr, uid, data, context):
mod_obj = pooler.get_pool(cr.dbname).get('ir.model.data')
act_obj = pooler.get_pool(cr.dbname).get('ir.actions.act_window')
result = mod_obj._get_id(cr, uid, 'audittrail', 'action_audittrail_log_tree')
id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
result = act_obj.read(cr, uid, [id])[0]
log_obj= pooler.get_pool(cr.dbname).get(result['res_model'])
log_id = log_obj.search(cr, uid, [])
log_model=log_obj.read(cr, uid,log_id,['object_id'])
if not data['form']['from']:
if data['form']['to'] <> time.strftime("%Y-%m-%d %H:%M:%S"):
result['domain'] = str([('timestamp', '<',data['form']['to'])])
else:
pass
else:
result['domain'] = str([('timestamp', '>',data['form']['from']),('timestamp', '<',data['form']['to'])])
return result
states = {
'init': {
'actions': [],
'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, 'state': [('end', 'Cancel'), ('open', 'Open Logs')]}
},
'open': {
'actions': [],
'result': {'type': 'action', 'action':_log_open_window, 'state':'end'}
}
}
wizard_view_log('audittrail.view.log')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -69,7 +69,7 @@
"mrp_view.xml",
"mrp_wizard.xml",
"mrp_report.xml",
"company_view.xml"
"company_view.xml",
],
"active": False,
"installable": True

View File

@ -29,6 +29,13 @@
<field eval="'ir.actions.wizard,%d'%wizard_price" name="value"/>
<field eval="True" name="object"/>
</record>
<wizard
string="Create Procurement"
model="product.product"
name="product.product.procurement"
keyword="client_action_multi"
id="product_procurement_wizard"/>
</data>
</openerp>

View File

@ -34,6 +34,7 @@ import wizard_schedulers_all
import wizard_price
import wizard_workcenter_load
import wizard_track_prod
import make_procurement
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,108 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2007 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import wizard
import pooler
import netsvc
import time
def _get_default(obj, cr, uid, data, context=None):
pool = pooler.get_pool(cr.dbname)
product = pool.get('product.product').browse(cr, uid, data['id'], context)
return {'product_id': product.id, 'uom_id':product.uom_id.id, 'qty':1.0}
def make_procurement(obj, cr, uid, data, context=None):
'''Create procurement'''
pool = pooler.get_pool(cr.dbname)
wh = pool.get('stock.warehouse').browse(cr, uid, data['form']['warehouse_id'], context)
user = pool.get('res.users').browse(cr, uid, uid, context)
procure_id = pool.get('mrp.procurement').create(cr, uid, {
'name':'INT:'+str(user.login),
'date_planned':data['form']['date_planned'],
'product_id':data['form']['product_id'],
'product_qty':data['form']['qty'],
'product_uom':data['form']['uom_id'],
'location_id':wh.lot_stock_id.id,
'procure_method':'make_to_order',
}, context=context)
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'mrp.procurement', procure_id, 'button_confirm', cr)
return {}
class MakeProcurement(wizard.interface):
'''Wizard that create a procurement from a product form'''
done_form = """<?xml version="1.0"?>
<form string="Make Procurement">
<label string="Your procurement request has been sent !"/>
</form>"""
procurement_form = """<?xml version="1.0"?>
<form string="Make Procurement">
<field name="product_id"/>
<field name="warehouse_id"/>
<field name="qty"/>
<field name="uom_id"/>
<field name="date_planned"/>
</form>"""
procurement_fields = {
'qty': {'string': 'Quantity', 'type': 'float', 'digits':(16,2), 'required': True},
'product_id': {'string': 'product', 'type': 'many2one', 'relation': 'product.product', 'required': True, 'readonly':1},
'uom_id': {'string': 'Unit of Measure', 'type': 'many2one', 'relation': 'product.uom', 'required':True},
'warehouse_id': {'string': 'Location', 'type': 'many2one', 'relation':'stock.warehouse', 'required':True},
'date_planned': {'string': 'Planned Date', 'type': 'date', 'required':True, 'default': lambda *args: time.strftime('%Y-%m-%d')}
}
states = {
'init': {
'actions': [_get_default],
'result': {'type': 'form', 'arch': procurement_form, 'fields': procurement_fields,
'state': [
('end', 'Cancel'),
('create', 'Ask New Products')
]
}
},
'done': {
'actions': [],
'result': {'type': 'form', 'arch': done_form, 'fields': {},
'state': [
('end', 'Close'),
]
}
},
'create': {
'actions': [],
'result': {'type': 'action', 'action': make_procurement, 'state': 'done'}
}
}
MakeProcurement('product.product.procurement')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -30,6 +30,7 @@ import product
import pricelist
import report
import partner
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -57,7 +57,7 @@
"security/ir.model.access.csv",
"product_data.xml","product_report.xml",
"product_view.xml", "pricelist_view.xml",
"partner_view.xml"],
"partner_view.xml", "product_wizard.xml"],
"active": False,
"installable": True
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" ?>
<openerp>
<data>
<wizard
id="report_wizard_price"
string="Price List"
model="product.product"
name="product.price_list"
keyword="client_print_multi"/>
</data>
</openerp>

View File

@ -27,7 +27,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import product_pricelist
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,127 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import datetime
from report.interface import report_rml
from report.interface import toxml
import pooler
from osv import osv
import datetime
class report_custom(report_rml):
def create_xml(self, cr, uid, ids, data, context):
pool = pooler.get_pool(cr.dbname)
price_list_id = data['form']['price_list']
product_categ_id =pool.get('product.category').search(cr,uid,[])
currency = pool.get('product.pricelist').read(cr,uid,[price_list_id],['currency_id','name'])[0]
qty =[]
for i in range(1,6):
q = 'qty%d'%i
if data['form'][q]:
qty.append(data['form'][q])
if not qty:
qty.append(1)
product_xml = []
cols = ''
cols = cols+'6cm'
title ='<title name=" Description " number="0" />'
i=1
for q in qty:
cols = cols+',2.5cm'
if q==1:
title+='<title name="%d unit" number="%d"/>'%(q,i)
else:
title+='<title name="%d units" number="%d"/>'%(q,i)
i+=1
date = datetime.date.today()
str_date=date.strftime("%d/%m/%Y")
product_xml.append('<cols>'+cols+'</cols>')
product_xml.append('<pricelist> %s </pricelist>'%currency['name'])
product_xml.append('<currency> %s </currency>'%currency['currency_id'][1])
product_xml.append('<date> %s </date>'%str_date)
product_xml.append("<product>")
for p_categ_id in product_categ_id:
product_ids = pool.get('product.product').search(cr,uid,[('id','in',ids),('categ_id','=',p_categ_id)])
if product_ids:
categ_name = pool.get('product.category').read(cr,uid,[p_categ_id],['name'])
products = pool.get('product.product').read(cr,uid,product_ids,['id','name','code'])
pro = []
i=0
pro.append('<pro name="%s" categ="true">' % (categ_name[0]['name']))
temp = []
for q in qty:
temp.append('<price name=" " />')
pro.extend(temp)
pro.append('</pro>')
for x in products:
#Replacement of special characters with their code html for allowing reporting - Edited by Hasa
x['name'] = x['name'].replace("&","&amp;")
x['name'] = x['name'].replace("\"","&quot;")
if x['code']:
pro.append('<pro name="[%s] %s" >' % (x['code'], x['name']))
else:
pro.append('<pro name="%s" >' % (x['name']))
temp = []
for q in qty:
price_dict = pool.get('product.pricelist').price_get(cr,uid,[price_list_id],x['id'],q)
if price_dict[price_list_id]:
price = price_dict[price_list_id]
else:
res = pool.get('product.product').read(cr, uid,[x['id']])
price = res[0]['list_price']
# temp.append('<price name="%s %s" />'%(price_list[i][x['id']]*q[2]['name'],currency['currency_id'][1]))
temp.append('<price name="%.2f" />'%(price))
i+=1
pro.extend(temp)
pro.append('</pro>')
# categ.extend(pro)
# categ.append('</categ>')
product_xml.extend(pro)
product_xml.append('</product>')
xml = '''<?xml version="1.0" encoding="UTF-8" ?>
<report>
%s
</report>
''' % (title+'\n'.join(product_xml))
return self.post_process_xml_data(cr, uid, xml, context)
report_custom('report.pricelist.pricelist', 'product.product','','addons/product_pricelist_print/report/product_price.xsl')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="../../custom/corporate_defaults.xsl" />
<xsl:template match="/">
<xsl:call-template name="rml" />
</xsl:template>
<xsl:template name="rml" match="/">
<document filename="example.pdf">
<template>
<pageTemplate id="first">
<frame id="first" x1="1cm" y1="2.5cm" width="19.0cm" height="23.0cm"/>
<pageGraphics>
<xsl:apply-imports />
</pageGraphics>
</pageTemplate>
</template>
<stylesheet>
<paraStyle name="normal" fontName="Times-Roman" fontSize="12" />
<paraStyle name="title" fontName="Times-Bold" fontSize="15" alignment="center" />
<paraStyle name="table_title" fontName="Times-Bold" fontSize="12" alignment="center" />
<paraStyle name="product1" fontName="Times-Roman" fontSize="8" />
<paraStyle name="categ" fontName="Times-Bold" fontSize="10" textColor="blue"/>
<paraStyle name="price" fontName="Times-Roman" fontSize="8" alignment="right" />
<blockTableStyle id="main_title">
<blockAlignment value="CENTER" />
<lineStyle kind="GRID" colorName="black"/>
<blockBackground colorName="#e6e6e6" />
<blockValign value="TOP"/>
</blockTableStyle>
<blockTableStyle id="product">
<blockAlignment value="LEFT" />
<xsl:for-each select="/report/title">
<xsl:variable name="col" select="attribute::number" />
<blockBackground>
<xsl:attribute name="colorName">#e6e6e6</xsl:attribute>
<xsl:attribute name="start">
<xsl:value-of select="$col" />
<xsl:text>,0</xsl:text>
</xsl:attribute>
<xsl:attribute name="stop">
<xsl:value-of select="$col" />
<xsl:text>,0</xsl:text>
</xsl:attribute>
</blockBackground>
</xsl:for-each>
<lineStyle kind="LINEABOVE" colorName="black" start="0,0" stop="-1,-1" />
<lineStyle kind="LINEBEFORE" colorName="black" start="0,0" stop="-1,-1"/>
<lineStyle kind="LINEAFTER" colorName="black" start="-1,0" stop="-1,-1"/>
<lineStyle kind="LINEBELOW" colorName="black" start="0,-1" stop="-1,-1"/>
<blockValign value="TOP"/>
</blockTableStyle>
</stylesheet >
<story>
<xsl:call-template name="story"/>
</story>
</document>
</xsl:template>
<xsl:template name="story">
<spacer length="1cm" />
<blockTable rowHeights="1cm">
<xsl:attribute name="style">main_title</xsl:attribute>
<tr> <td> <para style="title" t="1">Products Price List</para> </td> </tr>
</blockTable>
<spacer length="1cm" />
<para style="normal" t="1">Price List Name :<xsl:value-of select="report/pricelist" /></para>
<para style="normal" t="1">Currency : <xsl:value-of select="report/currency" /></para>
<para style="normal" t="1">Printing Date : <xsl:value-of select="report/date" /></para>
<spacer length="0.7cm" />
<blockTable>
<xsl:attribute name="style">product</xsl:attribute>
<xsl:attribute name="colWidths"><xsl:value-of select="report/cols" /></xsl:attribute>
<tr>
<xsl:for-each select="report/title" >
<td><para style="table_title"> <xsl:value-of select="attribute::name" /> </para></td>
</xsl:for-each>
</tr>
<xsl:for-each select="report/product/pro" >
<tr>
<xsl:choose>
<xsl:when test="@categ">
<td> <para style="categ"><xsl:value-of select="attribute::name" /> </para> </td>
</xsl:when>
<xsl:otherwise>
<td> <para style="product1"> <xsl:value-of select="attribute::name" /> </para> </td>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each select="price" >
<td><para style="price"> <xsl:value-of select="attribute::name" /> </para> </td>
</xsl:for-each>
</tr>
</xsl:for-each>
</blockTable>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,156 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import time
from report import report_sxw
from osv import osv
import pooler
parents = {
'tr':1,
'li':1,
'story': 0,
'section': 0
}
class product_pricelist(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(product_pricelist, self).__init__(cr, uid, name, context)
self.pricelist=False
self.quantity=[]
self.localcontext.update({
'time': time,
'get_pricelist': self._get_pricelist,
'get_currency': self._get_currency,
'get_categories': self._get_categories,
'get_price': self._get_price,
'get_quantity':self._get_quantity,
'qty_header':self._qty_header,
})
def _qty_header(self,form):
qty=[]
self.pricelist=form['price_list']
for i in range(1,6):
q = 'qty%d'%i
if form[q]:
self.quantity.append(form[q])
if form[q]==1:
qty.append('%d unit'%(form[q]))
else:
qty.append('%d units'%(form[q]))
return qty
def _get_quantity(self,form):
qty=[]
for i in range(1,6):
q = 'qty%d'%i
if form[q]:
qty.append(form[q])
return qty
def _get_pricelist(self, pricelist_id):
pool = pooler.get_pool(self.cr.dbname)
pricelist = pool.get('product.pricelist').read(self.cr,self.uid,[pricelist_id],['name'])[0]
return pricelist['name']
def _get_currency(self, pricelist_id):
pool = pooler.get_pool(self.cr.dbname)
pricelist = pool.get('product.pricelist').read(self.cr,self.uid,[pricelist_id],['currency_id'])[0]
return pricelist['currency_id'][1]
def _get_categories(self, products):
cat_ids=[]
res=[]
pool = pooler.get_pool(self.cr.dbname)
pro_ids=[]
for product in products:
pro_ids.append(product.id)
if product.categ_id.id not in cat_ids:
cat_ids.append(product.categ_id.id)
cats=pool.get('product.category').browse(self.cr,self.uid,cat_ids)
for cat in cats:
product_ids=pool.get('product.product').search(self.cr,self.uid,[('id','in',pro_ids),('categ_id','=',cat.id)])
products = []
for product in pool.get('product.product').browse(self.cr,self.uid,product_ids):
val={
'id':product.id,
'name':product.name,
'code':product.code
}
for qty in self.quantity:
val[str(qty)]=self._get_price(self.pricelist,product.id,qty)
products.append(val)
res.append({'name':cat.name,'products':products})
return res
def _get_price(self,pricelist_id, product_id,qty):
pool = pooler.get_pool(self.cr.dbname)
price_dict = pool.get('product.pricelist').price_get(self.cr,self.uid,[pricelist_id],product_id,qty)
if price_dict[pricelist_id]:
price = self.formatLang(price_dict[pricelist_id])
else:
res = pool.get('product.product').read(self.cr, self.uid,[product_id])
price = self.formatLang(res[0]['list_price'])
return price
def repeatIn(self, lst, name, nodes_parent=False,value=[],width=False,type=False):
self._node.data = ''
node = self._find_parent(self._node, nodes_parent or parents)
ns = node.nextSibling
if not lst:
lst.append(1)
for ns in node.childNodes :
if ns and ns.nodeName!='#text' and ns.tagName=='blockTable' and len(value) :
width_str = ns._attrs['colWidths'].nodeValue
ns.removeAttribute('colWidths')
if not width or width=='':
width=30
if type.lower() in ('title'):
width=width*len(value)
width_str= '%d'%(float(width_str)+width)
ns.setAttribute('colWidths',width_str)
else:
for v in value:
width_str +=',%d'%width
ns.setAttribute('colWidths',width_str)
child_list = ns.childNodes
for child in child_list:
if child.nodeName=='tr':
lc = child.childNodes[1]
t=0
for v in value:
newnode = lc.cloneNode(1)
if type.lower() in ('string'):
newnode.childNodes[1].lastChild.data="[[ %s['%s'] ]]"%(name,v)
elif type.lower() in ('label'):
newnode.childNodes[1].lastChild.data= "%s"%(v)
child.appendChild(newnode)
newnode=False
return super(product_pricelist,self).repeatIn(lst, name, nodes_parent=False)
#end
report_sxw.report_sxw('report.product.pricelist','product.product','addons/product_pricelist_print/report/product_pricelist.rml',parser=product_pricelist)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,115 @@
<?xml version="1.0"?>
<document filename="test.pdf">
<template pageSize="(595.0,842.0)" title="Test" author="Martin Simon" allowSplitting="20">
<pageTemplate id="first">
<frame id="first" x1="57.0" y1="57.0" width="481" height="728"/>
</pageTemplate>
</template>
<stylesheet>
<blockTableStyle id="Standard_Outline">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
</blockTableStyle>
<blockTableStyle id="Table1">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<blockBackground colorName="#e6e6e6" start="0,0" stop="0,0"/>
<lineStyle kind="GRID" colorName="black"/>
</blockTableStyle>
<blockTableStyle id="Table6">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<blockBackground colorName="#e6e6e6" />
<lineStyle kind="GRID" colorName="black"/>
</blockTableStyle>
<blockTableStyle id="Table3">
<blockAlignment value="LEFT"/>
<blockValign value="TOP"/>
<lineStyle kind="GRID" colorName="black"/>
</blockTableStyle>
<initialize>
<paraStyle name="all" alignment="justify"/>
</initialize>
<paraStyle name="P1" fontName="Times-Roman" fontSize="9.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P2" fontName="Times-Roman" fontSize="9.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P3" fontName="Times-Roman" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P4" fontName="Times-Roman" alignment="CENTER"/>
<paraStyle name="P5" fontName="Times-Roman" fontSize="8.0" leading="10"/>
<paraStyle name="P6" fontName="Times-Bold" fontSize="11.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P7" fontName="Times-Roman" alignment="LEFT"/>
<paraStyle name="P8" fontName="Times-Roman" fontSize="20.0" leading="25" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P9" fontName="Times-Roman" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P10" fontName="Times-Roman" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P11" fontName="Times-Roman" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="P12" fontName="Times-Roman" fontSize="11.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="Standard" fontName="Times-Roman" fontSize="12"/>
<paraStyle name="Text body" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="List" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="Table Contents" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="Table Heading" fontName="Times-Roman" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
<paraStyle name="Caption" fontName="Times-Roman" fontSize="10.0" leading="13" spaceBefore="6.0" spaceAfter="6.0"/>
<paraStyle name="Index" fontName="Times-Roman"/>
<paraStyle name="cat" fontName="Times-Bold" textColor="blue" fontSize="10.0" leading="13" spaceBefore="6.0" spaceAfter="6.0"/>
</stylesheet>
<story>
<para style="P5">
<font color="white"> </font>
</para>
<blockTable colWidths="530.0" repeatRows="1" style="Table1">
<tr>
<td>
<para style="P8">Products Price List</para>
</td>
</tr>
</blockTable>
<para style="P5">
<font color="white"> </font>
</para>
<para style="Standard">
<font color="white"> </font>
</para>
<para style="Standard">Price List Name : [[ get_pricelist (data['form']['price_list']) ]]</para>
<para style="Standard">Currency : [[ get_currency ( data['form']['price_list']) ]]</para>
<para style="Standard">Printing Date: [[ formatLang(time.strftime('%Y-%m-%d'), date=True) ]]</para>
<para style="P7">
<font color="white"> </font>
</para>
<section>
<para style="P6">[[repeatIn([],'qty_header',width=59,value=qty_header(data['form']),type='label') ]]</para>
<blockTable colWidths="227.0" style="Table6">
<tr>
<td>
<para style="P6">Description</para>
</td>
</tr>
</blockTable>
</section>
<section>
<para style="Standard">[[ repeatIn(get_categories(objects), 'c',width=59,value=get_quantity(data['form']),type='title') ]]</para>
<blockTable colWidths="227.0" style="Table3">
<tr>
<td>
<para style="cat">[[ c['name'] ]]</para>
</td>
</tr>
</blockTable>
<section>
<para style="Standard">[[repeatIn(c['products'], 'p',width=59,value=get_quantity(data['form']),type='string') ]]</para>
<blockTable colWidths="227.0" style="Table3">
<tr>
<td>
<para style="P1">[[ p['code'] and '[' + p['code'] + '] ' or '' ]] [[ p['name'] ]]</para>
</td>
</tr>
</blockTable>
</section>
</section>
<para style="P5"/>
<para style="P3">
<font color="white"> </font>
</para>
</story>
</document>

View File

@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Fabien Pinckaers <fp@tiny.Be>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import wizard_price
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,67 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Fabien Pinckaers <fp@tiny.Be>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import wizard
qty1_form = '''<?xml version="1.0"?>
<form string="Price list">
<field name="price_list" />
<field name="qty1" colspan="2" />
<field name="qty2" colspan="2" />
<field name="qty3" colspan="2" />
<field name="qty4" colspan="2" />
<field name="qty5" colspan="2" />
</form>'''
qty1_fields = {
'price_list' : {'string' : 'PriceList', 'type' : 'many2one', 'relation' : 'product.pricelist', 'required':True },
'qty1': {'string':'Quantity-1', 'type':'integer', 'default':0},
'qty2': {'string':'Quantity-2', 'type':'integer', 'default':0},
'qty3': {'string':'Quantity-3', 'type':'integer', 'default':0},
'qty4': {'string':'Quantity-4', 'type':'integer', 'default':0},
'qty5': {'string':'Quantity-5', 'type':'integer', 'default':0},
}
class wizard_qty(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type':'form', 'arch':qty1_form, 'fields':qty1_fields, 'state':[('end','Cancel'),('price','Print')]}
},
'price': {
'actions': [],
'result': {'type':'print', 'report':'product.pricelist', 'state':'end'}
}
}
wizard_qty('product.price_list')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -18,6 +18,21 @@
<wizard id="wizard_invoice_onshipping" keyword="client_action_multi" model="stock.picking" name="stock.invoice_onshipping" string="Create invoice"/>
<wizard
string="Set Stock to 0"
model="stock.inventory"
name="inventory.merge.stock.zero"
keyword="client_action_multi"
id="wizard_merge_inventory_zero"/>
<wizard
string="Merge inventories"
model="stock.inventory"
name="inventory.merge"
keyword="client_action_multi"
multi="True"
id="wizard_merge_inventory"/>
</data>
</openerp>

View File

@ -37,6 +37,8 @@ import wizard_split_lot_line
import wizard_track_line
import wizard_ups
import wizard_invoice_onshipping
import inventory_merge
import inventory_merge_zero
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,104 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import wizard
import pooler
_form = """<?xml version="1.0"?>
<form string="Merge inventories">
<separator colspan="4" string="Merge inventories" />
<label string="Do you want to merge theses inventories ?"/>
</form>
"""
def do_merge(self, cr, uid, data, context):
invent_obj = pooler.get_pool(cr.dbname).get('stock.inventory')
invent_line_obj = pooler.get_pool(cr.dbname).get('stock.inventory.line')
invent_lines = {}
if len(data['ids']) < 2:
raise wizard.except_wizard("Warning",
"Please select at least two inventories.")
for inventory in invent_obj.browse(cr, uid, data['ids'], context=context):
if inventory.state == "done":
raise wizard.except_wizard("Warning",
"Merging is only allowed on draft inventories.")
for line in inventory.inventory_line_id:
key = (line.location_id.id, line.product_id.id, line.product_uom.id)
if key in invent_lines:
invent_lines[key] += line.product_qty
else:
invent_lines[key] = line.product_qty
new_invent = invent_obj.create(cr, uid, {
'name': 'Merged inventory'
}, context=context)
for key, quantity in invent_lines.items():
invent_line_obj.create(cr, uid, {
'inventory_id': new_invent,
'location_id': key[0],
'product_id': key[1],
'product_uom': key[2],
'product_qty': quantity,
})
return {}
class merge_inventory(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'form',
'arch' : _form,
'fields' : {},
'state' : [('end', 'Cancel'),
('merge', 'Yes') ]}
},
'merge' : {
'actions' : [],
'result' : {'type' : 'action',
'action': do_merge,
'state' : 'end'}
},
}
merge_inventory("inventory.merge")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,94 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import wizard
import pooler
_form = """<?xml version="1.0"?>
<form string="Set Stock to Zero">
<separator colspan="4" string="Set Stocks to Zero" />
<label string="Do you want to set stocks to zero ?"/>
</form>
"""
def do_merge(self, cr, uid, data, context):
invent_obj = pooler.get_pool(cr.dbname).get('stock.inventory')
invent_line_obj = pooler.get_pool(cr.dbname).get('stock.inventory.line')
prod_obj = pooler.get_pool(cr.dbname).get('product.product')
if len(data['ids']) <> 1:
raise wizard.except_wizard("Warning",
"Please select one and only one inventory!")
cr.execute('select distinct location_id from stock_inventory_line where inventory_id=%d', (data['ids'][0],))
loc_ids = map(lambda x: x[0], cr.fetchall())
locs = ','.join(map(lambda x: str(x), loc_ids))
cr.execute('select distinct location_id,product_id from stock_inventory_line where inventory_id=%d', (data['ids'][0],))
inv = cr.fetchall()
cr.execute('select distinct product_id from stock_move where (location_dest_id in ('+locs+')) or (location_id in ('+locs+'))')
stock = cr.fetchall()
for s in stock:
for loc in loc_ids:
if (loc,s[0]) not in inv:
p = prod_obj.browse(cr, uid, s[0])
invent_line_obj.create(cr, uid, {
'inventory_id': data['ids'][0],
'location_id': loc,
'product_id': s[0],
'product_uom': p.uom_id.id,
'product_qty': 0.0,
})
return {}
class merge_inventory(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'form',
'arch' : _form,
'fields' : {},
'state' : [('end', 'Cancel'),
('merge', 'Set to Zero') ]}
},
'merge' : {
'actions' : [],
'result' : {'type' : 'action',
'action': do_merge,
'state' : 'end'}
},
}
merge_inventory("inventory.merge.stock.zero")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Fabien Pinckaers <fp@tiny.Be>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import stock_no_autopicking
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,23 @@
# -*- encoding: utf-8 -*-
{
"name":"Stock No Auto-Picking",
"version":"1.0",
"author":"Tiny",
"category":"Generic Modules/Production",
"description": """
This module allows an intermediate picking process to provide raw materials
to production orders.
One example of usage of this module is to manage production made by your
suppliers (sub-contracting). To achieve this, set the assembled product
which is sub-contracted to "No Auto-Picking" and put the location of the
supplier in the routing of the assembly operation.
""",
"depends":["mrp"],
"demo_xml":[],
"update_xml":["stock_no_autopicking_view.xml"],
"active":False,
"installable":True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,50 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# $Id: stock.py 1005 2005-07-25 08:41:42Z nicoe $
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import netsvc
from osv import fields,osv
class product(osv.osv):
_inherit = "product.product"
_columns = {
'auto_pick': fields.boolean('Auto Picking', help="Auto picking for raw materials of production orders.")
}
_defaults = {
'auto_pick': lambda *args: True
}
product()
class mrp_production(osv.osv):
_inherit = "mrp.production"
def _get_auto_picking(self, cr, uid, production):
return production.product_id.auto_pick
mrp_production()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,18 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record model="ir.ui.view" id="view_product_form_auto_pick">
<field name="name">product.normal.auto_pick.form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view" />
<field name="type">form</field>
<field name="arch" type="xml">
<field name="product_manager" position="after">
<field name="auto_pick" />
</field>
</field>
</record>
</data>
</openerp>