[MERGE]: Merge with lp:~openerp-dev/openobject-addons/trunk-dev-addons2

bzr revid: rpa@tinyerp.com-20101208092808-k4rxpuskhpcpohq9
This commit is contained in:
rpa (Open ERP)
2010-12-08 14:58:08 +05:30
22 changed files with 443 additions and 187 deletions
+22 -4
View File
@@ -53,11 +53,23 @@ class mrp_workcenter(osv.osv):
'costs_journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal'),
'costs_general_account_id': fields.many2one('account.account', 'General Account', domain=[('type','<>','view')]),
'resource_id': fields.many2one('resource.resource','Resource', ondelete='cascade', required=True),
'product_id': fields.many2one('product.product','Workcenter Product', help="Fill this product to track easily your production costs in the analytic accounting."),
}
_defaults = {
'capacity_per_cycle': 1.0,
'resource_type': 'material',
}
def on_change_product_cost(self, cr, uid, ids, product_id, context=None):
if context is None:
context = {}
value = {}
if product_id:
cost = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
value = {'costs_hour' :cost.standard_price}
return {'value': value}
mrp_workcenter()
@@ -99,8 +111,8 @@ class mrp_routing_workcenter(osv.osv):
'name': fields.char('Name', size=64, required=True),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of routing workcenters."),
'cycle_nbr': fields.float('Number of Cycles', required=True,
help="Number of operations this workcenter can do."),
'hour_nbr': fields.float('Number of Hours', required=True, help="Time in hours for doing one cycle."),
help="Number of iterations this workcenter has to do in the specified operation of the routing."),
'hour_nbr': fields.float('Number of Hours', required=True, help="Time in hours for this workcenter to achieve the operation of the specified routing."),
'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade',
help="Routing indicates all the workcenters used, for how long and/or cycles." \
"If Routing is indicated then,the third tab of a production order (workcenters) will be automatically pre-completed."),
@@ -746,7 +758,10 @@ class mrp_production(osv.osv):
'account_id': account,
'general_account_id': wc.costs_general_account_id.id,
'journal_id': wc.costs_journal_id.id,
'code': wc.code
'ref': wc.code,
'product_id': wc.product_id.id,
'unit_amount': wc_line.hour,
'product_uom_id': wc.product_id.uom_id.id
} )
if wc.costs_journal_id and wc.costs_general_account_id:
value = wc_line.cycle * wc.costs_cycle
@@ -759,7 +774,10 @@ class mrp_production(osv.osv):
'account_id': account,
'general_account_id': wc.costs_general_account_id.id,
'journal_id': wc.costs_journal_id.id,
'code': wc.code,
'ref': wc.code,
'product_id': wc.product_id.id,
'unit_amount': wc_line.cycle,
'product_uom_id': wc.product_id.uom_id.id
} )
return amount
+10 -9
View File
@@ -162,12 +162,13 @@
</group>
<group col="2" colspan="2">
<separator colspan="2" string="Costing Information"/>
<field name="product_id" on_change="on_change_product_cost(product_id)"/>
<field name="costs_hour"/>
<field name="costs_hour_account_id" groups="analytic.group_analytic_accounting"/>
<field name="costs_cycle"/>
<field name="costs_cycle_account_id" groups="analytic.group_analytic_accounting"/>
<field name="costs_journal_id" groups="analytic.group_analytic_accounting"/>
<field name="costs_general_account_id" groups="analytic.group_analytic_accounting"/>
<field name="costs_journal_id" attrs="{'required':['|',('costs_hour_account_id', '=', True),('costs_cycle_account_id', '=', True)]}" groups="analytic.group_analytic_accounting"/>
<field name="costs_general_account_id" attrs="{ 'required':['|',('costs_cycle_account_id', '=', True),('costs_hour_account_id', '=', True)]}" groups="analytic.group_analytic_accounting"/>
</group>
<separator colspan="4" string="Description"/>
<field colspan="4" name="note" nolabel="1"/>
@@ -650,9 +651,9 @@
<field name="product_uom" string="UOM"/>
<field name="location_id" string="Source Loc." />
<field name="state" invisible="1"/>
<button name="%(stock.action_partial_move)d"
string="Partial"
type="action" states="confirmed,assigned"
<button name="%(stock.action_partial_move)d"
string="Partial"
type="action" states="confirmed,assigned"
icon="gtk-justify-fill"/>
<button name="%(stock.move_scrap)d"
string="Scrap Products" type="action"
@@ -729,8 +730,8 @@
<field name="arch" type="xml">
<search string="Search Production">
<group col='9' colspan='4'>
<filter icon="terp-document-new" string="Draft"
domain="[('state','=','draft')]"
<filter icon="terp-camera_test" string="Ready"
domain="[('state','=','ready')]"
help="Non confirmed manufacturing orders"/>
<filter icon="terp-check" string="Current" name="current"
default="1"
@@ -935,9 +936,9 @@
<menuitem action="mrp_workcenter_action" id="menu_view_resource_search_mrp" parent="menu_pm_resources_config" sequence="1"/>
<menuitem action="resource.action_resource_calendar_form" id="menu_view_resource_calendar_search_mrp" parent="menu_pm_resources_config" sequence="1"/>
<menuitem action="resource.action_resource_calendar_leave_tree" id="menu_view_resource_calendar_leaves_search_mrp" parent="menu_pm_resources_config" sequence="1"/>
<!-- Planning -->
<menuitem id="menu_mrp_planning" name="Planning"
parent="base.menu_mrp_root" sequence="2"
groups="base.group_extended"/>
+1 -1
View File
@@ -25,7 +25,7 @@ class mrp_price(osv.osv_memory):
_name = 'mrp.product_price'
_description = 'Product Price'
_columns = {
'number': fields.integer('Quantity', required=True, help="Specify quantity of products to produce or buy. Report of Cost structure will be displayed base on this qunatity."),
'number': fields.integer('Quantity', required=True, help="Specify quantity of products to produce or buy. Report of Cost structure will be displayed base on this quantity."),
}
_defaults = {
'number': 1,
+16 -4
View File
@@ -119,11 +119,11 @@ class procurement_order(osv.osv):
'company_id': fields.many2one('res.company','Company',required=True),
}
_defaults = {
'state': lambda *a: 'draft',
'priority': lambda *a: '1',
'state': 'draft',
'priority': '1',
'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'close_move': lambda *a: 0,
'procure_method': lambda *a: 'make_to_order',
'close_move': 0,
'procure_method': 'make_to_order',
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'procurement.order', context=c)
}
@@ -490,6 +490,16 @@ class stock_warehouse_orderpoint(osv.osv):
_name = "stock.warehouse.orderpoint"
_description = "Minimum Inventory Rule"
def _get_draft_procurements(self, cr, uid, ids, field_name, arg, context=None):
if context is None:
context = {}
result = {}
procurement_obj = self.pool.get('procurement.order')
for orderpoint in self.browse(cr, uid, ids, context=context):
procurement_ids = procurement_obj.search(cr, uid , [('state', '=', 'draft'), ('product_id', '=', orderpoint.product_id.id), ('location_id', '=', orderpoint.location_id.id)])
result[orderpoint.id] = procurement_ids
return result
_columns = {
'name': fields.char('Name', size=32, required=True),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the orderpoint without removing it."),
@@ -508,6 +518,8 @@ class stock_warehouse_orderpoint(osv.osv):
help="The procurement quantity will by rounded up to this multiple."),
'procurement_id': fields.many2one('procurement.order', 'Latest procurement', ondelete="set null"),
'company_id': fields.many2one('res.company','Company',required=True),
'procurement_draft_ids': fields.function(_get_draft_procurements, method=True, type='many2many', relation="procurement.order", \
string="Related Procurement Orders",help="Draft procurement of the product and location of that orderpoint"),
}
_defaults = {
'active': lambda *a: 1,
+9 -5
View File
@@ -4,7 +4,7 @@
<!--
Procurement
-->
<record id="procurement_tree_view" model="ir.ui.view">
<field name="name">procurement.order.tree</field>
@@ -145,7 +145,7 @@
<field name="search_view_id" ref="view_procurement_filter"/>
<field name="help">Procurement Orders represent the need for a certain quantity of products, at a given time, in a given location. Sale Orders are one typical source of Procurement Orders (but these are distinct documents). Depending on the procurement parameters and the products configuration, the procurement engine will attempt to satisfy the need by reserving products from stock, or ordering products from a supplier, or passing a manufacturing order, etc. A Procurement Exception occurs when the system cannot find a way to fulfill a procurement. Some exceptions will resolve themselves automatically, but others require manual intervention (those are identified by a specific error message)</field>
</record>
<record id="procurement_action5" model="ir.actions.act_window">
<field name="name">Procurement Exceptions</field>
<field name="type">ir.actions.act_window</field>
@@ -224,6 +224,10 @@
<field name="procurement_id" readonly="1"/>
<field name="active" />
</group>
<group col="4" colspan="2" groups="base.group_extended">
<separator string="Procurement Orders to Process" colspan="2" />
<field name="procurement_draft_ids" colspan="2" nolabel="1"/>
</group>
</form>
</field>
</record>
@@ -238,11 +242,11 @@
<field name="help">You can define your minimum stock rules, so that OpenERP will trigger automatically the propositions of manufacturing or purchase orders according to the stock level. Once the virtual stock of a product (=stock on hand minus all confirmed orders and reservations) is bellow the minimum quantity, OpenERP will generate a procurement request in order to fullfil the stock up to the maximum quantity.</field>
</record>
<act_window
<act_window
context="{'search_default_warehouse_id': active_id}"
id="act_stock_warehouse_2_stock_warehouse_orderpoint"
name="Minimum Stock Rules"
res_model="stock.warehouse.orderpoint"
name="Minimum Stock Rules"
res_model="stock.warehouse.orderpoint"
src_model="stock.warehouse"/>
<!-- add product_uom to context to be the default value when adding new orderpoints -->
+38 -11
View File
@@ -34,14 +34,14 @@ class procurement_order(osv.osv):
def _procure_confirm(self, cr, uid, ids=None, use_new_cursor=False, context=None):
'''
Call the scheduler to check the procurement order
@param self: The object pointer
@param cr: The current row, from the database cursor,
@param uid: The current user ID for security checks
@param ids: List of selected IDs
@param use_new_cursor: False or the dbname
@param context: A standard dictionary for contextual values
@return: Dictionary of values
@return: Dictionary of values
'''
if not context:
context = {}
@@ -50,7 +50,7 @@ class procurement_order(osv.osv):
if use_new_cursor:
cr = pooler.get_db(use_new_cursor).cursor()
wf_service = netsvc.LocalService("workflow")
procurement_obj = self.pool.get('procurement.order')
if not ids:
ids = procurement_obj.search(cr, uid, [], order="date_planned")
@@ -112,13 +112,13 @@ class procurement_order(osv.osv):
if uid:
request = self.pool.get('res.request')
summary = '''Here is the procurement scheduling report.
Start Time: %s
End Time: %s
Total Procurements processed: %d
Procurements with exceptions: %d
Skipped Procurements (scheduled date outside of scheduler range) %d
Exceptions:\n'''% (start_date, end_date, report_total, report_except, report_later)
summary += '\n'.join(report)
request.create(cr, uid,
@@ -141,7 +141,7 @@ class procurement_order(osv.osv):
def create_automatic_op(self, cr, uid, context=None):
"""
Create procurement of virtual stock < 0
@param self: The object pointer
@param cr: The current row, from the database cursor,
@param uid: The current user ID for security checks
@@ -157,7 +157,9 @@ class procurement_order(osv.osv):
warehouse_ids = warehouse_obj.search(cr, uid, [], context=context)
cr.execute('select id from product_product')
cr.execute('select p.id from product_product p \
join product_template t on (p.product_tmpl_id=t.id) \
where p.active=True and t.purchase_ok=True')
products_id = [x for x, in cr.fetchall()]
for warehouse in warehouse_obj.browse(cr, uid, warehouse_ids, context=context):
@@ -191,14 +193,14 @@ class procurement_order(osv.osv):
'''
Create procurement based on Orderpoint
use_new_cursor: False or the dbname
@param self: The object pointer
@param cr: The current row, from the database cursor,
@param user_id: The current user ID for security checks
@param context: A standard dictionary for contextual values
@param param: False or the dbname
@return: Dictionary of values
"""
"""
'''
if not context:
context = {}
@@ -212,27 +214,52 @@ class procurement_order(osv.osv):
report = []
offset = 0
ids = [1]
newdate = datetime.today()
if automatic:
self.create_automatic_op(cr, uid, context=context)
while ids:
ids = orderpoint_obj.search(cr, uid, [], offset=offset, limit=100)
for op in orderpoint_obj.browse(cr, uid, ids):
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
if op.procurement_id.state != 'exception':
if op.procurement_id and op.procurement_id.purchase_id and op.procurement_id.purchase_id.state in ('draft', 'confirmed'):
continue
prods = location_obj._product_virtual_get(cr, uid,
op.location_id.id, [op.product_id.id],
{'uom': op.product_uom.id})[op.product_id.id]
if prods < op.product_min_qty:
qty = max(op.product_min_qty, op.product_max_qty)-prods
reste = qty % op.qty_multiple
if reste > 0:
qty += op.qty_multiple - reste
newdate = datetime.today() + relativedelta(
days = int(op.product_id.seller_delay))
if qty <= 0:
continue
if op.product_id.type not in ('consu'):
# Check draft procurement related to this order point
if op.procurement_draft_ids:
procure_qty = {}
#Compute list of draft procurement attached to Orderpoint
for pro_data in op.procurement_draft_ids:
procure_qty.update({pro_data.product_qty: pro_data.id })
procure_list = procure_qty.keys()
procure_list.sort()
procure_list.reverse()
to_generate = qty
for proc in procure_list:
if to_generate >= proc:
wf_service.trg_validate(uid, 'procurement.order', procure_qty[proc], 'button_confirm', cr)
procurement_obj.write(cr, uid, [procure_qty[proc]], {'origin': op.name}, context=context)
to_generate -= proc
if not to_generate:
break
qty = to_generate
if qty:
proc_id = procurement_obj.create(cr, uid, {
'name': op.name,
'date_planned': newdate.strftime('%Y-%m-%d'),
@@ -248,7 +275,7 @@ class procurement_order(osv.osv):
wf_service.trg_validate(uid, 'procurement.order', proc_id,
'button_check', cr)
orderpoint_obj.write(cr, uid, [op.id],
{'procurement_id': proc_id})
{'procurement_id': proc_id}, context=context)
offset += len(ids)
if use_new_cursor:
cr.commit()
-9
View File
@@ -346,16 +346,7 @@ class product_template(osv.osv):
return False
return True
def _check_uos(self, cursor, user, ids):
for product in self.browse(cursor, user, ids):
if product.uos_id \
and product.uos_id.category_id.id \
== product.uom_id.category_id.id:
return False
return True
_constraints = [
(_check_uos, 'Error: UOS must be in a different category than the UOM', ['uos_id']),
(_check_uom, 'Error: The default UOM and the purchase UOM must be in the same category.', ['uom_id']),
]
+18 -6
View File
@@ -8,6 +8,18 @@
<menuitem id="menu_procurement_management" name="Purchase Management"
parent="base.menu_purchase_root" sequence="1" />
<menuitem id="menu_purhase_config_purchase" name="Configuration"
parent="base.menu_purchase_root" sequence="100"/>
<menuitem
action="product.product_pricelist_action" id="menu_product_pricelist_action_purhase"
parent="menu_purhase_config_purchase" sequence="2"/>
<menuitem
action="product.product_pricelist_action2" id="menu_product_pricelist_action2_purchase"
parent="menu_purhase_config_purchase" sequence="1"/>
<!--supplier addresses action-->
<record id="action_supplier_address_form" model="ir.actions.act_window">
<field name="name">Addresses</field>
@@ -162,7 +174,7 @@
<group colspan="2" col="2">
<separator string="Invoice Control" colspan="2"/>
<field name="invoice_method"/>
<field name="invoice_id" readonly="1" groups="base.group_extended"/>
<field name="invoice_id" readonly="1" groups="base.group_extended" />
<field name="fiscal_position" widget="selection"/>
</group>
<newline/>
@@ -312,12 +324,12 @@
<field name="product_id"/>
<field name="price_unit"/>
<field name="product_qty"/>
<field name="product_uom"/>
<field name="product_uom"/>
<field name="price_subtotal"/>
<field name="date_planned" widget="date" width="135"/>
<field name="state" invisible="1"/>
<field name="invoiced" invisible="1"/>
</tree>
@@ -375,7 +387,7 @@
<field name="order_id"/>
<field name="product_id"/>
<field name="partner_id" string="Supplier"/>
</group>
</group>
<newline/>
<group expand="0" string="Group By...">
<filter string="Supplier" icon="terp-partner" domain="[]" context="{'group_by' : 'partner_id'}" />
+26 -24
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@@ -26,26 +26,26 @@ from tools.translate import _
class purchase_line_invoice(osv.osv_memory):
""" To create invoice for purchase order line"""
_name = 'purchase.order.line_invoice'
_description = 'Purchase Order Line Make Invoice'
def makeInvoices(self, cr, uid, ids, context=None):
"""
"""
To get Purchase Order line and create Invoice
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param context: A standard dictionary
@param context: A standard dictionary
@return : retrun view of Invoice
"""
if context is None:
context={}
record_ids = context.get('active_ids',[])
if record_ids:
res = False
@@ -55,28 +55,28 @@ class purchase_line_invoice(osv.osv_memory):
property_obj=self.pool.get('ir.property')
account_fiscal_obj=self.pool.get('account.fiscal.position')
invoice_line_obj=self.pool.get('account.invoice.line')
account_jrnl_obj=self.pool.get('account.journal')
def multiple_order_invoice_name(orders):
name = "PO";
for order in orders:
name += "-%d" % order.id
return name
def multiple_order_invoice_reference(partner, orders):
reference = "P%dPO" % partner.id
for order in orders:
for order in orders:
reference += "-%d" % order.id
return reference
def multiple_order_invoice_notes(orders):
notes = ""
for order in orders:
notes += "%s \n" % order.notes
return notes
def make_invoice_by_partner(partner, orders, lines_ids):
"""
create a new invoice for one supplier
@@ -84,23 +84,25 @@ class purchase_line_invoice(osv.osv_memory):
@param orders : The set of orders to add in the invoice
@param lines : The list of line's id
"""
journal_id = account_jrnl_obj.search(cr, uid, [('type', '=', 'purchase')], context=None)
journal_id = journal_id and journal_id[0] or False
a = partner.property_account_payable.id
if partner and partner.property_payment_term.id:
pay_term = partner.property_payment_term.id
else:
pay_term = False
inv = {
'name': multiple_order_invoice_name(orders),
'origin': multiple_order_invoice_name(orders),
'name': multiple_order_invoice_name(orders),
'origin': multiple_order_invoice_name(orders),
'type': 'in_invoice',
'journal_id':journal_id,
'reference': multiple_order_invoice_reference(partner, orders),
'account_id': a,
'partner_id': partner.id,
'address_invoice_id': orders[0].partner_address_id.id,
'address_contact_id': orders[0].partner_address_id.id,
'invoice_line': [(6,0,lines_ids)],
'currency_id' : orders[0].pricelist_id.currency_id.id,
'currency_id' : orders[0].pricelist_id.currency_id.id,
'comment': multiple_order_invoice_notes(orders),
'payment_term': pay_term,
'fiscal_position': partner.property_account_position.id
@@ -136,7 +138,7 @@ class purchase_line_invoice(osv.osv_memory):
'uos_id': line.product_uom.id,
'product_id': line.product_id.id or False,
'invoice_line_tax_id': [(6, 0, [x.id for x in line.taxes_id])],
'note': line.notes,
'note': line.notes,
'account_analytic_id': line.account_analytic_id and line.account_analytic_id.id or False,
})
cr.execute('insert into purchase_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))
@@ -147,7 +149,7 @@ class purchase_line_invoice(osv.osv_memory):
for result in invoices.values():
il = map(lambda x: x[1], result)
orders = list(set(map(lambda x : x[0].order_id, result)))
res.append(make_invoice_by_partner(orders[0].partner_id, orders, il))
return {
+6 -2
View File
@@ -38,8 +38,12 @@ def register_report(name, model, tmpl_path, parser=rml_parse):
"Register the report into the services"
name = 'report.%s' % name
if netsvc.Service._services.get(name, False):
if hasattr(netsvc.Service._services[name], 'parser'):
parser = netsvc.Service._services[name].parser
service = netsvc.Service._services[name]
if isinstance(service, WebKitParser):
#already instantiated properly, skip it
return
if hasattr(service, 'parser'):
parser = service.parser
del netsvc.Service._services[name]
WebKitParser(name, model, tmpl_path, parser=parser)
+1 -1
View File
@@ -51,7 +51,7 @@ class WebKitHelper(object):
height = 'width="%spx"'%(height)
else :
height = ' '
toreturn = '<img %s %s src="data:image/%s;base64,%s">'%(
toreturn = '<img %s %s src="data:image/%s;base64,%s" />'%(
width,
height,
type,
+79 -54
View File
@@ -35,7 +35,7 @@ import report
import tempfile
import time
from mako.template import Template
from mako import exceptions
import netsvc
import pooler
from report_helper import WebKitHelper
@@ -84,8 +84,10 @@ class WebKitParser(report_sxw):
_('path to Wkhtmltopdf is not absolute'),
'for path %s'%(path)
)
def generate_pdf(self, comm_path, report_xml, header, footer, html_list):
def generate_pdf(self, comm_path, report_xml, header, footer, html_list, webkit_header=False):
"""Call webkit in order to generate pdf"""
if not webkit_header:
webkit_header = report_xml.webkit_header
tmp_dir = tempfile.gettempdir()
out = report_xml.name+str(time.time())+'.pdf'
out = os.path.join(tmp_dir, out.replace(' ',''))
@@ -95,7 +97,7 @@ class WebKitParser(report_sxw):
command = [comm_path]
else:
command = ['wkhtmltopdf']
command.append('-q')
if header :
head_file = file( os.path.join(
@@ -120,20 +122,22 @@ class WebKitParser(report_sxw):
file_to_del.append(foot_file.name)
command.append("--footer-html '%s'"%(foot_file.name))
if report_xml.webkit_header.margin_top :
command.append('--margin-top %s'%(report_xml.webkit_header.margin_top))
if report_xml.webkit_header.margin_bottom :
command.append('--margin-bottom %s'%(report_xml.webkit_header.margin_bottom))
if report_xml.webkit_header.margin_left :
command.append('--margin-left %s'%(report_xml.webkit_header.margin_left))
if report_xml.webkit_header.margin_right :
command.append('--margin-right %s'%(report_xml.webkit_header.margin_right))
if report_xml.webkit_header.orientation :
command.append("--orientation '%s'"%(report_xml.webkit_header.orientation))
if report_xml.webkit_header.format :
command.append(" --page-size '%s'"%(report_xml.webkit_header.format))
if webkit_header.margin_top :
command.append('--margin-top %s'%(webkit_header.margin_top))
if webkit_header.margin_bottom :
command.append('--margin-bottom %s'%(webkit_header.margin_bottom))
if webkit_header.margin_left :
command.append('--margin-left %s'%(webkit_header.margin_left))
if webkit_header.margin_right :
command.append('--margin-right %s'%(webkit_header.margin_right))
if webkit_header.orientation :
command.append("--orientation '%s'"%(webkit_header.orientation))
if webkit_header.format :
command.append(" --page-size '%s'"%(webkit_header.format))
count = 0
for html in html_list :
html_file = file(os.path.join(tmp_dir, str(time.time()) + '.body.html'), 'w')
html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w')
count += 1
html_file.write(html)
html_file.close()
file_to_del.append(html_file.name)
@@ -168,6 +172,8 @@ class WebKitParser(report_sxw):
"""Translate String."""
ir_translation = self.pool.get('ir.translation')
res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid, self.name, 'report', self.localcontext.get('lang', 'en_US'), src)
if not res :
return src
return res
def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False):
@@ -207,14 +213,14 @@ class WebKitParser(report_sxw):
if context is None:
context={}
if report_xml.report_type != 'webkit':
return super(WebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context)
self.parser_instance = self.parser(
cursor,
uid,
self.name2,
cursor,
uid,
self.name2,
context=context
)
@@ -272,45 +278,64 @@ class WebKitParser(report_sxw):
#default_filters=['unicode', 'entity'] can be used to set global filter
body_mako_tpl = Template(template ,input_encoding='utf-8')
helper = WebKitHelper(cursor, uid, report_xml.id, context)
html = body_mako_tpl.render( helper=helper,
css=css,
_=self.translate_call,
**self.parser_instance.localcontext
)
try :
html = body_mako_tpl.render( helper=helper,
css=css,
_=self.translate_call,
**self.parser_instance.localcontext
)
except Exception, e:
msg = exceptions.text_error_template().render()
netsvc.Logger().notifyChannel('Webkit render', netsvc.LOG_ERROR, msg)
raise except_osv(_('Webkit render'), msg)
head_mako_tpl = Template(header, input_encoding='utf-8')
head = head_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
_debug=False
)
try :
head = head_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
_debug=False
)
except Exception, e:
raise except_osv(_('Webkit render'),
exceptions.text_error_template().render())
foot = False
if footer :
foot_mako_tpl = Template(footer ,input_encoding='utf-8')
foot = foot_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
)
try :
foot = foot_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
)
except:
msg = exceptions.text_error_template().render()
netsvc.Logger().notifyChannel('Webkit render', netsvc.LOG_ERROR, msg)
raise except_osv(_('Webkit render'), msg)
if report_xml.webkit_debug :
deb = head_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
_debug=html,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
)
try :
deb = head_mako_tpl.render(
company=company,
time=time,
helper=helper,
css=css,
_debug=html,
formatLang=self.formatLang,
setLang=self.setLang,
_=self.translate_call,
)
except Exception, e:
msg = exceptions.text_error_template().render()
netsvc.Logger().notifyChannel('Webkit render', netsvc.LOG_ERROR, msg)
raise except_osv(_('Webkit render'), msg)
return (deb, 'html')
bin = self.get_lib(cursor, uid, company.id)
pdf = self.generate_pdf(bin, report_xml, head, foot, [html])
+3 -2
View File
@@ -45,10 +45,11 @@ Thanks to the double entry management, the inventory controlling is powerful and
"init_xml" : [],
"demo_xml" : ["stock_demo.xml"],
"update_xml" : [
"security/stock_security.xml",
"security/ir.model.access.csv",
"security/stock_security.xml",
"security/ir.model.access.csv",
"stock_data.xml",
"wizard/stock_move_view.xml",
"wizard/stock_change_product_qty_view.xml",
"wizard/stock_partial_picking_view.xml",
"wizard/stock_partial_move_view.xml",
"wizard/stock_fill_inventory_view.xml",
+4 -1
View File
@@ -102,9 +102,12 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<group name="status" position="after">
<group colspan="2" col="2">
<group colspan="2" col="3">
<separator string="Stocks" colspan="4"/>
<field name="qty_available"/>
<button name="%(action_view_change_product_quantity)d" string="Update" attrs="{'invisible': [('type', '=', 'service')]}"
type="action" icon="gtk-execute" groups = "stock.group_stock_manager,product.group_product_manager"/>
<newline/>
<field name="virtual_available"/>
</group>
<group colspan="2" col="2" name="lot" groups="base.group_extended">
+20 -7
View File
@@ -110,6 +110,7 @@ class stock_location(osv.osv):
@param field_names: Name of field
@return: Dictionary of values
"""
prod_id = context and context.get('product_id', False)
product_product_obj = self.pool.get('product.product')
@@ -122,9 +123,10 @@ class stock_location(osv.osv):
currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
currency_obj = self.pool.get('res.currency')
currency = self.pool.get('res.currency').browse(cr, uid, currency_id)
currency_obj.round(cr, uid, currency, 300)
currency = currency_obj.browse(cr, uid, currency_id, context=context)
for loc_id, product_ids in products_by_location.items():
if prod_id:
product_ids = [prod_id]
c = (context or {}).copy()
c['location'] = loc_id
for prod in product_product_obj.browse(cr, uid, product_ids, context=c):
@@ -1494,8 +1496,8 @@ class stock_move(osv.osv):
'location_dest_id': fields.many2one('stock.location', 'Destination Location', required=True,states={'done': [('readonly', True)]}, select=True, help="Location where the system will stock the finished products."),
'address_id': fields.many2one('res.partner.address', 'Destination Address', help="Optional address where goods are to be delivered, specifically used for allotment"),
'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', help="Production lot is used to put a serial number on the production", select=True),
'tracking_id': fields.many2one('stock.tracking', 'Pack', select=True, help="Logistical shipping unit: pallet, box, pack ..."),
'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', states={'done': [('readonly', True)]}, help="Production lot is used to put a serial number on the production", select=True),
'tracking_id': fields.many2one('stock.tracking', 'Pack', select=True, states={'done': [('readonly', True)]}, help="Logistical shipping unit: pallet, box, pack ..."),
'auto_validate': fields.boolean('Auto Validate'),
@@ -1930,6 +1932,12 @@ class stock_move(osv.osv):
acc_variation = accounts.get('property_stock_variation', False)
journal_id = accounts['stock_journal']
if acc_dest == acc_variation:
raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Output Account defined on this product and Variant account on category of this product is same.'))
if acc_src == acc_variation:
raise osv.except_osv(_('Error!'), _('Can not create Journal Entry, Input Account defined on this product and Variant account on category of this product is same.'))
if not acc_src:
raise osv.except_osv(_('Error!'), _('There is no stock input account defined for this product or its category: "%s" (id: %d)') % \
(move.product_id.name, move.product_id.id,))
@@ -2442,6 +2450,12 @@ class stock_inventory(osv.osv):
return self.pool.get('stock.move').create(cr, uid, move_vals)
def action_done(self, cr, uid, ids, context=None):
""" Finished the inventory
@return: True
"""
if context is None:
context = {}
move_obj = self.pool.get('stock.move')
for inv in self.browse(cr, uid, ids, context=context):
move_obj.action_done(cr, uid, [x.id for x in inv.move_ids], context=context)
@@ -2449,18 +2463,17 @@ class stock_inventory(osv.osv):
return True
def action_confirm(self, cr, uid, ids, context=None):
""" Finishes the inventory and writes its finished date
""" Confirm the inventory and writes its finished date
@return: True
"""
if context is None:
context = {}
# to perform the correct inventory corrections we need analyze stock location by
# location, never recursively, so we use a special context
product_context = dict(context, compute_child=False)
location_obj = self.pool.get('stock.location')
for inv in self.browse(cr, uid, ids):
for inv in self.browse(cr, uid, ids, context=context):
move_ids = []
for line in inv.inventory_line_id:
pid = line.product_id.id
+17 -17
View File
@@ -670,15 +670,15 @@
attrs="{'invisible': [('tracking_id','&lt;&gt;',False)]}"
icon="terp-stock_effects-object-colorize"
groups="base.group_extended"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<button name="%(split_into)d" string="Put in a new pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<button name="%(split_into)d" string="Put in a new pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_expected" string="Date Expected"/>
@@ -719,14 +719,14 @@
<button name="%(split_into)d" string="New pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done" colspan="1"/>
states="draft,assigned,confirmed" colspan="1"/>
<field name="prodlot_id" groups="base.group_extended"
context="{'location_id':location_id, 'product_id':product_id}"
domain="[('product_id','=?',product_id)]"
on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)" colspan="3"/>
<button name="%(track_line)d"
groups="base.group_extended"
states="draft,waiting,confirmed,assigned,done"
states="draft,waiting,confirmed,assigned"
string="Split" type="action" icon="terp-stock_effects-object-colorize" colspan="1" />
</group>
<label string="" colspan="4"/>
@@ -859,18 +859,18 @@
<field name="prodlot_id" groups="base.group_extended"/>
<button name="%(track_line)d" string="Split in production lots" type="action"
icon="terp-stock_effects-object-colorize" attrs="{'invisible': [('prodlot_id','&lt;&gt;',False)]}"
states="draft,assigned,confirmed,done"
states="draft,assigned,confirmed"
groups="base.group_extended"/>
<field name="tracking_id" groups="base.group_extended"/>
<button name="setlast_tracking" string="Put in current pack" type="object"
attrs="{'invisible': [('tracking_id','&lt;&gt;',False)]}"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<button name="%(split_into)d" string="Put in a new pack" type="action"
icon="terp-stock_effects-object-colorize"
groups="base.group_extended"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<field name="location_id"/>
<field name="date"/>
<field name="state"/>
@@ -912,14 +912,14 @@
<button name="%(split_into)d" string="New pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done" colspan="1"/>
states="draft,assigned,confirmed" colspan="1"/>
<field name="prodlot_id" groups="base.group_extended"
context="{'location_id':location_id, 'product_id':product_id}"
domain="[('product_id','=?',product_id)]"
on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)" colspan="3"/>
<button name="%(track_line)d"
groups="base.group_extended"
states="draft,waiting,confirmed,assigned,done"
states="draft,waiting,confirmed,assigned"
string="Split" type="action" icon="terp-stock_effects-object-colorize" colspan="1" />
</group>
<label string="" colspan="4"/>
@@ -1089,7 +1089,7 @@
<button name="setlast_tracking" string="Put in current pack" type="object"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize" attrs="{'invisible': [('tracking_id','&lt;&gt;',False)]}"
states="draft,assigned,confirmed,done"/>
states="draft,assigned,confirmed"/>
<button name="%(split_into)d" string="Put in a new pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
@@ -1132,14 +1132,14 @@
<button name="%(split_into)d" string="New pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done" colspan="1"/>
states="draft,assigned,confirmed" colspan="1"/>
<field name="prodlot_id" groups="base.group_extended"
context="{'location_id':location_id, 'product_id':product_id}"
domain="[('product_id','=?',product_id)]"
on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)" colspan="3"/>
<button name="%(track_line)d"
groups="base.group_extended"
states="draft,waiting,confirmed,assigned,done"
states="draft,waiting,confirmed,assigned"
string="Split" type="action" icon="terp-stock_effects-object-colorize" colspan="1" />
</group>
<label string="" colspan="4"/>
@@ -1399,14 +1399,14 @@
<button name="%(split_into)d" string="New pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done" colspan="1"/>
states="draft,assigned,confirmed" colspan="1"/>
<field name="prodlot_id" groups="base.group_extended"
context="{'location_id':location_id, 'product_id':product_id}"
domain="[('product_id','=?',product_id)]"
on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)" colspan="3"/>
<button name="%(track_line)d"
groups="base.group_extended"
states="draft,waiting,confirmed,assigned,done"
states="draft,waiting,confirmed,assigned"
string="Split" type="action" icon="terp-stock_effects-object-colorize" colspan="1"/>
</group>
@@ -1758,7 +1758,7 @@
src_model="stock.location"/>
<act_window
context="{'location': active_id, 'search_default_done': 1,'search_default_product_id': [active_id]}"
context="{'search_default_done': 1,'search_default_product_id': [active_id]}"
id="act_product_stock_move_open"
name="Stock Moves"
res_model="stock.move"
@@ -1772,7 +1772,7 @@
src_model="stock.move"/>
<act_window
context="{'location': active_id, 'search_default_future': 1,'search_default_product_id': [active_id]}"
context="{'search_default_future': 1,'search_default_product_id': [active_id]}"
domain="[('state','in',('waiting','confirmed','assigned'))]"
id="act_product_stock_move_futur_open"
name="Future Stock Moves"
+1 -1
View File
@@ -33,6 +33,6 @@ import stock_invoice_onshipping
import stock_location_product
import stock_change_standard_price
import stock_return_picking
import stock_change_product_qty
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 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/>.
#
##############################################################################
from osv import fields, osv
from tools.translate import _
import time
class stock_change_product_qty(osv.osv_memory):
_name = "stock.change.product.qty"
_description = "Change Product Quantity"
_columns = {
'new_quantity': fields.float('Quantity', required=True),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True, ondelete="cascade"),
'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="cascade", domain="[('usage', '=', 'internal')]"),
}
def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context={}):
""" Finds location id for changed warehouse.
@param warehouse_id: Changed id of warehouse.
@return: Dictionary of values.
"""
if warehouse_id:
warehouse = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context)
val = {'location_id': warehouse.lot_stock_id.id}
return {'value': val}
return {}
def default_get(self, cr, uid, fields, context):
""" To get default values for the object.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
res = super(stock_change_product_qty, self).default_get(cr, uid, fields, context=context)
wids = self.pool.get('stock.warehouse').search(cr, uid, [], context=context)
if 'warehouse_id' in fields:
res.update({'warehouse_id': wids and wids[0] or False})
if 'new_quantity' in fields:
res.update({'new_quantity': 1})
return res
def change_product_qty(self, cr, uid, ids, context=None):
""" Changes the Product Quantity by making a Physical Inventory.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of IDs selected
@param context: A standard dictionary
@return:
"""
if context is None:
context = {}
move_ids = []
rec_id = context and context.get('active_id', False)
assert rec_id, _('Active ID is not set in Context')
inventry_obj = self.pool.get('stock.inventory')
inventry_line_obj = self.pool.get('stock.inventory.line')
prod_obj_pool = self.pool.get('product.product')
res_original = prod_obj_pool.browse(cr, uid, rec_id, context=context)
for data in self.browse(cr, uid, ids, context=context):
invntry_id = inventry_obj.create(cr , uid, {'name': 'INV:' + str(res_original.name)}, context=context)
line_data ={
'inventory_id' : invntry_id,
'product_qty' : data.new_quantity,
'location_id' : data.location_id.id,
'product_id' : rec_id,
'product_uom' : res_original.uom_id.id,
'company_id' : self.pool.get('res.users').browse(cr, uid, uid).company_id.id or False ,
}
line_id = inventry_line_obj.create(cr , uid, line_data, context=context)
inventry_obj.action_confirm(cr, uid, [invntry_id], context=context)
inventry_obj.action_done(cr, uid, [invntry_id], context=context)
return {}
stock_change_product_qty()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_change_product_quantity" model="ir.ui.view">
<field name="name">Change Product Quantity</field>
<field name="model">stock.change.product.qty</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Change Product Quantity">
<separator string="Select Quantity" colspan="4"/>
<newline/>
<field name="new_quantity" />
<newline/>
<field name="warehouse_id" on_change="onchange_warehouse_id(warehouse_id)" widget="selection"/>
<field name="location_id" />
<separator string="" colspan="4" />
<label string="" colspan="2"/>
<group col="2" colspan="2">
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
<button name="change_product_qty" string="_Apply" type="object" icon="gtk-apply"/>
</group>
</form>
</field>
</record>
<record id="action_view_change_product_quantity" model="ir.actions.act_window">
<field name="name">Change Product Quantity</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">stock.change.product.qty</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_change_product_quantity"/>
<field name="target">new</field>
</record>
</data>
</openerp>
+19 -19
View File
@@ -56,16 +56,16 @@ class stock_return_picking(osv.osv_memory):
return res
def view_init(self, cr, uid, fields_list, context=None):
"""
"""
Creates view dynamically and adding fields at runtime.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param context: A standard dictionary
@param context: A standard dictionary
@return: New arch of view with new columns.
"""
res = super(stock_return_picking, self).view_init(cr, uid, fields_list, context=context)
record_id = context and context.get('active_id', False)
record_id = context and context.get('active_id', False)
if record_id:
pick_obj = self.pool.get('stock.picking')
pick = pick_obj.browse(cr, uid, record_id)
@@ -87,15 +87,15 @@ class stock_return_picking(osv.osv_memory):
if not valid_lines:
raise osv.except_osv(_('Warning !'), _("There are no products to return (only lines in Done state and not fully returned yet can be returned)!"))
return res
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
context=None, toolbar=False, submenu=False):
"""
"""
Changes the view dynamically
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param context: A standard dictionary
@param context: A standard dictionary
@return: New arch of view.
"""
res = super(stock_return_picking, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
@@ -116,7 +116,7 @@ class stock_return_picking(osv.osv_memory):
quantity = m.product_qty
if m.state=='done' and quantity > return_history[m.id]:
arch_lst.append('<field name="return%s"/>\n<newline/>' % (m.id,))
res['fields']['return%s' % m.id]={'string':m.name, 'type':'float', 'required':True}
res['fields']['return%s' % m.id]={'string':m.name, 'type':'float', 'required':True}
res.setdefault('returns', []).append(m.id)
arch_lst.append('<field name="invoice_state"/>\n<newline/>')
res['fields']['invoice_state']={'string':_('Invoicing'), 'type':'selection','required':True, 'selection':[('2binvoiced', _('To be refunded/invoiced')), ('none', _('No invoicing'))]}
@@ -129,26 +129,26 @@ class stock_return_picking(osv.osv_memory):
return res
def create_returns(self, cr, uid, ids, context):
"""
"""
Creates return picking.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of ids selected
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
@param ids: List of ids selected
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
record_id = context and context.get('active_id', False) or False
move_obj = self.pool.get('stock.move')
pick_obj = self.pool.get('stock.picking')
uom_obj = self.pool.get('product.uom')
wf_service = netsvc.LocalService("workflow")
pick = pick_obj.browse(cr, uid, record_id)
data = self.read(cr, uid, ids[0])
new_picking = None
date_cur = time.strftime('%Y-%m-%d %H:%M:%S')
set_invoice_state_to_none = True
returned_lines = 0
for move in pick.move_lines:
@@ -159,22 +159,22 @@ class stock_return_picking(osv.osv_memory):
new_type = 'out'
else:
new_type = 'internal'
new_picking = pick_obj.copy(cr, uid, pick.id, {'name':'%s (return)' % pick.name,
new_picking = pick_obj.copy(cr, uid, pick.id, {'name':'%s-return' % pick.name,
'move_lines':[], 'state':'draft', 'type':new_type,
'date':date_cur, 'invoice_state':data['invoice_state'],})
new_location=move.location_dest_id.id
if move.state=='done':
new_qty = data['return%s' % move.id]
returned_qty = move.product_qty
for rec in move.move_history_ids2:
returned_qty -= rec.product_qty
if returned_qty != new_qty:
set_invoice_state_to_none = False
if new_qty:
returned_lines += 1
returned_lines += 1
new_move=move_obj.copy(cr, uid, move.id, {
'product_qty': new_qty,
'product_uos_qty': uom_obj._compute_qty(cr, uid, move.product_uom.id,
+1 -1
View File
@@ -64,7 +64,7 @@ class stock_split_into(osv.osv_memory):
if quantity_rest>0:
quantity_rest = move.product_qty - quantity
tracking_id = track_obj.create(cr, uid, {}, context=context)
if quantity==0.0:
if quantity == 0.0:
move_obj.write(cr, uid, [move.id], {'tracking_id': tracking_id}, context=context)
else:
default_val = {
+9 -9
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,34 +15,34 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class action_traceability(osv.osv_memory):
"""
"""
This class defines a function action_traceability for wizard
"""
_name = "action.traceability"
_description = "Action traceability "
def action_traceability(self, cr, uid, ids, context={}):
""" It traces the information of a product
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of IDs selected
@param context: A standard dictionary
@param ids: List of IDs selected
@param context: A standard dictionary
@return: A dictionary of values
"""
lot_id = ids
type1 = context['type'] or 'move_history_ids2'
field = context['field'] or 'tracking_id'
obj = self.pool.get('stock.move')
ids = obj.search(cr, uid, [(field, 'in',context['active_ids'])])
ids = obj.search(cr, uid, [(field, 'in',lot_id)])
cr.execute('select id from ir_ui_view where model=%s and field_parent=%s and type=%s', ('stock.move', type1, 'tree'))
view_id = cr.fetchone()[0]
value = {
@@ -53,7 +53,7 @@ class action_traceability(osv.osv_memory):
'field_parent': type1,
'view_id': (view_id,'View'),
'type': 'ir.actions.act_window',
'nodestroy':True,
'nodestroy':True,
}
return value