bzr revid: hmo@tinyerp.com-20100311142449-gfhiuwigpchfr074
This commit is contained in:
Harry (Open ERP)
2010-03-11 19:54:49 +05:30
82 changed files with 2291 additions and 1884 deletions
+3
View File
@@ -64,6 +64,9 @@ class node_calendar(object):
def _get_ttag(self,cr):
return 'calendar-%d' % self.calendar_id
def get_dav_eprop(self,cr,ns,prop):
return None
class Calendar(osv.osv):
_inherit = 'basic.calendar'
+2 -2
View File
@@ -30,8 +30,8 @@
'init_xml': ['delivery_data.xml'],
'update_xml': [
'security/ir.model.access.csv',
'delivery_view.xml',
'delivery_wizard.xml',
'wizard/delivery_sale_order_view.xml',
'delivery_view.xml',
'partner_view.xml'
],
'demo_xml': ['delivery_demo.xml'],
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard id="wizard_deliver_line_add" keyword="client_action_multi" model="sale.order" name="delivery.sale.order" string="Delivery Costs"/>
</data>
</openerp>
+81 -65
View File
@@ -20,77 +20,93 @@
##############################################################################
import time
import wizard
import ir
import pooler
from tools.translate import _
from tools.misc import UpdateableStr
from osv import osv, fields
delivery_form = UpdateableStr()
class make_delivery(osv.osv_memory):
_name = "delivery.sale.order"
_description = 'Make Delievery'
delivery_fields = {
'carrier_id' : {'string':'Delivery Method', 'type':'many2one', 'relation': 'delivery.carrier','required':True}
}
def _delivery_default(self, cr, uid, data, context):
order_obj = pooler.get_pool(cr.dbname).get('sale.order')
order = order_obj.browse(cr, uid, data['ids'])[0]
delivery_form.string="""<?xml version="1.0"?>
<form string="Create deliveries">
<separator colspan="4" string="Delivery Method" />
<field name="carrier_id" context="{'order_id': %d}"/>
</form>
""" % (data['id'],)
if not order.state in ('draft'):
raise wizard.except_wizard(_('Order not in draft state !'), _('The order state have to be draft to add delivery lines.'))
carrier_id = order.partner_id.property_delivery_carrier.id
return {'carrier_id': carrier_id}
def _delivery_set(self, cr, uid, data, context):
order_obj = pooler.get_pool(cr.dbname).get('sale.order')
line_obj = pooler.get_pool(cr.dbname).get('sale.order.line')
order_objs = order_obj.browse(cr, uid, data['ids'], context)
for order in order_objs:
grid_id = pooler.get_pool(cr.dbname).get('delivery.carrier').grid_get(cr, uid, [data['form']['carrier_id']],order.partner_shipping_id.id)
if not grid_id:
raise wizard.except_wizard(_('No grid avaible !'), _('No grid matching for this carrier !'))
grid_obj=pooler.get_pool(cr.dbname).get('delivery.grid')
grid = grid_obj.browse(cr, uid, [grid_id])[0]
taxes = grid.carrier_id.product_id.taxes_id
fpos = order.fiscal_position or False
taxes_ids = pooler.get_pool(cr.dbname).get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
line_obj.create(cr, uid, {
'order_id': order.id,
'name': grid.carrier_id.name,
'product_uom_qty': 1,
'product_uom': grid.carrier_id.product_id.uom_id.id,
'product_id': grid.carrier_id.product_id.id,
'price_unit': grid_obj.get_price(cr, uid, grid.id, order, time.strftime('%Y-%m-%d'), context),
'tax_id': [(6,0,taxes_ids)],
'type': 'make_to_stock'
})
return {}
class make_delivery(wizard.interface):
states = {
'init' : {
'actions' : [_delivery_default],
'result' : {'type' : 'form', 'arch' : delivery_form, 'fields' : delivery_fields, 'state' : [('end', 'Cancel', 'gtk-cancel'),('delivery', 'Add Delivery Costs', 'gtk-ok') ]}
},
'delivery' : {
'actions' : [_delivery_set],
'result' : {'type' : 'state', 'state' : 'end'}
},
_columns = {
'carrier_id': fields.many2one('delivery.carrier','Delivery Method', required=True),
}
make_delivery("delivery.sale.order")
def default_get(self, cr, uid, fields, context):
"""
@summary: 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.
"""
rec_id = context and context.get('active_id',False)
res = {}
order_obj = self.pool.get('sale.order')
order = order_obj.browse(cr, uid, rec_id)
if not order.state in ('draft'):
raise osv.except_osv(_('Order not in draft state !'), _('The order state have to be draft to add delivery lines.'))
carrier_id = order.partner_id.property_delivery_carrier.id
res['carrier_id'] = carrier_id
return res
def delivery_set(self, cr, uid, ids, context):
"""
@summary: Adds delivery costs to Sale Order Line.
@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:
"""
rec_ids = context and context.get('active_ids',[])
order_obj = self.pool.get('sale.order')
line_obj = self.pool.get('sale.order.line')
grid_obj = self.pool.get('delivery.grid')
carrier_obj = self.pool.get('delivery.carrier')
acc_fp_obj = self.pool.get('account.fiscal.position')
order_objs = order_obj.browse(cr, uid, rec_ids, context)
for datas in self.browse(cr, uid, ids):
for order in order_objs:
grid_id = carrier_obj.grid_get(cr, uid, [datas.carrier_id.id],order.partner_shipping_id.id)
if not grid_id:
raise osv.except_osv(_('No grid available !'), _('No grid matching for this carrier !'))
if not order.state in ('draft'):
raise osv.except_osv(_('Order not in draft state !'), _('The order state have to be draft to add delivery lines.'))
grid = grid_obj.browse(cr, uid, grid_id)
taxes = grid.carrier_id.product_id.taxes_id
fpos = order.fiscal_position or False
taxes_ids = acc_fp_obj.map_tax(cr, uid, fpos, taxes)
line_obj.create(cr, uid, {
'order_id': order.id,
'name': grid.carrier_id.name,
'product_uom_qty': 1,
'product_uom': grid.carrier_id.product_id.uom_id.id,
'product_id': grid.carrier_id.product_id.id,
'price_unit': grid_obj.get_price(cr, uid, grid.id, order, time.strftime('%Y-%m-%d'), context),
'tax_id': [(6,0,taxes_ids)],
'type': 'make_to_stock'
})
return {}
make_delivery()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Delivery Sale Order -->
<record id="view_make_delivery_wizard" model="ir.ui.view">
<field name="name">Delivery Costs</field>
<field name="model">delivery.sale.order</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Create Deliveries">
<separator colspan="4" string="Delivery Method" />
<field name="carrier_id"/>
<newline/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="delivery_set" string="Add Delivery Costs"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<act_window name="Delivery Costs"
res_model="delivery.sale.order"
src_model="sale.order"
view_mode="form"
target="new"
key2="client_action_multi"
id="act_delivery_cost"/>
</data>
</openerp>
-1
View File
@@ -21,7 +21,6 @@
import mrp
import installer
import mrp_wizard
import wizard
import report
import company
+5 -1
View File
@@ -60,8 +60,12 @@
'security/ir.model.access.csv',
'mrp_workflow.xml',
'mrp_data.xml',
'mrp_wizard_view.xml',
'wizard/mrp_product_produce_view.xml',
'wizard/make_procurement_view.xml',
'wizard/change_production_qty_view.xml',
'wizard/orderpoint_procurement_view.xml',
'mrp_view.xml',
'wizard/schedulers_all_view.xml',
'mrp_wizard.xml',
'mrp_report.xml',
'company_view.xml',
+31 -34
View File
@@ -188,7 +188,7 @@ class mrp_bom(osv.osv):
'revision_type': fields.selection([('numeric','numeric indices'),('alpha','alphabetical indices')], 'Index type'),
'child_ids': fields.function(_child_compute,relation='mrp.bom', method=True, string="BoM Hierarchy", type='many2many'),
'child_complete_ids': fields.function(_child_compute,relation='mrp.bom', method=True, string="BoM Hierarchy", type='many2many'),
'company_id': fields.many2one('res.company','Company',required=True),
'company_id': fields.many2one('res.company','Company',required=True),
}
_defaults = {
'active': lambda *a: 1,
@@ -196,7 +196,7 @@ class mrp_bom(osv.osv):
'product_qty': lambda *a: 1.0,
'product_rounding': lambda *a: 1.0,
'type': lambda *a: 'normal',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.bom', context=c)
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.bom', context=c),
}
_order = "sequence"
_sql_constraints = [
@@ -375,30 +375,7 @@ class one2many_domain(fields.one2many):
class mrp_production(osv.osv):
_name = 'mrp.production'
_description = 'Production'
_date_name = 'date_planned'
def _get_sale_order(self,cr,uid,ids,field_name=False):
move_obj=self.pool.get('stock.move')
def get_parent_move(move_id):
move = move_obj.browse(cr,uid,move_id)
if move.move_dest_id:
return get_parent_move(move.move_dest_id.id)
return move_id
productions=self.read(cr,uid,ids,['id','move_prod_id'])
res={}
for production in productions:
res[production['id']]=False
if production.get('move_prod_id',False):
parent_move_line=get_parent_move(production['move_prod_id'][0])
if parent_move_line:
move = move_obj.browse(cr,uid,parent_move_line)
#TODO: fix me sale module can not be used here,
#as may be mrp can be installed without sale module
if field_name=='name':
res[production['id']]=move.sale_line_id and move.sale_line_id.order_id.name or False
if field_name=='client_order_ref':
res[production['id']]=move.sale_line_id and move.sale_line_id.order_id.client_order_ref or False
return res
_date_name = 'date_planned'
def _production_calc(self, cr, uid, ids, prop, unknow_none, context={}):
result = {}
@@ -424,11 +401,12 @@ class mrp_production(osv.osv):
result[prod.id] = prod.date_planned[:10]
return result
def _sale_name_calc(self, cr, uid, ids, prop, unknow_none, unknow_dict):
return self._get_sale_order(cr,uid,ids,field_name='name')
def _sale_ref_calc(self, cr, uid, ids, prop, unknow_none, unknow_dict):
return self._get_sale_order(cr,uid,ids,field_name='client_order_ref')
def _ref_calc(self, cr, uid, ids, field_names=None, arg=False, context={}):
res = {}
for f in field_names:
for order_id in ids:
res[order_id] = {f:False}
return res
_columns = {
'name': fields.char('Reference', size=64, required=True),
@@ -470,8 +448,8 @@ class mrp_production(osv.osv):
'hour_total': fields.function(_production_calc, method=True, type='float', string='Total Hours', multi='workorder'),
'cycle_total': fields.function(_production_calc, method=True, type='float', string='Total Cycles', multi='workorder'),
'sale_name': fields.function(_sale_name_calc, method=True, type='char', string='Sale Name', help='Indicate the name of sale order.'),
'sale_ref': fields.function(_sale_ref_calc, method=True, type='char', string='Sale Reference', help='Indicate the Customer Reference from sale order.'),
'sale_name': fields.function(_ref_calc, method=True, multi='sale_name', type='char', string='Sale Name', help='Indicate the name of sale order.'),
'sale_ref': fields.function(_ref_calc, method=True, multi='sale_ref', type='char', string='Sale Reference', help='Indicate the Customer Reference from sale order.'),
'company_id': fields.many2one('res.company','Company',required=True),
}
_defaults = {
@@ -1385,13 +1363,32 @@ class StockMove(osv.osv):
def consume_moves(self, cr, uid, ids, product_qty, location_id=False, location_dest_id=False, consume=True, context=None):
res = []
production_obj = self.pool.get('mrp.production')
wf_service = netsvc.LocalService("workflow")
for move in self.browse(cr, uid, ids):
new_moves = super(StockMove, self).consume_moves(cr, uid, [move.id], product_qty, location_id, location_dest_id, consume, context=context)
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
for prod in production_obj.browse(cr, uid, production_ids, context=context):
if prod.state == 'confirmed':
production_obj.force_production(cr, uid, [prod.id])
wf_service.trg_validate(uid, 'mrp.production', prod.id, 'button_produce', cr)
for new_move in new_moves:
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new_move)]})
res.append(new_move)
return res
return res
def scrap_moves(self, cr, uid, ids, product_qty, location_id, context=None):
res = []
production_obj = self.pool.get('mrp.production')
wf_service = netsvc.LocalService("workflow")
for move in self.browse(cr, uid, ids):
new_moves = super(StockMove, self).scrap_moves(cr, uid, [move.id], product_qty, location_id, context=context)
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
for prod_id in production_ids:
wf_service.trg_validate(uid, 'mrp.production', prod_id, 'button_produce', cr)
for new_move in new_moves:
production_obj.write(cr, uid, production_ids, {'move_lines': [(4, new_move)]})
res.append(new_move)
return {}
StockMove()
+34 -65
View File
@@ -438,15 +438,7 @@
<field name="cycle_total" operator="+"/>
</graph>
</field>
</record>
<wizard
string="Change Product Qty."
model="mrp.production"
name="change_production_qty"
id="mrp.wizard_change_production_qty"
keyword="client_action_multi"
multi="True"/>
</record>
<record id="mrp_production_form_view" model="ir.ui.view">
<field name="name">mrp.production.form</field>
@@ -462,7 +454,9 @@
<field name="product_qty"/>
<group colspan="2" col="3">
<field name="product_uom"/>
<button type="action" name="%(mrp.wizard_change_production_qty)d" string="Change Qty" states="ready,confirmed,in_production"/>
<button type="action"
name="%(mrp.action_change_production_qty)d"
string="Change Qty" states="ready,confirmed" />
</group>
<label string="" colspan="2"/>
<field name="product_uos_qty" groups="product.group_uos"/>
@@ -484,35 +478,27 @@
mode="tree,form" height="275" domain="[('state','&lt;&gt;', ('done', 'cancel'))]">
<tree string="Products to Consume">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
<field name="state" invisible="1" />
<button
name="%(stock.move_consume)d"
string=">" type="action"
icon="gtk-go-forward" context="{'consume': True}"
states="draft,waiting,confirmed,assigned"/>
<button name="%(stock.move_scrap)d"
string="D" type="action"
icon="gtk-justify-fill" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
<field name="product_qty" string="Qty"/>
<field name="product_uom" string="UOM"/>
<button name="%(stock.move_consume)d"
string="Consume Products" type="action"
icon="gtk-go-forward" context="{'consume': True}"
states="draft,waiting,confirmed,assigned" />
<button name="%(stock.move_scrap)d"
string="Scrap Products" type="action"
icon="gtk-justify-fill" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
</tree>
<form string="Products to Consume">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
</form>
</field>
<field colspan="2" name="move_lines2" nolabel="1" domain="[('state','in', ('done', 'cancel'))]"
widget="one2many_list" mode="tree,form" height="275">
<tree string="Consumed Products" editable="bottom">
<tree string="Consumed Products" editable="bottom" colors="red:state=='cancel';black:state=='done';">
<field name="product_id" readonly="1"/>
<field name="product_qty" readonly="1"/>
<field name="product_uom" readonly="1" />
<field name="state" invisible="1" />
<field name="location_id" readonly="1"/>
<field name="prodlot_id" />
<field name="product_qty" readonly="1" string="Qty"/>
<field name="product_uom" readonly="1" string="UOM"/>
<field name="location_dest_id" readonly="1" string="Destination"/>
<field name="prodlot_id" />
<button
name="%(stock.track_line)d"
string="Split in production lots"
@@ -520,15 +506,11 @@
states="done,cancel" />
<button
name="%(stock.move_scrap)d"
string="D" type="action"
string="Scrap Products" type="action"
icon="gtk-convert"
states="done,cancel" />
states="done,cancel" />
</tree>
<form string="Consumed Products">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
</form>
</field>
<group col="9" colspan="4">
@@ -547,24 +529,17 @@
mode="tree,form" height="275" domain="[('state','&lt;&gt;', ('done', 'cancel'))]">
<tree string="Products to Finish">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
<field name="state" invisible="1" />
<button
name="%(stock.move_consume)d"
string=">" type="action"
icon="gtk-go-forward"
states="draft,waiting,confirmed,assigned"/>
<button name="%(stock.move_scrap)d"
string="D" type="action"
icon="gtk-justify-fill" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
<field name="product_qty" string="Qty"/>
<field name="product_uom" string="UOM"/>
<button name="%(stock.move_consume)d"
string="Consume Products" type="action"
icon="gtk-go-forward" context="{'consume': True}"
states="draft,waiting,confirmed,assigned" />
<button name="%(stock.move_scrap)d"
string="Scrap Products" type="action"
icon="gtk-justify-fill" context="{'scrap': True}"
states="draft,waiting,confirmed,assigned" />
</tree>
<form string="Products to Finish">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
</form>
</field>
<field colspan="2" name="move_created_ids2" nolabel="1" domain="[('state','in', ('done', 'cancel'))]"
@@ -572,21 +547,15 @@
<tree string="Finished Products" editable="bottom">
<field name="product_id" readonly="1"/>
<field name="product_qty" readonly="1"/>
<field name="product_uom" readonly="1" />
<field name="state" invisible="1" />
<field name="product_uom" readonly="1" />
<field name="location_id" readonly="1"/>
<field name="prodlot_id" />
<button name="%(stock.track_line)d"
string="Split in production lots" type="action" icon="gtk-justify-fill" states="done,cancel"/>
<button name="%(stock.move_scrap)d"
string="D" type="action" icon="gtk-go-forward"
string="Scrap Products" type="action" icon="gtk-go-forward"
states="done,cancel" />
</tree>
<form string="Finished Products">
<field name="product_id" />
<field name="product_qty" />
<field name="product_uom" />
</form>
</field>
</page>
<page string="Work Orders">
-18
View File
@@ -1,17 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard id="wiz_mrp_proc0" model="mrp.procurement" string="Compute Schedulers" name="mrp.procurement.compute.all"/>
<menuitem id="menu_mrp_scheduler" name="Schedulers" parent="base.menu_mrp_root" sequence="4"/>
<menuitem action="wiz_mrp_proc0" id="mrp_Sched_all" parent="mrp.menu_mrp_scheduler" type="wizard" sequence="90"/>
<!--
<menuitem action="wiz_mrp_proc1" id="menu_wiz_mrp_proc1" parent="mrp.mrp_Sched_all" type="wizard"/>
-->
<wizard id="wiz_mrp_proc2" model="mrp.procurement" string="Compute Stock Minimum Rules Only" name="mrp.procurement.orderpoint.compute"/>
<!--
<menuitem action="wiz_mrp_proc2" id="menu_wiz_mrp_proc2" parent="mrp.mrp_Sched_all" type="wizard"/>
-->
<wizard id="wizard_workcenter_load" model="mrp.workcenter" name="mrp.workcenter.load" string="Work Center load"/>
@@ -24,12 +13,5 @@
<field eval="True" name="object"/>
</record>
<wizard
string="Requisition Request"
model="product.product"
name="product.product.procurement"
keyword="client_action_multi"
id="product_procurement_wizard"/>
</data>
</openerp>
+2 -2
View File
@@ -195,9 +195,9 @@ class mrp_procurement(osv.osv):
qty = max(op.product_min_qty, op.product_max_qty)-prods
reste = qty % op.qty_multiple
if reste > 0:
qty += op.qty_multiple - reste
qty += op.qty_multiple - reste
newdate = DateTime.now() + DateTime.RelativeDateTime(
days=op.product_id.seller_delay)
days=int(op.product_id.seller_delay))
if op.product_id.supply_method == 'buy':
location_id = op.warehouse_id.lot_input_id
elif op.product_id.supply_method == 'produce':
+4
View File
@@ -32,3 +32,7 @@
"access_mrp_production_stock_worker","mrp.production stock_worker","model_mrp_production","stock.group_stock_user",1,0,0,0
"access_mrp_installer","mrp.installer","model_mrp_installer","mrp.group_mrp_user",1,0,0,0
"access_mrp_product_produce","mrp.product.produce","model_mrp_product_produce","mrp.group_mrp_user",1,0,0,0
"access_mrp_make_procurement","make.procurement","model_make_procurement","mrp.group_mrp_user",1,0,0,0
"access_mrp_change_production_qty","change.production.qty","model_change_production_qty","mrp.group_mrp_user",1,0,0,0
"access_mrp_procurement_compute_all","mrp.procurement.compute.all","model_mrp_procurement_compute_all","mrp.group_mrp_user",1,0,0,0
"access_mrp_procurement_orderpoint_compute","mrp.procurement.orderpoint.compute","model_mrp_procurement_orderpoint_compute","mrp.group_mrp_user",1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
32 access_mrp_production_stock_worker mrp.production stock_worker model_mrp_production stock.group_stock_user 1 0 0 0
33 access_mrp_installer mrp.installer model_mrp_installer mrp.group_mrp_user 1 0 0 0
34 access_mrp_product_produce mrp.product.produce model_mrp_product_produce mrp.group_mrp_user 1 0 0 0
35 access_mrp_make_procurement make.procurement model_make_procurement mrp.group_mrp_user 1 0 0 0
36 access_mrp_change_production_qty change.production.qty model_change_production_qty mrp.group_mrp_user 1 0 0 0
37 access_mrp_procurement_compute_all mrp.procurement.compute.all model_mrp_procurement_compute_all mrp.group_mrp_user 1 0 0 0
38 access_mrp_procurement_orderpoint_compute mrp.procurement.orderpoint.compute model_mrp_procurement_orderpoint_compute mrp.group_mrp_user 1 0 0 0
+5 -4
View File
@@ -19,14 +19,15 @@
#
##############################################################################
import wizard_orderpoint_procurement
import mrp_product_produce
import orderpoint_procurement
import wizard_procurement
import wizard_schedulers_all
import schedulers_all
import wizard_price
import wizard_workcenter_load
import wizard_track_prod
import wizard_change_production_qty
import make_procurement
import change_production_qty
import make_procurement_product
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+114
View File
@@ -0,0 +1,114 @@
# -*- 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/>.
#
##############################################################################
import time
import ir
from osv.osv import except_osv
from osv import fields, osv
import netsvc
from tools.translate import _
class change_production_qty(osv.osv_memory):
_name = 'change.production.qty'
_description = 'Change Quantity of Products'
_columns = {
'product_qty': fields.float('Product Qty', required=True),
}
def default_get(self, cr, uid, fields, context):
"""
@summary: 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 = {}
record_id = context and context.get('active_id',False)
if not record_id:
return res
prod_obj = self.pool.get('mrp.production')
prod = prod_obj.browse(cr, uid, record_id)
if prod.state in ('in_production','cancel', 'done'):
raise osv.except_osv(_('Warning !'), _('The production is in "%s" state. You can not change the production quantity anymore') % (prod.state).upper() )
res['product_qty'] = prod.product_qty
return res
def change_prod_qty(self, cr, uid, ids, context):
"""
@summary: Changes the Quantity of 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
@return:
"""
record_id = context and context.get('active_id',False)
assert record_id, _('Active Id is not found')
prod_obj = self.pool.get('mrp.production')
product_lines_obj = self.pool.get('mrp.production.product.line')
bom_obj = self.pool.get('mrp.bom')
for wiz_qty in self.browse(cr, uid, ids):
prod = prod_obj.browse(cr, uid,record_id)
prod_obj.write(cr, uid,prod.id, {'product_qty': wiz_qty.product_qty})
prod_obj.action_compute(cr, uid, [prod.id])
move_lines_obj = self.pool.get('stock.move')
for move in prod.move_lines:
bom_point = prod.bom_id
bom_id = prod.bom_id.id
if not bom_point:
bom_id = bom_obj._bom_find(cr, uid, prod.product_id.id, prod.product_uom.id)
if not bom_id:
raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product"))
prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id})
bom_point = sbom_obj.browse(cr, uid, [bom_id])[0]
if not bom_id:
raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product"))
factor = prod.product_qty * prod.product_uom.factor / bom_point.product_uom.factor
res = bom_obj._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, [])
for r in res[0]:
if r['product_id']== move.product_id.id:
move_lines_obj.write(cr, uid,move.id, {'product_qty' : r['product_qty']})
for m in prod.move_created_ids:
move_lines_obj.write(cr, uid,m.id, {'product_qty': wiz_qty.product_qty})
return {}
change_production_qty()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Change Product Quantity -->
<record id="view_change_production_qty_wizard" model="ir.ui.view">
<field name="name">Change Product Qty</field>
<field name="model">change.production.qty</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Change Product Qty">
<field name="product_qty"/>
<newline/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="change_prod_qty" string="Validate"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<record id="action_change_production_qty" model="ir.actions.act_window">
<field name="name">Change Product Qty</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">change.production.qty</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>
-102
View File
@@ -1,102 +0,0 @@
# -*- 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/>.
#
##############################################################################
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 Requisition">
<label string="Your procurement request has been sent !"/>
</form>"""
procurement_form = """<?xml version="1.0"?>
<form string="Internal Requisition Request">
<label string="This wizard will plan the procurement for this product. This procurement may generate task, production orders or purchase orders." align="0.0" colspan="4"/>
<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': 'Warehouse', '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:
@@ -0,0 +1,130 @@
# -*- 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/>.
#
##############################################################################
import netsvc
import time
from osv import fields, osv
class make_procurement(osv.osv_memory):
_name = 'make.procurement'
_description = 'Make Procurements'
def onchange_product_id(self, cr, uid, ids, prod_id):
"""
@summary: On Change of Product ID getting the value of related UoM.
@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 prod_id: Changed ID of Product
@return: A dictionary which gives the UoM of the changed Product
"""
product = self.pool.get('product.product').browse(cr, uid, prod_id)
return {'value': {'uom_id': product.uom_id.id}}
_columns = {
'qty': fields.float('Quantity', digits=(16,2), required=True),
'product_id': fields.many2one('product.product', 'Product', required=True, readonly=1),
'uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
'date_planned': fields.date('Planned Date', required=True),
}
_defaults = {
'date_planned': lambda *args: time.strftime('%Y-%m-%d'),
'qty': lambda *args: 1.0,
}
def make_procurement(self, cr, uid, ids, context=None):
"""
@summary: Creates procurement order for selected 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
@return: A dictionary which loads Procurement form view.
"""
user = self.pool.get('res.users').browse(cr, uid, uid, context).login
for proc in self.browse(cr, uid, ids):
wh = self.pool.get('stock.warehouse').browse(cr, uid, proc.warehouse_id.id, context)
procure_id = self.pool.get('mrp.procurement').create(cr, uid, {
'name':'INT: '+str(user),
'date_planned': proc.date_planned,
'product_id': proc.product_id.id,
'product_qty': proc.qty,
'product_uom': proc.uom_id.id,
'location_id': wh.lot_stock_id.id,
'procure_method':'make_to_order',
})
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'mrp.procurement', procure_id, 'button_confirm', cr)
data_obj = self.pool.get('ir.model.data')
id2 = data_obj._get_id(cr, uid, 'mrp', 'mrp_procurement_tree_view')
id3 = data_obj._get_id(cr, uid, 'mrp', 'mrp_procurement_form_view')
if id2:
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
if id3:
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
return {
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'mrp.procurement',
'res_id' : procure_id,
'views': [(id3,'form'),(id2,'tree')],
'type': 'ir.actions.act_window',
}
def default_get(self, cr, uid, fields, context=None):
"""
@summary: 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.
"""
record_id = context and context.get('active_id', False) or False
res = super(make_procurement, self).default_get(cr, uid, fields, context=context)
if record_id:
product_id = self.pool.get('product.product').browse(cr, uid, record_id, context=context).id
res['product_id'] = product_id
return res
make_procurement()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Make Procurement -->
<record id="view_make_procurment_wizard" model="ir.ui.view">
<field name="name">Requisition Request</field>
<field name="model">make.procurement</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Requisition Request">
<label string="This wizard will plan the procurement for this product. This procurement may generate task, production orders or purchase orders." colspan="4"/>
<field name="product_id" on_change="onchange_product_id(product_id)"/>
<field name="qty"/>
<field name="uom_id"/>
<field name="date_planned"/>
<field name="warehouse_id" colspan="4"/>
<newline/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="make_procurement" string="Ask New Products"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<act_window name="Requisition Request"
res_model="make.procurement"
src_model="product.product"
view_mode="form"
target="new"
key2="client_action_multi"
id="act_make_procurement"/>
</data>
</openerp>
@@ -0,0 +1,71 @@
# -*- 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/>.
#
##############################################################################
#
# Order Point Method:
# - Order if the virtual stock of today is bellow the min of the defined order point
#
import threading
from osv import fields,osv
class procurement_compute(osv.osv_memory):
_name = 'mrp.procurement.orderpoint.compute'
_description = 'Automatic Order Point'
_columns = {
'automatic': fields.boolean('Automatic Orderpoint', help='If the stock of a product is under 0, it will act like an orderpoint'),
}
_defaults = {
'automatic' : lambda *a: False,
}
def _procure_calculation_orderpoint(self, cr, uid, ids, context):
"""
@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
"""
proc_obj = self.pool.get('mrp.procurement')
for proc in self.browse(cr, uid, ids):
proc_obj._procure_orderpoint_confirm(cr, uid, automatic=proc.automatic, use_new_cursor=cr.dbname, context=context)
return {}
def procure_calculation(self, cr, uid, ids, context):
"""
@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
"""
threaded_calculation = threading.Thread(target=self._procure_calculation_orderpoint, args=(cr, uid, ids, context))
threaded_calculation.start()
return {}
procurement_compute()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Compute Stock Minimum Rules Only -->
<record id="view_procurement_compute_wizard" model="ir.ui.view">
<field name="name">Compute Stock Minimum Rules Only</field>
<field name="model">mrp.procurement.orderpoint.compute</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Parameters">
<field name="automatic"/>
<separator colspan="4"/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="procure_calculation" string="Compute Stock"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<act_window name="Compute Stock Minimum Rules Only"
res_model="mrp.procurement.orderpoint.compute"
src_model="mrp.procurement"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_procurement_compute"/>
</data>
</openerp>
+68
View File
@@ -0,0 +1,68 @@
# -*- 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/>.
#
##############################################################################
import threading
from osv import osv, fields
class procurement_compute(osv.osv_memory):
_name = 'mrp.procurement.compute.all'
_description = 'Compute all schedulers'
_columns = {
'automatic': fields.boolean('Automatic orderpoint',help='Triggers an automatic procurement for all products that have a virtual stock under 0. You should probably not use this option, we suggest using a MTO configuration on products.'),
}
_defaults ={
'automatic': lambda *a: False,
}
def _procure_calculation_all(self, cr, uid, ids, context):
"""
@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
"""
proc_obj = self.pool.get('mrp.procurement')
for proc in self.browse(cr, uid, ids):
proc_obj.run_scheduler(cr, uid, automatic=proc.automatic, use_new_cursor=cr.dbname,\
context=context)
return {}
def procure_calculation(self, cr, uid, ids, context):
"""
@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
"""
threaded_calculation = threading.Thread(target=self._procure_calculation_all, args=(cr, uid, ids, context))
threaded_calculation.start()
return {}
procurement_compute()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Compute Schedulers -->
<record id="view_compute_schedulers_wizard" model="ir.ui.view">
<field name="name">Compute Schedulers</field>
<field name="model">mrp.procurement.compute.all</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Scheduler Parameters">
<field name="automatic"/>
<separator colspan="4"/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="procure_calculation" string="Compute Schedulers"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<act_window name="Compute Schedulers"
res_model="mrp.procurement.compute.all"
src_model="mrp.procurement"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_compute_schedulers"/>
<menuitem id="menu_mrp_scheduler" name="Schedulers" parent="base.menu_mrp_root" sequence="4"/>
<menuitem action="action_compute_schedulers" id="mrp_Sched_all" parent="mrp.menu_mrp_scheduler" sequence="90"/>
</data>
</openerp>
@@ -1,117 +0,0 @@
# -*- 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/>.
#
##############################################################################
import time
import wizard
import ir
import pooler
from osv.osv import except_osv
from osv import fields,osv
import netsvc
from tools.translate import _
form1 = '''<?xml version="1.0"?>
<form string="Change Product Qty">
<field name="product_qty"/>
</form>'''
form1_fields={
'product_qty': {'string': 'Product Qty', 'type':'float', 'required':True},
}
def _get_qty(self,cr,uid, data, state):
prod_obj = pooler.get_pool(cr.dbname).get('mrp.production')
prod = prod_obj.browse(cr, uid,data['ids'])[0]
form1_fields['product_qty']['default']=prod.product_qty
return {}
def _get_states(self, cr, uid, data, context):
prod_obj = pooler.get_pool(cr.dbname).get('mrp.production')
prod = prod_obj.browse(cr, uid,data['ids'])[0]
if prod.state in ('cancel', 'done'):
raise wizard.except_wizard(_('Warning !'), _('The production is in "%s" state. You can not change the production quantity anymore') % (prod.state).upper() )
return 'end'
if prod.state in ('draft'):
#raise wizard.except_wizard('Warning !', 'The production is in "%s" state. You can change the production quantity directly...!!!' % (prod.state).upper() )
return 'end'
else:
return 'confirm'
def _change_prod_qty(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
prod_obj = pool.get('mrp.production')
prod = prod_obj.browse(cr, uid,data['ids'])[0]
prod_obj.write(cr, uid,prod.id, {'product_qty' : data['form']['product_qty']})
prod_obj.action_compute(cr, uid, [prod.id])
move_lines_obj = pool.get('stock.move')
for move in prod.move_lines:
bom_point = prod.bom_id
bom_id = prod.bom_id.id
if not bom_point:
bom_id = pool.get('mrp.bom')._bom_find(cr, uid, prod.product_id.id, prod.product_uom.id)
if not bom_id:
raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product"))
self.write(cr, uid, [prod.id], {'bom_id': bom_id})
bom_point = pool.get('mrp.bom').browse(cr, uid, [bom_id])[0]
if not bom_id:
raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product"))
factor = prod.product_qty * prod.product_uom.factor / bom_point.product_uom.factor
res = pool.get('mrp.bom')._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, [])
for r in res[0]:
if r['product_id']== move.product_id.id:
move_lines_obj.write(cr, uid,move.id, {'product_qty' : r['product_qty']})
product_lines_obj = pool.get('mrp.production.product.line')
for m in prod.move_created_ids:
move_lines_obj.write(cr, uid,m.id, {'product_qty' : data['form']['product_qty']})
return {}
class change_production_qty(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'choice', 'next_state' : _get_states}
},
'confirm' : {
'actions' : [_get_qty],
'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, 'state':[('end','Cancel'),('validate','Validate')]}
},
'validate': {
'actions': [],
'result': {'type':'action', 'action':_change_prod_qty, 'state':'end'}
},
'end' : {
'actions' : [],
'result': {'type': 'state', 'state': 'end'},
},
}
change_production_qty('change_production_qty')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,73 +0,0 @@
# -*- 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/>.
#
##############################################################################
#
# Order Point Method:
# - Order if the virtual stock of today is bellow the min of the defined order point
#
import wizard
import threading
import pooler
parameter_form = '''<?xml version="1.0"?>
<form string="Parameters" colspan="4">
<field name="automatic" />
</form>'''
parameter_fields = {
'automatic': {'string': 'Automatic orderpoint', 'type': 'boolean', 'help': 'If the stock of a product is under 0, it will act like an orderpoint', 'default': lambda *a: False},
}
def _procure_calculation_orderpoint(self, db_name, uid, data, context):
db, pool = pooler.get_db_and_pool(db_name)
cr = db.cursor()
try:
proc_obj = pool.get('mrp.procurement')
automatic = data['form']['automatic']
proc_obj._procure_orderpoint_confirm(cr, uid, automatic=automatic,\
use_new_cursor=cr.dbname, context=context)
finally:
cr.close()
return {}
def _procure_calculation(self, cr, uid, data, context):
threaded_calculation = threading.Thread(target=_procure_calculation_orderpoint, args=(self, cr.dbname, uid, data, context))
threaded_calculation.start()
return {}
class procurement_compute(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type': 'form', 'arch':parameter_form, 'fields': parameter_fields, 'state':[('end','Cancel'),('compute','Compute Stock')]}
},
'compute': {
'actions': [_procure_calculation],
'result': {'type': 'state', 'state':'end'}
},
}
procurement_compute('mrp.procurement.orderpoint.compute')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,64 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import threading
import pooler
parameter_form = '''<?xml version="1.0"?>
<form string="Scheduler Parameters" colspan="4">
<field name="automatic" />
</form>'''
parameter_fields = {
'automatic': {'string': 'Automatic orderpoint', 'type': 'boolean', 'help': 'Triggers an automatic procurement for all products that have a virtual stock under 0. You should probably not use this option, we suggest using a MTO configuration on products.', 'default': lambda *a: False},
}
def _procure_calculation_all(self, db_name, uid, data, context):
db, pool = pooler.get_db_and_pool(db_name)
cr = db.cursor()
proc_obj = pool.get('mrp.procurement')
automatic = data['form']['automatic']
proc_obj.run_scheduler(cr, uid, automatic=automatic, use_new_cursor=cr.dbname,\
context=context)
cr.close()
return {}
def _procure_calculation(self, cr, uid, data, context):
threaded_calculation = threading.Thread(target=_procure_calculation_all, args=(self, cr.dbname, uid, data, context))
threaded_calculation.start()
return {}
class procurement_compute(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type': 'form', 'arch':parameter_form, 'fields': parameter_fields, 'state':[('end','Cancel'),('compute','Compute Stock') ]}
},
'compute': {
'actions': [_procure_calculation],
'result': {'type': 'state', 'state':'end'}
},
}
procurement_compute('mrp.procurement.compute.all')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+4 -3
View File
@@ -37,11 +37,12 @@
'depends': ['base', 'sale', 'account'],
'update_xml': [
'security/ir.model.access.csv',
'mrp_repair_sequence.xml',
'mrp_repair_wizard.xml',
'mrp_repair_sequence.xml',
'wizard/mrp_repair_cancel_view.xml',
'wizard/mrp_repair_make_invoice_view.xml',
'mrp_repair_view.xml',
'mrp_repair_workflow.xml',
'mrp_repair_report.xml'
'mrp_repair_report.xml',
],
'demo_xml': [],
'installable': True,
+3 -3
View File
@@ -95,7 +95,7 @@ class mrp_repair(osv.osv):
\n* The \'To be Invoiced\' state is used to generate the invoice before or after repairing done. \
\n* The \'Done\' state is set when repairing is completed.\
\n* The \'Cancelled\' state is used when user cancel repair order.'),
'location_id': fields.many2one('stock.location', 'Current Location', required=True, select=True, readonly=True, states={'draft':[('readonly',False)]}),
'location_id': fields.many2one('stock.location', 'Current Location', select=True, readonly=True, states={'draft':[('readonly',False)]}),
'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, states={'draft':[('readonly',False)]}),
'move_id': fields.many2one('stock.move', 'Move',required=True, domain="[('product_id','=',product_id)]", readonly=True, states={'draft':[('readonly',False)]}),
'guarantee_limit': fields.date('Guarantee limit', help="The guarantee limit is computed as: last move date + warranty defined on selected product. If the current date is below the guarantee limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards."),
@@ -261,12 +261,12 @@ class mrp_repair(osv.osv):
def action_invoice_create(self, cr, uid, ids, group=False, context=None):
res={}
invoices_group = {}
for repair in self.browse(cr, uid, ids, context=context):
for repair in self.browse(cr, uid, ids, context=context):
res[repair.id]=False
if repair.state in ('draft','cancel') or repair.invoice_id:
continue
if not (repair.partner_id.id and repair.partner_invoice_id.id):
raise osv.except_osv(_('No partner !'),_('You have to select a partner in the repair form !'))
raise osv.except_osv(_('No partner !'),_('You have to select a Partner Invoice Address in the repair form !'))
comment=repair.quotation_notes
if (repair.invoice_method != 'none'):
if group and repair.partner_invoice_id.id in invoices_group:
-22
View File
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard
id="action_cancel_repair"
model="mrp.repair"
name="mrp.repair.cancel"
string="Cancel Repair"
menu = "False"
multi = "True"
/>
<wizard
id="wizard_mrp_repair_make_invoice"
keyword="client_action_multi"
model="mrp.repair"
name="mrp.repair.make_invoice"
multi="True"
string="Make invoices"/>
</data>
</openerp>
+2 -2
View File
@@ -19,7 +19,7 @@
#
##############################################################################
import wizard_cancel_repair
import wizard_make_invoice
import cancel_repair
import make_invoice
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+87
View File
@@ -0,0 +1,87 @@
# -*- 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/>.
#
##############################################################################
import netsvc
from osv import osv,fields
from tools.translate import _
class repair_cancel(osv.osv_memory):
_name = 'mrp.repair.cancel'
_description = 'Cancel Repair'
def cancel_repair(self, cr, uid, ids, context):
"""
@summary: Cancels the repair
@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:
"""
record_id = context and context.get('active_id', False) or False
assert record_id, _('Active ID is not Found')
repair_order_obj = self.pool.get('mrp.repair')
repair_line_obj = self.pool.get('mrp.repair.line')
repair_order = repair_order_obj.browse(cr, uid, record_id)
if repair_order.invoiced or repair_order.invoice_method == 'none':
repair_order_obj.action_cancel(cr, uid, [record_id], context=context)
else:
raise osv.except_osv(_('Warning!'),_('Repair is not cancelled. It is not invoiced.'))
return {}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
"""
@summary: 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
@return: New arch of view.
"""
record_id = context and context.get('order_id', False) or False
res = super(repair_cancel, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
if record_id:
repair_order = self.pool.get('mrp.repair').browse(cr, uid, record_id)
if not repair_order.invoiced:
res['arch'] = """ <form string="Cancel Repair" colspan="4">
<group col="2" colspan="2">
<label string="Do you want to continue?" colspan="4"/>
<separator colspan="4"/>
<button icon="gtk-cancel" special="cancel" string="No" readonly="0"/>
<button name="cancel_repair" string="Yes" type="object" icon="gtk-ok"/>
</group>
</form>
"""
return res
repair_cancel()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+64
View File
@@ -0,0 +1,64 @@
# -*- 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/>.
#
##############################################################################
import netsvc
from osv import osv, fields
class make_invoice(osv.osv_memory):
_name = 'mrp.repair.make_invoice'
_description = 'Make Invoice'
_columns = {
'group': fields.boolean('Group by partner invoice address'),
}
def make_invoices(self, cr, uid, ids, context):
"""
@summary: Generates invoice(s) of selected records.
@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: Loads the view of new invoice(s).
"""
inv = self.browse(cr, uid, ids[0])
order_obj = self.pool.get('mrp.repair')
newinv = order_obj.action_invoice_create(cr, uid, context['active_ids'], group=inv.group,context=context)
return {
'domain': [('id','in', newinv.values())],
'name': 'Invoices',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'view_id': False,
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window'
}
make_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Cancel Repair -->
<record id="view_cancel_repair" model="ir.ui.view">
<field name="name">Cancel Repair</field>
<field name="model">mrp.repair.cancel</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Cancel Repair Order">
<label string="This operation will cancel the Repair process, but will not cancel it's Invoice. Do you want to continue?" colspan="4"/>
<newline/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="No" />
<button name="cancel_repair" string="Yes"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<record id="action_cancel_repair" model="ir.actions.act_window">
<field name="name">Cancel Repair Order</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.repair.cancel</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'order_id':active_id}</field>
</record>
</data>
</openerp>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Make Invoice -->
<record id="view_make_invoice" model="ir.ui.view">
<field name="name">Make Invoice</field>
<field name="model">mrp.repair.make_invoice</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Create invoices">
<separator colspan="4" string="Do you really want to create the invoices ?" />
<field name="group"/>
<newline/>
<group col="2" colspan="4">
<button icon='gtk-cancel' special="cancel"
string="Cancel" />
<button name="make_invoices" string="Create Invoice"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<act_window name="Make Invoice"
res_model="mrp.repair.make_invoice"
src_model="mrp.repair"
view_mode="form"
target="new"
key2="client_action_multi"
id="act_mrp_repair_invoice"/>
</data>
</openerp>
@@ -1,81 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import netsvc
import pooler
cancel_form = """<?xml version="1.0"?>
<form string="Cancel Repair...??">
<label colspan="4" string="This operation will cancel the Repair process, but will not cancel it's Invoice.\nDo you want to continue?" />
</form>
"""
cancel_fields = {}
def check_state(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
repair_obj = pool.get('mrp.repair').browse(cr, uid, data['ids'])[0]
if repair_obj.invoice_id:
return 'display'
else:
pool.get('mrp.repair').write(cr,uid,data['ids'],{'state':'cancel'})
return 'end'
def _cancel_repair(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
repair_obj = pool.get('mrp.repair').browse(cr, uid, data['ids'])
pool.get('mrp.repair').write(cr,uid,data['ids'],{'state':'cancel'})
mrp_line_obj = pool.get('mrp.repair.line')
for line in repair_obj:
mrp_line_obj.write(cr, uid, [l.id for l in line.operations], {'state': 'cancel'})
return {}
class repair_cancel(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'choice', 'next_state' : check_state}
},
'display' : {
'actions' : [],
'result' : {'type' : 'form',
'arch' : cancel_form,
'fields' : cancel_fields,
'state' : [('end', 'No'),('yes', 'Yes') ]}
},
'yes' : {
'actions' : [],
'result' : {'type' : 'action',
'action' : _cancel_repair,
'state' : 'end'}
},
'end' : {
'actions' : [],
'result': {'type': 'state', 'state': 'end'},
},
}
repair_cancel("mrp.repair.cancel")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,81 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import netsvc
import pooler
invoice_form = """<?xml version="1.0"?>
<form string="Create invoices">
<separator colspan="4" string="Do you really want to create the invoices ?" />
<field name="group"/>
</form>
"""
invoice_fields = {
'group': {
'string': 'Group by partner invoice address',
'type':'boolean'
},
}
ack_form = """<?xml version="1.0"?>
<form string="Create invoices">
<separator string="Invoices created" />
</form>"""
ack_fields = {}
def _makeInvoices(self, cr, uid, data, context):
order_obj = pooler.get_pool(cr.dbname).get('mrp.repair')
newinv = order_obj.action_invoice_create(cr, uid, data['ids'],group=data['form']['group'],context=context)
return {
'domain': [('id','in', newinv.values())],
'name': 'Invoices',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'view_id': False,
'context': "{'type':'out_refund'}",
'type': 'ir.actions.act_window'
}
class make_invoice(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'form',
'arch' : invoice_form,
'fields' : invoice_fields,
'state' : [('end', 'Cancel'),('invoice', 'Create invoices') ]}
},
'invoice' : {
'actions' : [],
'result' : {'type' : 'action',
'action' : _makeInvoices,
'state' : 'end'}
},
}
make_invoice("mrp.repair.make_invoice")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+1
View File
@@ -43,6 +43,7 @@ Main features :
'security/ir.model.access.csv',
'pos_report.xml',
'pos_wizard.xml',
'wizard/pos_add_product.xml',
'pos_view.xml',
'pos_sequence.xml',
'posrule_data.xml',
+1 -1
View File
@@ -23,7 +23,6 @@
import wizard_pos_payment
import wizard_default_journal
import wizard_refund_order
import wizard_add_product
import wizard_confirm
import wizard_discount
import wizard_get_sale
@@ -39,5 +38,6 @@ import wizard_pos_sales_user_current_user
import wizard_pos_details
import wizard_open_statement
import wizard_all_closed_cashbox_of_the_day
import pos_add_product
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,67 @@
# -*- 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/>.
#
##############################################################################
import netsvc
from osv import osv,fields
from tools.translate import _
class add_product(osv.osv_memory):
_name = 'pos.add.product'
_description = 'Add Product'
_columns = {
'product_id': fields.many2one('product.product', 'Product',required=True),
'quantity': fields.float('Quantity ', required=True),
}
_defaults = {
'quantity': lambda *a: 1,
}
def select_product(self, cr, uid, ids, context):
"""
@summary: To get the product and quantity and add in order .
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param context: A standard dictionary
@return : Retrun the add product form again for addin more product
"""
this = self.browse(cr, uid, ids[0], context=context)
record_id = context and context.get('active_id',False)
assert record_id, _('Active ID is not found')
if record_id:
order_obj = self.pool.get('pos.order')
order_obj.add_product(cr, uid, record_id, this.product_id.id,this.quantity,context=context)
return {
'name': _('Add Product'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'pos.add.product',
'view_id': False,
'target':'new',
'views': False,
'type': 'ir.actions.act_window',
}
add_product()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Add Product -->
<record id="view_add_product" model="ir.ui.view">
<field name="name">Add Product</field>
<field name="model">pos.add.product</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Add product :">
<group col="2" colspan="4">
<field name="product_id"/>
<field name="quantity"/>
<button icon='gtk-cancel' special="cancel"
string="Close" />
<button name="select_product" string="Contiue"
colspan="1" type="object" icon="gtk-ok" />
</group>
</form>
</field>
</record>
<record id="action_add_product" model="ir.actions.act_window">
<field name="name">Add Product</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.add.product</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>
@@ -1,88 +0,0 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# 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 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import pooler
import wizard
_form = """<?xml version="1.0"?>
<form string="Add product :">
<field name="product"/>
<field name="quantity"/>
</form>
"""
_fields = {
'product': {
'string': 'Product',
'type': 'many2one',
'relation': 'product.product',
'required': True,
'default': False
},
'quantity': {
'string': 'Quantity',
'type': 'integer',
'required': True,
'default': 1},
}
def _add(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
order_obj = pool.get('pos.order')
order_obj.add_product(cr, uid, data['id'], data['form']['product'],
data['form']['quantity'], context=context)
return {}
def _pre_init(self, cr, uid, data, context):
return {'product': False, 'quantity': 1}
class add_product(wizard.interface):
states = {
'init': {
'actions': [_pre_init],
'result': {
'type': 'form',
'arch': _form,
'fields': _fields,
'state': [('end', 'Cancel'), ('add', '_Add product', 'gtk-ok', True)
]
}
},
'add': {
'actions': [_add],
'result': {
'type': 'state',
'state': 'init',
}
},
}
add_product('pos.add_product')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+1 -1
View File
@@ -31,7 +31,7 @@ the report has several options to help you get the data you need.
""",
'author': 'Tiny',
'depends': ['base', 'product', 'account'],
'update_xml': ['product_margin_view.xml'],
'update_xml': ['wizard/product_margin_view.xml','product_margin_view.xml'],
'demo_xml': [],
'installable': True,
'active': False,
@@ -1,15 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard id="action_open_margin" menu="False" model="product.product" name="product.margins" string="Product Margins"/>
<!-- <menuitem id="menu_product_reporting"-->
<!-- name="Reporting" parent ="product.menu_main_product"-->
<!-- groups="product.group_product_manager"/>-->
<!---->
<!-- <menuitem icon="STOCK_JUSTIFY_FILL" action="action_open_margin" id="menu_action_product_margin" type="wizard" sequence="5" parent="menu_product_reporting" />-->
<menuitem id="base.next_id_64" name="Reporting" parent="base.menu_base_partner" sequence="8"/>
<menuitem
action="product_margin_action"
id="menu_mrp_property_action"
parent="base.next_id_64" />
<record model="ir.ui.view" id="view_product_margin_graph">
<field name="name">product.margin.graph</field>
<field name="model">product.product</field>
+1 -1
View File
@@ -19,7 +19,7 @@
#
##############################################################################
import wizard_product_margin
import product_margin
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,98 @@
# -*- 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/>.
#
##############################################################################
import time
from osv import osv
from osv import fields
import netsvc
import time
from tools.translate import _
class product_margin(osv.osv_memory):
'''
Product Margin
'''
_name = 'product.margin'
_description = 'Product Margin'
def action_open_window(self, cr, uid, ids, context):
"""
@summary:
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: the account ID or list of IDs if we want more than one
@return:
"""
mod_obj = self.pool.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'product', 'product_search_form_view')
id = mod_obj.read(cr, uid, result, ['res_id'])
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.graph', 'graph'))
view_res3 = cr.fetchone()[0]
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.form.inherit', 'form'))
view_res2 = cr.fetchone()[0]
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.tree', 'tree'))
view_res = cr.fetchone()[0]
#get the current product.margin object to obtain the values from it
product_margin_obj = self.browse(cr,uid,ids)[0]
return {
'name': _('Product Margins'),
'context':{'date_from':product_margin_obj.from_date,'date_to':product_margin_obj.to_date,'invoice_state' : product_margin_obj.invoice_state},
'view_type': 'form',
"view_mode": 'tree,form,graph',
'res_model':'product.product',
'type': 'ir.actions.act_window',
'views': [(view_res,'tree'), (view_res2,'form'), (view_res3,'graph')],
'view_id': False,
'search_view_id': id['res_id']
}
def action_cancel(self, cr, uid, ids, context=None):
"""
@summary:
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: the account ID or list of IDs if we want more than one
@return:
"""
return {'type':'ir.actions.act_window_close'}
_columns = {
#TODO : import time required to get currect date
'from_date': fields.date('From'),
#TODO : import time required to get currect date
'to_date': fields.date('To'),
'invoice_state':fields.selection([
('paid','Paid'),
('open_paid','Open and Paid'),
('draft_open_paid','Draft, Open and Paid'),
],'Invoice State', select=True, required=True),
}
_defaults = {
'from_date': lambda *a:time.strftime('%Y-01-01'),
'to_date': lambda *a:time.strftime('%Y-01-01'),
'invoice_state': lambda *a:"open_paid",
}
product_margin()
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="product_margin_form_view" model="ir.ui.view">
<field name="name">product.margin.form</field>
<field name="model">product.margin</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Properties categories">
<separator colspan="4" string="General Information"/>
<field name="from_date" />
<field name="to_date" />
<field name="invoice_state" />
<group col="4" colspan="2">
<button special="cancel" string="Cancel" type="object"/>
<button name="action_open_window" string="Open Margins" type="object"/>
</group>
</form>
</field>
</record>
<record id="product_margin_action" model="ir.actions.act_window">
<field name="name">Product Margine</field>
<field name="type">ir.actions.act_window</field>
<field name="target">new</field>
<field name="res_model">product.margin</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="product_margin_form_view"/>
</record>
</data>
</openerp>
@@ -1,93 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import pooler
import time
from tools.translate import _
def _action_open_window(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
mod_obj = pool.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'product', 'product_search_form_view')
id = mod_obj.read(cr, uid, result, ['res_id'])
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.graph', 'graph'))
view_res3 = cr.fetchone()[0]
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.form.inherit', 'form'))
view_res2 = cr.fetchone()[0]
cr.execute('select id,name from ir_ui_view where name=%s and type=%s', ('product.margin.tree', 'tree'))
view_res = cr.fetchone()[0]
return {
'name': _('Product Margins'),
'context':{'date_from':data['form']['from_date'],'date_to':data['form']['to_date'],'invoice_state' : data['form']['invoice_state']},
'view_type': 'form',
"view_mode": 'tree,form,graph',
'res_model':'product.product',
'type': 'ir.actions.act_window',
'views': [(view_res,'tree'), (view_res2,'form'), (view_res3,'graph')],
'view_id': False,
'search_view_id': id['res_id']
}
class product_margins(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="View Stock of Products">
<separator string="Select " colspan="4"/>
<field name="from_date"/>
<field name="to_date"/>
<field name="invoice_state"/>
</form>'''
form1_fields = {
'from_date': {
'string': 'From',
'type': 'date',
'default': lambda *a:time.strftime('%Y-01-01'),
},
'to_date': {
'string': 'To',
'type': 'date',
'default': lambda *a:time.strftime('%Y-12-31'),
},
'invoice_state': {
'string': 'Invoice State',
'type': 'selection',
'selection': [('paid','Paid'),('open_paid','Open and Paid'),('draft_open_paid','Draft, Open and Paid'),],
'required': True,
'default': lambda *a:"open_paid",
},
}
states = {
'init': {
'actions': [],
'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, 'state': [('end', 'Cancel','gtk-cancel'),('open', 'Open Margins','gtk-ok')]}
},
'open': {
'actions': [],
'result': {'type': 'action', 'action': _action_open_window, 'state':'end'}
}
}
product_margins('product.margins')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+4 -4
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/>.
#
##############################################################################
@@ -45,16 +45,16 @@
'depends': ['product', 'stock', 'mrp', 'process'],
'init_xml': [],
'update_xml': [
'wizard/sale_make_invoice_advance.xml',
'wizard/sale_line_invoice.xml',
'security/sale_security.xml',
'security/ir.model.access.csv',
'sale_workflow.xml',
'sale_sequence.xml',
'sale_data.xml',
'sale_wizard.xml',
'sale_view.xml',
'sale_report_view.xml',
'sale_report.xml',
'sale_wizard.xml',
'stock_view.xml',
'report_sale_view.xml',
'process/sale_process.xml',
+14 -3
View File
@@ -149,7 +149,12 @@
<field name="state" select="2"/>
<group col="3" colspan="2">
<field name="invoiced" select="2"/>
<button colspan="1" name="%(wizard_sale_order_line_invoice)d" states="confirmed" string="Make Invoice" type="action" icon="gtk-print"/>
<button colspan="1"
name="%(action_view_sale_order_line_make_invoice)d"
states="confirmed"
string="Make Invoice"
type="action"
icon="gtk-print" />
</group>
</page>
<page groups="base.group_extended" string="Extra Info">
@@ -379,8 +384,14 @@
<separator colspan="4" string="States"/>
<field name="state" select="2"/>
<group col="2" colspan="2">
<button name="button_done" states="confirmed,exception" string="Done" type="object" icon="gtk-jump-to"/>
<button name="button_cancel" states="confirmed,exception" string="Cancel" type="object" icon="gtk-cancel" />
<button name="button_done"
states="confirmed,exception"
string="Done" type="object"
icon="gtk-jump-to" />
<button name="button_cancel"
states="confirmed,exception"
string="Cancel" type="object"
icon="gtk-cancel" />
</group>
</page>
<page string="Properties">
-28
View File
@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard
id="wizard_sale_order_make_invoice"
keyword="client_action_multi"
model="sale.order"
name="sale.order.make_invoice"
multi="True"
string="Make invoices"/>
<wizard
id="wizard_sale_order_line_invoice"
keyword="client_action_multi"
model="sale.order.line"
name="sale.order.line.make_invoice"
multi="True"
string="Make invoices"/>
<wizard string="Advance Invoice"
model="sale.order"
name="sale.advance_payment_inv"
id="sale.advance_payment"
menu="True"/>
</data>
</openerp>
+5 -6
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,13 +15,12 @@
# 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 make_invoice import make_invoice
#remaining make_invoice
import sale_line_invoice
import sale_make_invoice_advance
import wizard_sale_line_invoice
import make_invoice_advance
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-157
View File
@@ -1,157 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import pooler
from osv import fields, osv
from tools.translate import _
form = """<?xml version="1.0"?>
<form string="Advance Payment">
<field name="product_id"/>
<newline />
<field name="qtty"/>
<field name="amount"/>
<newline />
</form>
"""
fields = {
'product_id': {'string':'Product', 'type':'many2one','relation':'product.product','required':True},
'amount': {'string':'Unit Price', 'type':'float', 'size':(16,2),'required':True},
'qtty': {'string':'Quantity', 'type':'float', 'size':(16,2),'required':True, 'default': lambda *a: 1},
}
form_msg = """<?xml version="1.0"?>
<form string="Invoices">
<label string="You invoice has been successfully created !"/>
</form>
"""
fields_msg = {}
def _createInvoices(self, cr, uid, data, context={}):
list_inv = []
pool_obj = pooler.get_pool(cr.dbname)
obj_sale = pool_obj.get('sale.order')
data_sale = obj_sale.browse(cr,uid,data['ids'])
obj_lines = pool_obj.get('account.invoice.line')
for sale in data_sale:
address_contact = False
address_invoice = False
create_ids = []
ids_inv = []
if sale.order_policy == 'postpaid':
raise osv.except_osv(
_('Error'),
_("You cannot make an advance on a sale order that is defined as 'Automatic Invoice after delivery'."))
val = obj_lines.product_id_change(cr, uid, [], data['form']['product_id'],uom = False, partner_id = sale.partner_id.id, fposition_id=sale.fiscal_position.id)
line_id =obj_lines.create(cr, uid, {
'name': val['value']['name'],
'account_id':val['value']['account_id'],
'price_unit': data['form']['amount'],
'quantity': data['form']['qtty'],
'discount': False,
'uos_id': val['value']['uos_id'],
'product_id':data['form']['product_id'],
'invoice_line_tax_id': [(6,0,val['value']['invoice_line_tax_id'])],
'account_analytic_id': sale.project_id and sale.project_id.id or False,
'note':'',
})
create_ids.append(line_id)
inv = {
'name': sale.name,
'origin': sale.name,
'type': 'out_invoice',
'reference': False,
'account_id': sale.partner_id.property_account_receivable.id,
'partner_id': sale.partner_id.id,
'address_invoice_id':sale.partner_invoice_id.id,
'address_contact_id':sale.partner_order_id.id,
'invoice_line': [(6,0,create_ids)],
'currency_id' :sale.pricelist_id.currency_id.id,
'comment': '',
'payment_term':sale.payment_term.id,
'fiscal_position': sale.partner_id.property_account_position.id
}
inv_obj = pool_obj.get('account.invoice')
inv_id = inv_obj.create(cr, uid, inv)
for inv in sale.invoice_ids:
ids_inv.append(inv.id)
ids_inv.append(inv_id)
obj_sale.write(cr,uid,sale.id,{'invoice_ids':[(6,0,ids_inv)]})
list_inv.append(inv_id)
#
# If invoice on picking: add the cost on the SO
# If not, the advance will be deduced when generating the final invoice
#
if sale.order_policy=='picking':
pool_obj.get('sale.order.line').create(cr, uid, {
'order_id': sale.id,
'name': val['value']['name'],
'price_unit': -data['form']['amount'],
'product_uom_qty': data['form']['qtty'],
'product_uos_qty': data['form']['qtty'],
'product_uos': val['value']['uos_id'],
'product_uom': val['value']['uos_id'],
'product_id':data['form']['product_id'],
'discount': False,
'tax_id': [(6,0,val['value']['invoice_line_tax_id'])],
}, context)
return {'invoice_ids':list_inv}
class sale_advance_payment(wizard.interface):
def _open_invoice(self, cr, uid, data, context):
pool_obj = pooler.get_pool(cr.dbname)
mod_obj = pool_obj.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'account', 'view_account_invoice_filter')
id = mod_obj.read(cr, uid, result, ['res_id'])
model_data_ids = pool_obj.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','invoice_form')])
resource_id = pool_obj.get('ir.model.data').read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
return {
'domain': "[('id','in', ["+','.join(map(str,data['form']['invoice_ids']))+"])]",
'name': 'Invoices',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'views': [(False,'tree'),(resource_id,'form')],
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
'search_view_id': id['res_id']
}
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'form' , 'arch' : form,'fields' : fields,'state' : [('end','Cancel','gtk-cancel'),('create','Create Advance Invoice','gtk-ok')]}
},
'create': {
'actions': [_createInvoices],
'result': {'type' : 'form' ,'arch' : form_msg,'fields' : fields_msg, 'state':[('end','Close','gtk-close'),('open','Open Advance Invoice','gtk-open')]}
},
'open': {
'actions': [],
'result': {'type':'action', 'action':_open_invoice, 'state':'end'}
}
}
sale_advance_payment("sale.advance_payment_inv")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+100
View File
@@ -0,0 +1,100 @@
# -*- 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 service import web_services
import wizard
import netsvc
import ir
import pooler
class sale_order_line_make_invoice(osv.osv_memory):
_name = "sale.order.line.make.invoice"
_description = "Sale OrderLine Make_invoice"
_columns = {
'grouped': fields.boolean('Group the invoices'),
}
_default = {
'grouped' : lambda *a: False
}
def makeInvoices(self, cr, uid, ids, context):
res = False
invoices = {}
#TODO: merge with sale.py/make_invoice
def make_invoice(order, lines):
a = order.partner_id.property_account_receivable.id
if order.partner_id and order.partner_id.property_payment_term.id:
pay_term = order.partner_id.property_payment_term.id
else:
pay_term = False
inv = {
'name': order.name,
'origin': order.name,
'type': 'out_invoice',
'reference': "P%dSO%d" % (order.partner_id.id, order.id),
'account_id': a,
'partner_id': order.partner_id.id,
'address_invoice_id': order.partner_invoice_id.id,
'address_contact_id': order.partner_invoice_id.id,
'invoice_line': [(6,0,lines)],
'currency_id' : order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': pay_term,
'fiscal_position': order.partner_id.property_account_position.id
}
inv_id = self.pool.get('account.invoice').create(cr, uid, inv)
return inv_id
for line in self.pool.get('sale.order.line').browse(cr,uid,context['active_ids']):
if (not line.invoiced) and (line.state not in ('draft','cancel')):
if not line.order_id.id in invoices:
invoices[line.order_id.id] = []
line_id = self.pool.get('sale.order.line').invoice_line_create(cr, uid,
[line.id])
for lid in line_id:
invoices[line.order_id.id].append((line, lid))
self.pool.get('sale.order.line').write(cr, uid, [line.id],
{'invoiced': True})
flag = True
data_sale = self.pool.get('sale.order').browse(cr,uid,line.order_id.id)
for line in data_sale.order_line:
if not line.invoiced:
flag = False
break
if flag:
wf_service = netsvc.LocalService('workflow')
wf_service.trg_validate(uid, 'sale.order', line.order_id.id, 'all_lines', cr)
self.pool.get('sale.order').write(cr,uid,[line.order_id.id],{'state' : 'progress'})
for result in invoices.values():
order = result[0][0].order_id
il = map(lambda x: x[1], result)
res = make_invoice(order, il)
cr.execute('INSERT INTO sale_order_invoice_rel \
(order_id,invoice_id) values (%s,%s)', (order.id, res))
return {}
sale_order_line_make_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_sale_order_line_make_invoice" model="ir.ui.view">
<field name="name">Sale OrderLine Make Invoice</field>
<field name="model">sale.order.line.make.invoice</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Create invoices">
<separator colspan="4" string="Do you really want to create the invoices ?" />
<field name="grouped" />
<separator string="" colspan="6" />
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
<button name="makeInvoices" string="Create Invoices" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Make Invoices"
res_model="sale.order.line.make.invoice"
src_model="sale.order.line"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_view_sale_order_line_make_invoice"/>
</data>
</openerp>
@@ -0,0 +1,154 @@
##############################################################################
#
# 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 service import web_services
from tools.translate import _
import ir
import netsvc
import pooler
import wizard
class sale_advance_payment_inv(osv.osv_memory):
_name = "sale.advance.payment.inv"
_description = "Sale Advance Payment Invoice"
_columns = {
'product_id': fields.many2one('product.product', 'Product', required=True),
'amount': fields.float('Unit Price', size=(16, 2), required=True),
'qtty': fields.float('Quantity', size=(16, 2), required=True),
}
_default = {
'qtty' : lambda *a: 1
}
def createInvoices(self, cr, uid, ids, context={}):
list_inv = []
obj_sale = self.pool.get('sale.order')
obj_lines = self.pool.get('account.invoice.line')
for sale_adv_obj in self.browse(cr, uid, ids):
for sale in obj_sale.browse(cr, uid, context['active_ids']):
address_contact = False
address_invoice = False
create_ids = []
ids_inv = []
if sale.order_policy == 'postpaid':
raise osv.except_osv(
_('Error'),
_("You cannot make an advance on a sale order \
that is defined as 'Automatic Invoice after delivery'."))
val = obj_lines.product_id_change(cr, uid, [], sale_adv_obj.product_id.id,
uom = False, partner_id = sale.partner_id.id, fposition_id=sale.fiscal_position.id)
line_id =obj_lines.create(cr, uid, {
'name': val['value']['name'],
'account_id': val['value']['account_id'],
'price_unit': sale_adv_obj.amount,
'quantity': sale_adv_obj.qtty,
'discount': False,
'uos_id': val['value']['uos_id'],
'product_id': sale_adv_obj.product_id.id,
'invoice_line_tax_id': [(6, 0, val['value']['invoice_line_tax_id'])],
'account_analytic_id': sale.project_id.id or False,
#'note':'',
})
create_ids.append(line_id)
inv = {
'name': sale.name,
'origin': sale.name,
'type': 'out_invoice',
'reference': False,
'account_id': sale.partner_id.property_account_receivable.id,
'partner_id': sale.partner_id.id,
'address_invoice_id':sale.partner_invoice_id.id,
'address_contact_id':sale.partner_order_id.id,
'invoice_line': [(6, 0, create_ids)],
'currency_id' :sale.pricelist_id.currency_id.id,
'comment': '',
'payment_term':sale.payment_term.id,
'fiscal_position': sale.partner_id.property_account_position.id
}
inv_obj = self.pool.get('account.invoice')
inv_id = inv_obj.create(cr, uid, inv)
for inv in sale.invoice_ids:
ids_inv.append(inv.id)
ids_inv.append(inv_id)
obj_sale.write(cr, uid, sale.id, {'invoice_ids':[(6, 0, ids_inv)]})
list_inv.append(inv_id)
#
# If invoice on picking: add the cost on the SO
# If not, the advance will be deduced when generating the final invoice
#
if sale.order_policy=='picking':
self.pool.get('sale.order.line').create(cr, uid, {
'order_id': sale.id,
'name': val['value']['name'],
'price_unit': -sale_adv_obj.amount,
'product_uom_qty': sale_adv_obj.qtty,
'product_uos_qty': sale_adv_obj.qtty,
'product_uos': val['value']['uos_id'],
'product_uom': val['value']['uos_id'],
'product_id': sale_adv_obj.product_id.id,
'discount': False,
'tax_id': [(6, 0, val['value']['invoice_line_tax_id'])],
}, context)
return {#'invoice_ids':list_inv,
'name': 'Open Invoice',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'sale.open.invoice',
'type': 'ir.actions.act_window',
'target': 'new',
'context': "{'invoice_ids'=%s}" % (list_inv)
}
sale_advance_payment_inv()
class sale_open_invoice(osv.osv_memory):
_name = "sale.open.invoice"
_description = "Sale Open Invoice"
_columns = {
}
def open_invoice(self, cr, uid, ids, context):
mod_obj = self.pool.get('ir.model.data')
invoices = []
#TODO: Can not get invoice ids here
for advance_pay in self.browse(cr, uid, ids):
result = mod_obj._get_id(cr, uid, 'account', 'view_account_invoice_filter')
id = mod_obj.read(cr, uid, result, ['res_id'])
model_data_ids = self.pool.get('ir.model.data').search(cr, uid,
[('model', '=', 'ir.ui.view'), ('name', '=', 'invoice_form')])
resource_id = self.pool.get('ir.model.data').read(cr, uid, model_data_ids,
fields=['res_id'])[0]['res_id']
return {
# 'domain': "[('id','in', ["+','.join(map(str, invoices))+"])]", # TODO
'name': 'Invoices',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'views': [(False, 'tree'), (resource_id, 'form')],
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
'search_view_id': id['res_id']
}
sale_open_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_sale_advance_payment_inv" model="ir.ui.view">
<field name="name">Sale Advance Payment Invoive</field>
<field name="model">sale.advance.payment.inv</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Advance Payment">
<field name="product_id"/>
<newline />
<field name="qtty"/>
<field name="amount"/>
<newline />
<separator string="" colspan="4"/>
<label string="" colspan="2" />
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
<button name="createInvoices" string="Create Advance Invoice" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Advance Invoice"
res_model="sale.advance.payment.inv"
src_model="sale.order"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_view_sale_advance_payment_inv"/>
<record id="view_sale_open_invoice" model="ir.ui.view">
<field name="name">Open Invoice</field>
<field name="model">sale.open.invoice</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Invoices">
<label string="You invoice has been successfully created!" />
<newline />
<separator string="" colspan="4"/>
<group colspan="4">
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
<button name="open_invoice" string="Open Invoice" type="object" icon="gtk-open"/>
</group>
</form>
</field>
</record>
<record id="action_view_sale_open_invoice" model="ir.actions.act_window">
<field name="name">Open Invoice</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sale.open.invoice</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>
@@ -1,121 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import netsvc
import ir
import pooler
invoice_form = """<?xml version="1.0"?>
<form string="Create invoices">
<separator colspan="4" string="Do you really want to create the invoices ?" />
<field name="grouped" />
</form>
"""
invoice_fields = {
'grouped' : {'string':'Group the invoices', 'type':'boolean', 'default': lambda *a: False}
}
def _makeInvoices(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
res = False
invoices = {}
#TODO: merge with sale.py/make_invoice
def make_invoice(order, lines):
a = order.partner_id.property_account_receivable.id
if order.partner_id and order.partner_id.property_payment_term.id:
pay_term = order.partner_id.property_payment_term.id
else:
pay_term = False
inv = {
'name': order.name,
'origin': order.name,
'type': 'out_invoice',
'reference': "P%dSO%d" % (order.partner_id.id, order.id),
'account_id': a,
'partner_id': order.partner_id.id,
'address_invoice_id': order.partner_invoice_id.id,
'address_contact_id': order.partner_invoice_id.id,
'invoice_line': [(6,0,lines)],
'currency_id' : order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': pay_term,
'fiscal_position': order.partner_id.property_account_position.id
}
inv_id = pool.get('account.invoice').create(cr, uid, inv)
return inv_id
for line in pool.get('sale.order.line').browse(cr,uid,data['ids']):
if (not line.invoiced) and (line.state not in ('draft','cancel')):
if not line.order_id.id in invoices:
invoices[line.order_id.id] = []
line_id = pool.get('sale.order.line').invoice_line_create(cr, uid,
[line.id])
for lid in line_id:
invoices[line.order_id.id].append((line, lid))
pool.get('sale.order.line').write(cr, uid, [line.id],
{'invoiced': True})
flag = True
data_sale = pool.get('sale.order').browse(cr,uid,line.order_id.id)
for line in data_sale.order_line:
if not line.invoiced:
flag = False
break
if flag:
wf_service = netsvc.LocalService('workflow')
wf_service.trg_validate(uid, 'sale.order', line.order_id.id, 'all_lines', cr)
pool.get('sale.order').write(cr,uid,[line.order_id.id],{'state' : 'progress'})
for result in invoices.values():
order = result[0][0].order_id
il = map(lambda x: x[1], result)
res = make_invoice(order, il)
cr.execute('INSERT INTO sale_order_invoice_rel \
(order_id,invoice_id) values (%s,%s)', (order.id, res))
return {}
class line_make_invoice(wizard.interface):
states = {
'init' : {
'actions': [],
'result': {
'type': 'form',
'arch': invoice_form,
'fields': invoice_fields,
'state': [
('end', 'Cancel'),
('invoice', 'Create invoices')
]
}
},
'invoice' : {
'actions' : [_makeInvoices],
'result' : {'type': 'state', 'state': 'end'}
},
}
line_make_invoice("sale.order.line.make_invoice")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+2 -3
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/>.
#
##############################################################################
@@ -27,7 +27,6 @@ import report
import wizard
import report_stock
import stock_wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+8 -3
View File
@@ -41,11 +41,16 @@ Thanks to the double entry management, the inventory controlling is powerful and
"init_xml" : [],
"demo_xml" : ["stock_demo.xml"],
"update_xml" : [
"stock_workflow.xml",
"stock_data.xml",
"wizard/stock_move_view.xml",
"wizard/stock_inventory_set_stock_zero_view.xml",
"wizard/stock_fill_inventory_view.xml",
"wizard/stock_invoice_onshipping_view.xml",
"wizard/stock_location_product_view.xml",
"wizard/stock_inventory_line_split_view.xml",
"stock_workflow.xml",
"stock_incoterms.xml",
"stock_wizard.xml",
"stock_wizard_view.xml",
"stock_wizard.xml",
"stock_view.xml",
"stock_report.xml",
"stock_sequence.xml",
@@ -22,4 +22,10 @@
"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,0,0,0
"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,0,0,0
"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,0,0,0
"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,0,0,0"access_report_products_to_received_planned","report.products.to.received.planned","model_report_products_to_received_planned","stock.group_stock_user",1,0,0,0
"access_report_delivery_products_planned","report.delivery.products.planned","model_report_delivery_products_planned","stock.group_stock_user",1,0,0,0
"access_stock_move_track","stock.move.track","model_stock_move_track","stock.group_stock_user",1,0,0,0
"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,0,0,0
"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,0,0,0
"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,0,0,0
"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,0,0,0
Can't render this file because it contains an unexpected character in line 25 and column 121.
+52 -3
View File
@@ -1309,7 +1309,40 @@ class stock_move(osv.osv):
wf_service.trg_trigger(uid, 'stock.move', id, cr)
#self.action_cancel(cr,uid, ids2, context)
return True
def action_scrap(self, cr, uid, ids,context=None):
'''
add the damaged product into consumed product by updating its state to cancel and
add same product since we need that product to manufacture the parent product.
:param cr: the database cursor
:param uid: the user id
:param ids: ids of product object to be scraped
:param context: context arguments
:return:
'''
# to find the parent id(manufacturing order) of the active record(product to consume),
# obtain active record id 1st and then get the production_id from mrp_production_move_ids
active_id=ids[0]
cr.execute("select production_id from mrp_production_move_ids where move_id=%s" % (active_id))
# it gives parent id in [list(tuple)] format so extract it [(21,)]
parent_id = int(cr.fetchall()[0][0])
# get the parent object
parent_obj = self.pool.get('mrp.production').browse(cr, uid, parent_id)
# create copy for multiple id processing for product to consume which r scraped
for id in ids:
#create copy of the product records which are scraped due to damage since they are
#still required to manufacture the product.
new_rec_id = self.copy(cr, uid, id, {'state': 'waiting'}, context)
#assign all new products which will replace damaged product to the current manufacturing order
cr.execute('insert into mrp_production_move_ids (production_id,move_id) values (%s,%s)', (parent_id, new_rec_id))
# all damaged product needs to be in consumed product window having cancel state.
vals={'state': 'cancel', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S')}
self.pool.get('stock.move').write(cr, uid, ids,vals )
return True
def action_done(self, cr, uid, ids, context=None):
track_flag = False
picking_ids = []
@@ -1563,11 +1596,27 @@ class stock_move(osv.osv):
self.write(cr, uid, [move.id], update_val)
if consume:
self.action_done(cr, uid, res)
self.action_done(cr, uid, res)
else:
self.action_scrap(cr, uid, res,context)
return res
def scrap_moves(self, cr, uid, ids, quantity, location_dest_id, context=None):
return self.consume_moves(cr, uid, ids, quantity, location_id=False, location_dest_id=location_dest_id, consume=False, context=context)
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
res = []
for move in self.browse(cr, uid, ids, context=context):
move_qty = move.product_qty
uos_qty = quantity / move_qty * move.product_uos_qty
default_val = {
'product_qty': quantity,
'product_uos_qty': uos_qty,
'state': move.state,
'location_dest_id': location_dest_id
}
new_move = self.copy(cr, uid, move.id, default_val)
res += [new_move]
return res
stock_move()
+47 -32
View File
@@ -32,8 +32,10 @@
<field name="product_qty"/>
<field name="product_uom"/>
<field name="prod_lot_id"/>
<field colspan="4" domain="[('usage','=','internal')]" name="location_id" select="1"/>
<button name="%(split_inventory_lots)d" string="Split Inventory Lines" type="action" icon="gtk-justify-fill"/>
<field colspan="4" domain="[('usage','=','internal')]" name="location_id" select="1"/>
<button name="%(stock.action_view_stock_inventory_line_split)d"
string="Split inventory lines"
type="action" icon="gtk-justify-fill"/>
</form>
</field>
</record>
@@ -50,6 +52,7 @@
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
</group>
</search>
</field>
</record>
@@ -64,6 +67,7 @@
<field name="state"/>
</tree>
</field>
</record>
<record id="view_inventory_form" model="ir.ui.view">
<field name="name">stock.inventory.form</field>
@@ -89,11 +93,12 @@
<field name="product_qty"/>
<field name="product_uom"/>
<field domain="[('usage','=','internal')]" name="location_id" select="1"/>
<field name="prod_lot_id"/>
<group colspan="2" col="3">
<field name="prod_lot_id"/>
<button name="%(split_inventory_lots)d" string="Split in Production Lots" type="action" icon="gtk-justify-fill"/>
</group>
<button name="%(stock.action_view_stock_inventory_line_split)d"
string="Split inventory lines"
type="action" icon="gtk-justify-fill"/>
</group>
</form>
</field>
</page><page string="Posted Inventory">
@@ -106,6 +111,7 @@
<button name="action_cancel" states="cancel" string="Set to Draft" type="object" icon="gtk-cancel"/>
<button name="action_cancel_inventary" states="draft" string="Cancel Inventory" type="object" icon="gtk-cancel"/>
</group>
</form>
</field>
</record>
@@ -138,6 +144,9 @@
<field name="name" select="1"/>
<field name="serial" select="1"/>
<field name="date" select="1"/>
<field name="active" select="1"/>
<group colspan="4">
</group>
<field name="active" />
</form>
</field>
@@ -259,6 +268,7 @@
<field name="product_id" select="1"/>
<field name="date" select="1"/>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Product" icon="terp-stock" domain="[]" context="{'group_by':'product_id'}"/>
</group>
@@ -524,7 +534,7 @@
<field name="auto_refresh" eval="1"/>
<field name="target">new</field>
<field name="context">{'action_id': active_id}</field>
</record>
</record>
<record model="ir.ui.view" id="stock_picking_calendar">
<field name="name">stock.picking.calendar</field>
@@ -585,7 +595,7 @@
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_planned"/>
<field name="state"/>
<field name="state"/>
<button
name="%(stock.track_line)d"
string="Split in production lots"
@@ -661,7 +671,7 @@
<newline/>
<field name="move_type"/>
</page>
</notebook>
</notebook>
</form>
</field>
</record>
@@ -683,7 +693,8 @@
<field name="location_dest_id" select="1"/>
<field name="name" select="1"/>
<field name="address_id" select="1"/>
</group>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Partner" icon="terp-stock" domain="[]" context="{'group_by':'address_id'}"/>
<filter string="State" icon="terp-stock" domain="[]" context="{'group_by':'state'}"/>
@@ -726,6 +737,7 @@
<field name="min_date" select="1"/>
<field name="type"/>
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
</group>
<notebook colspan="4">
<page string="General Information">
@@ -740,7 +752,7 @@
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_planned"/>
<field name="state"/>
<field name="state"/>
<button
name="%(stock.track_line)d"
string="Split in production lots"
@@ -811,7 +823,7 @@
<field name="date_done" select="2"/>
<field name="move_type"/>
</page>
</notebook>
</notebook>
</form>
</field>
</record>
@@ -831,7 +843,8 @@
<field name="name" select="1"/>
<field name="address_id" select="1"/>
<field name="origin" select="1"/>
</group>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="10">
<filter string="Partner" icon="terp-stock" domain="[]" context="{'group_by':'address_id'}"/>
<filter string="State" icon="terp-stock" domain="[]" context="{'group_by':'state'}"/>
@@ -890,9 +903,6 @@
<field name="state"/>
<button name="%(partial_picking)d" states="assigned" string="Validate" type="action" icon="gtk-go-forward" help="Validate Picking"/>
<button name="button_cancel" states="assigned,confirmed,draft" string="Cancel" icon="gtk-cancel" help="Cancel" confirm="This operation will cancel the picking. Do you want to continue?"/>
<button name="%(wizard_invoice_onshipping)d" states="done" string="Invoice" type="action"
icon="gtk-execute" help="Create invoice"
attrs="{'invisible': [('invoice_state', '!=', '2binvoiced')]}" />
</tree>
</field>
</record>
@@ -925,7 +935,7 @@
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_planned"/>
<field name="state"/>
<field name="state"/>
<button
name="%(stock.track_line)d"
string="Split in production lots"
@@ -1016,8 +1026,9 @@
<field name="name" select="1"/>
<field name="address_id" select="1"/>
<field name="company_id" select="1" widget="selection"/>
</group>
<group expand="context.get('report',False)" string="Group By..." colspan="4" col="8">
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Partner" icon="terp-stock" domain="[]" context="{'group_by':'address_id'}"/>
<filter string="State" icon="terp-stock" domain="[]" context="{'group_by':'state'}"/>
<filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/>
@@ -1110,8 +1121,8 @@
name="%(stock.move_scrap)d"
string="D" type="action"
icon="gtk-convert"
states="draft,waiting,confirmed,assigned" />
</tree>
states="done,cancel" />
</tree>
<form string="Stock Moves">
<notebook colspan="4">
<page string="General Information">
@@ -1187,7 +1198,8 @@
<field name="name" select="1"/>
<field name="address_id" select="1"/>
<field name="company_id" select="1" widget="selection" groups="base.group_multi_company" />
</group>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Partner" icon="terp-stock" domain="[]" context="{'group_by':'address_id'}"/>
<filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/>
@@ -1240,7 +1252,8 @@
<field name="name" select="1"/>
<field name="origin" select="1"/>
<field name="company_id" select="1" widget="selection"/>
</group>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Partner" icon="terp-stock" domain="[]" context="{'group_by':'address_id'}"/>
<filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/>
@@ -1278,7 +1291,7 @@
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_planned"/>
<field name="state"/>
<field name="state"/>
</tree>
</field>
</record>
@@ -1317,7 +1330,7 @@
<field name="date"/>
<field name="date_planned"/>
<field name="priority"/>
</group>
</group>
<group colspan="2" col="4">
<separator string="Tracability" colspan="4" />
@@ -1327,7 +1340,7 @@
domain="[('product_id','=?',product_id)]"
on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)"/>
<button name="%(track_line)d" string="Split in production lots" type="action" icon="gtk-justify-fill" colspan="2" />
</group>
</group>
</page>
<page string="Return Picking History">
<field name="move_stock_return_history" nolabel="1"/>
@@ -1359,7 +1372,8 @@
<field name="location_id" select="1"/>
<field name="location_dest_id" select="1"/>
<field name="product_id" select="1"/>
</group>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Product" icon="terp-stock" domain="[]" context="{'group_by':'product_id'}"/>
<filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/>
@@ -1410,7 +1424,7 @@
<field name="arch" type="xml">
<tree colors="grey:state in ('cancel','done');black:state not in ('cancel','done')" string="Moves">
<field name="picking_id" string="Reference"/>
<field name="origin" string="Purchase Order"/>
<field name="origin" string="Latest Requisition"/>
<field name="partner_id" string="Supplier"/>
<field name="product_id"/>
<field name="product_qty" />
@@ -1488,11 +1502,12 @@
<filter icon="terp-stock" string="Back Orders" domain="[('backorder_id','!=',False)]" help="Back Orders"/>
<filter icon="terp-stock" string="Planned Today" domain="[('date_planned::date','=',time.strftime('%%Y-%%m-%%d'))]" help="Orders planned for today"/>
<separator orientation="vertical"/>
<field name="origin" string="Purchase Order" select="1"/>
<field name="origin" string="Latest Requisition" select="1"/>
<field name="partner_id" string="Supplier" select="1"/>
<field name="product_id"/>
</group>
<group expand="context.get('report',False)" string="Group By..." colspan="4" col="8">
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="8">
<filter string="Product" icon="terp-stock" domain="[]" context="{'group_by':'product_id'}"/>
<filter string="State" icon="terp-stock" domain="[]" context="{'group_by':'state'}"/>
<filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/>
@@ -1606,7 +1621,7 @@
<field name="key2">tree_but_open</field>
<field name="model">stock.location</field>
<field name="name">Open Products</field>
<field eval="'ir.actions.wizard,%d'%ref('location_product')" name="value"/>
<field eval="'ir.actions.act_window,%d'%action_view_stock_location_product" name="value"/>
<field eval="True" name="object"/>
</record>  
+2 -30
View File
@@ -43,20 +43,6 @@
name="stock.return.picking"
string="Return picking"/>
<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"
@@ -65,19 +51,5 @@
multi="True"
id="wizard_merge_inventory"/>
<wizard
string="Fill Inventory"
model="stock.inventory"
name="stock.fill_inventory"
keyword="client_action_multi"
id="wizard_fill_inventory"
/>
<wizard
id="location_product"
model="stock.location"
name="stock.location.products"
string="Products by Location"/>
</data>
</openerp>
</data>
</openerp>
+9 -7
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,11 +15,12 @@
# 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/>.
#
##############################################################################
import stock_traceability
import stock_move
import wizard_partial_picking
import wizard_partial_move
import wizard_picking_make
@@ -27,12 +28,13 @@ import wizard_replacement
import wizard_return
import wizard_split_lot_line
import wizard_ups
import wizard_invoice_onshipping
import wizard_location_product
import wizard_inventory
import wizard_split_inventory_lots
import inventory_merge_zero
import inventory_merge
import stock_inventory_set_stock_zero
import stock_fill_inventory
import stock_inventory_line_split
import stock_invoice_onshipping
import stock_location_product
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,94 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import pooler
from tools.translate import _
_form = """<?xml version="1.0"?>
<form string="Set Stock to Zero">
<separator colspan="4" string="Set Stocks to Zero" />
<field name="location_id"/>
<newline/>
<label colspan="4" string="Do you want to set stocks to zero ?"/>
</form>
"""
_inventory_fields = {
'location_id' : {
'string':'Location',
'type':'many2one',
'relation':'stock.location',
'required':True
}
}
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 !'))
loc = str(data['form']['location_id'])
cr.execute('select distinct location_id,product_id from stock_inventory_line where inventory_id=%s', (data['ids'][0],))
inv = cr.fetchall()
cr.execute('select distinct product_id from stock_move where location_dest_id=%s or location_id=%s',(loc,loc,))
stock = cr.fetchall()
for s in stock:
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' : _inventory_fields,
'state' : [('end', 'Cancel', 'gtk-cancel'),
('merge', 'Set to Zero', 'gtk-apply', True) ]}
},
'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:
@@ -0,0 +1,90 @@
# -*- 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 service import web_services
from tools.misc import UpdateableStr, UpdateableDict
from tools.translate import _
import netsvc
import pooler
import time
import wizard
class stock_fill_inventory(osv.osv_memory):
_name = "stock.fill.inventory"
_description = "Fill Inventory"
_columns = {
'location_id': fields.many2one('stock.location', 'Location', required=True),
'recursive': fields.boolean("Include all childs for the location"),
}
def fill_inventory(self, cr, uid, ids, context):
inventory_line_obj = self.pool.get('stock.inventory.line')
location_obj = self.pool.get('stock.location')
for fill_inventory in self.browse(cr, uid, ids):
res = {}
res_location = {}
if fill_inventory.recursive :
location_ids = location_obj.search(cr, uid, [('location_id',
'child_of', fill_inventory.location_id.id)])
for location in location_ids :
res = location_obj._product_get(cr, uid, location)
res_location[location] = res
else:
context.update({'compute_child': False})
res = location_obj._product_get(cr, uid,
fill_inventory.location_id.id, context=context)
res_location[fill_inventory.location_id.id] = res
product_ids = []
for location in res_location.keys():
res = res_location[location]
for product_id in res.keys():
prod = self.pool.get('product.product').browse(cr, uid, [product_id])[0]
uom = prod.uom_id.id
context.update({'uom': uom})
amount = self.pool.get('stock.location')._product_get(cr, uid,
location, [product_id], context=context)[product_id]
if(amount):
line_ids=inventory_line_obj.search(cr, uid,
[('inventory_id', '=', context['active_ids']),
('location_id', '=', location),
('product_id', '=', product_id),
('product_uom', '=', uom),
('product_qty', '=', amount)])
if not len(line_ids):
inventory_line = {'inventory_id': context['active_ids'][0],
'location_id': location,
'product_id': product_id,
'product_uom': uom,
'product_qty': amount}
inventory_line_obj.create(cr, uid, inventory_line)
product_ids.append(product_id)
if(len(product_ids) == 0):
raise osv.except_osv(_('Message !'), _('No product in this location.'))
return {}
stock_fill_inventory()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_stock_fill_inventory" model="ir.ui.view">
<field name="name">Fill Inventory</field>
<field name="model">stock.fill.inventory</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Fill Inventory">
<separator string="Fill Inventory for specific location" colspan="4" />
<field name="location_id"/>
<newline/>
<field name="recursive"/>
<newline/>
<separator string="" colspan="4" />
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="fill_inventory" string="Fill Inventory" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Fill Inventory"
res_model="stock.fill.inventory"
src_model="stock.inventory"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_view_stock_fill_inventory"/>
</data>
</openerp>
@@ -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 service import web_services
from tools.misc import UpdateableStr, UpdateableDict
from tools.translate import _
import netsvc
import pooler
import time
import wizard
class stock_inventory_line_split(osv.osv_memory):
_name = "stock.inventory.line.split"
_description = "Split inventory lines"
_columns = {
'prefix': fields.char('Prefix', size=64),
'quantity': fields.float('Quantity per lot'),
}
def _check_production_lot(self, cr, uid, context):
for inv_obj in self.pool.get('stock.inventory.line').browse(cr, uid, \
context['active_ids']):
if not inv_obj.prod_lot_id:
raise osv.except_osv(_('Caution!'), _('Before splitting the \
inventory lines, make sure the production lot is assigned to this product.'))
return
_defaults = {
'quantity': lambda *a: '1',
'prefix': _check_production_lot,
}
def split_lines(self, cr, uid, ids, context):
inv_id = context['active_id']
inv_line_obj = self.pool.get('stock.inventory.line')
prodlot_obj = self.pool.get('stock.production.lot')
for linesplit_obj in self.browse(cr, uid, ids):
ir_sequence_obj = self.pool.get('ir.sequence')
sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
if not sequence:
raise wizard.except_wizard(_('Error!'), _('No production sequence defined'))
if linesplit_obj.prefix:
sequence = linesplit_obj.prefix + '/' + (sequence or '')
inv = inv_line_obj.browse(cr, uid, [inv_id])[0]
quantity = linesplit_obj.quantity
prodlot_obj.write(cr, uid, inv.prod_lot_id.id, {'name': sequence})
if quantity <= 0 or inv.product_qty == 0:
return {}
quantity_rest = inv.product_qty % quantity
update_val = {
'product_qty': quantity,
}
new_line = []
for idx in range(int(inv.product_qty // quantity)):
if idx:
current_line = inv_line_obj.copy(cr, uid, inv.id,
{'prod_lot_id': inv.prod_lot_id.id})
new_line.append(current_line)
else:
current_line = inv.id
inv_line_obj.write(cr, uid, [current_line], update_val)
if quantity_rest > 0:
idx = int(inv.product_qty // quantity)
update_val['product_qty'] = quantity_rest
if idx:
current_line = inv_line_obj.copy(cr, uid, inv.id,
{'prod_lot_id': inv.prod_lot_id.id})
new_line.append(current_line)
else:
current_line = inv_line_obj.id
inv_line_obj.write(cr, uid, [current_line], update_val)
return {}
stock_inventory_line_split()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_stock_inventory_line_split" model="ir.ui.view">
<field name="name">Split inventory lines</field>
<field name="model">stock.inventory.line.split</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Split Inventory Line">
<field name="prefix"/>
<newline/>
<field name="quantity"/>
<separator string="" colspan="4" />
<label string=""/>
<button special="cancel" string="Cancel" icon="gtk-cancel" />
<button name="split_lines" string="Ok" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<record id="action_view_stock_inventory_line_split" model="ir.actions.act_window">
<field name="name">Split inventory lines</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">stock.inventory.line.split</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>
@@ -0,0 +1,72 @@
# -*- 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 service import web_services
from tools.misc import UpdateableStr, UpdateableDict
from tools.translate import _
import netsvc
import pooler
import time
import wizard
class inventory_merge_stock_zero(osv.osv_memory):
_name = "stock.inventory.merge.stock.zero"
_description = "Set Stock to 0"
_columns = {
'location_id': fields.many2one('stock.location', 'Location', required=True),
}
def do_merge(self, cr, uid, ids, 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(context['active_ids']) <> 1:
raise wizard.except_wizard(_('Warning'),
_('Please select one and only one inventory !'))
for id in ids:
datas = self.read(cr, uid, id)
loc = str(datas['location_id'])
cr.execute('select distinct location_id,product_id \
from stock_inventory_line \
where inventory_id=%s', (context['active_id'],))
inv = cr.fetchall()
cr.execute('select distinct product_id from stock_move where \
location_dest_id=%s or location_id=%s', (loc, loc,))
stock = cr.fetchall()
for s in stock:
if (loc, s[0]) not in inv:
p = prod_obj.browse(cr, uid, s[0])
invent_line_obj.create(cr, uid, {
'inventory_id': context['active_id'],
'location_id': loc,
'product_id': s[0],
'product_uom': p.uom_id.id,
'product_qty': 0.0,
})
return {}
inventory_merge_stock_zero()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_inventory_merge_stock_zero" model="ir.ui.view">
<field name="name">Set Stock to Zero</field>
<field name="model">stock.inventory.merge.stock.zero</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Set Stock to Zero">
<separator string="Set Stocks to Zero" colspan="4" />
<field name="location_id"/>
<newline/>
<label colspan="4" string="Do you want to set stocks to zero ?"/>
<separator string="" colspan="4" />
<button special="cancel" icon='gtk-cancel' string="Cancel" />
<button name="do_merge" string="Set Stock to Zero" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Set Stock to Zero"
res_model="stock.inventory.merge.stock.zero"
src_model="stock.inventory"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_view_inventory_merge_stock_zero"/>
</data>
</openerp>
@@ -0,0 +1,111 @@
# -*- 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 service import web_services
from tools.misc import UpdateableStr, UpdateableDict
from tools.translate import _
import netsvc
import pooler
import time
import wizard
class stock_invoice_onshipping(osv.osv_memory):
_name = "stock.invoice.onshipping"
_description = "Stock Invoice Onshipping"
_columns = {
'journal_id': fields.many2one('account.journal', 'Destination Journal', required=True),
'group': fields.boolean("Group by partner"),
'type': fields.selection([('out_invoice', 'Customer Invoice'),
('in_invoice', 'Supplier Invoice'),
('out_refund', 'Customer Refund'),
('in_refund', 'Supplier Refund')] , 'Type', required=True),
'invoice_date': fields.date('Invoiced date'),
}
def _get_type(self, cr, uid, context):
picking_obj = self.pool.get('stock.picking')
usage = 'customer'
pick = picking_obj.browse(cr, uid, context['active_id'])
if pick.invoice_state == 'invoiced':
raise osv.except_osv(_('UserError'), _('Invoice is already created.'))
if pick.invoice_state == 'none':
raise osv.except_osv(_('UserError'), _('Invoice cannot be created from Picking.'))
if pick.move_lines:
usage = pick.move_lines[0].location_id.usage
if pick.type == 'out' and usage == 'supplier':
type = 'in_refund'
elif pick.type == 'out' and usage == 'customer':
type = 'out_invoice'
elif pick.type == 'in' and usage == 'supplier':
type = 'in_invoice'
elif pick.type == 'in' and usage == 'customer':
type = 'out_refund'
else:
type = 'out_invoice'
return type
_defaults = {
'type': _get_type,
}
def create_invoice(self, cr, uid, ids, context):
result = []
for onshipdata_obj in self.read(cr, uid, ids, ['journal_id', 'group', 'type', 'invoice_date']):
if context.get('new_picking', False):
onshipdata_obj[id] = onshipdata_obj.new_picking
onshipdata_obj[ids] = onshipdata_obj.new_picking
picking_obj = self.pool.get('stock.picking')
mod_obj = self.pool.get('ir.model.data')
act_obj = self.pool.get('ir.actions.act_window')
type = onshipdata_obj['type']
context['date_inv'] = onshipdata_obj['invoice_date']
res = picking_obj.action_invoice_create(cr, uid,context['active_ids'],
journal_id = onshipdata_obj['journal_id'],
group=onshipdata_obj['group'],
type=type,
context=context)
invoice_ids = res.values()
if not invoice_ids:
raise osv.except_osv(_('Error'), _('Invoice is not created'))
if type == 'out_invoice':
xml_id = 'action_invoice_tree1'
elif type == 'in_invoice':
xml_id = 'action_invoice_tree2'
elif type == 'out_refund':
xml_id = 'action_invoice_tree3'
else:
xml_id = 'action_invoice_tree4'
result = mod_obj._get_id(cr, uid, 'account', xml_id)
id = mod_obj.read(cr, uid, result, ['res_id'])
result = act_obj.read(cr, uid, id['res_id'])
result['res_id'] = invoice_ids
return result
stock_invoice_onshipping()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_stock_invoice_onshipping" model="ir.ui.view">
<field name="name">Stock Invoice Onshipping</field>
<field name="model">stock.invoice.onshipping</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Create invoices">
<separator colspan="4" string="Create invoices" />
<field name="journal_id"/>
<newline/>
<field name="group"/>
<newline/>
<field name="type"/>
<newline/>
<field name="invoice_date" />
<separator string="" colspan="4" />
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="create_invoice" string="Create Invoices" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Create Invoice"
res_model="stock.invoice.onshipping"
src_model="stock.picking"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_stock_invoice_onshipping"/>
</data>
</openerp>
+59
View File
@@ -0,0 +1,59 @@
# -*- 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 service import web_services
from tools.misc import UpdateableStr, UpdateableDict
from tools.translate import _
import netsvc
import pooler
import time
import wizard
class stock_location_product(osv.osv_memory):
_name = "stock.location.product"
_description = "Products by Location"
_columns = {
'from_date': fields.datetime('From'),
'to_date': fields.datetime('To'),
}
def action_open_window(self, cr, uid, ids, context):
mod_obj = self.pool.get('ir.model.data')
for location_obj in self.read(cr, uid, ids, ['from_date', 'to_date']):
result = mod_obj._get_id(cr, uid, 'product', 'product_search_form_view')
id = mod_obj.read(cr, uid, result, ['res_id'])
return {
'name': 'product',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'product.product',
'type': 'ir.actions.act_window',
'context': {'location': context['active_id'],
'from_date': location_obj['from_date'],
'to_date': location_obj['to_date']},
'domain': [('type', '<>', 'service')],
'search_view_id': id['res_id']
}
stock_location_product()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_stock_location_product" model="ir.ui.view">
<field name="name">Products by Location</field>
<field name="model">stock.location.product</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="View Stock of Products">
<separator string="Stock Location Analysis" colspan="4"/>
<field name="from_date" colspan="4"/>
<newline/>
<field name="to_date" colspan="4"/>
<newline/>
<label string=""/>
<label string="(Keep empty to open the current situation. Adjust HH:MM:SS to 00:00:00 to filter all resources of the day for the 'From' date and 23:59:59 for the 'To' date)" align="0.0" colspan="3"/>
<separator string="" colspan="4" />
<label string=""/>
<button special="cancel" string="Cancel" icon="gtk-cancel" />
<button name="action_open_window" string="Open Product" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<act_window name="Products by Location"
res_model="stock.location.product"
src_model="stock.location"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_view_stock_location_product"/>
</data>
</openerp>
-111
View File
@@ -1,111 +0,0 @@
# -*- 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/>.
#
##############################################################################
import time
import wizard
import ir
import pooler
from osv.osv import except_osv
from osv import fields,osv
import netsvc
from tools.translate import _
inventory_form = """<?xml version="1.0"?>
<form string="Fill Inventory">
<separator colspan="4" string="Fill Inventory for specific location" />
<field name="location_id"/>
<newline/>
<field name="recursive"/>
<newline/>
</form>
"""
inventory_fields = {
'location_id' : {
'string':'Location',
'type':'many2one',
'relation':'stock.location',
'required':True
},
'recursive' : {'string':'Include all childs for the location', 'type':'boolean'}
}
def _fill_inventory(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
inventory_line_obj = pooler.get_pool(cr.dbname).get('stock.inventory.line')
location_obj = pooler.get_pool(cr.dbname).get('stock.location')
res={}
res_location={}
if data['form']['recursive'] :
location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', [data['form']['location_id']])])
for location in location_ids :
res=location_obj._product_get(cr, uid, location)
res_location[location]=res
else:
context.update({'compute_child':False})
res=location_obj._product_get(cr, uid, data['form']['location_id'],context=context)
res_location[data['form']['location_id']]=res
product_ids=[]
for location in res_location.keys():
res=res_location[location]
for product_id in res.keys():
#product_ids.append(product_id)
prod = pool.get('product.product').browse(cr, uid, [product_id])[0]
uom = prod.uom_id.id
context.update({'uom': uom})
amount=pool.get('stock.location')._product_get(cr, uid, location, [product_id], context=context)[product_id]
if(amount):
line_ids=inventory_line_obj.search(cr,uid,[('inventory_id','=',data['id']),('location_id','=',location),('product_id','=',product_id),('product_uom','=',uom),('product_qty','=',amount)])
if not len(line_ids):
inventory_line={'inventory_id':data['id'],'location_id':location,'product_id':product_id,'product_uom':uom,'product_qty':amount}
inventory_line_obj.create(cr, uid, inventory_line)
product_ids.append(product_id)
if(len(product_ids)==0):
raise wizard.except_wizard(_('Message !'), _('No product in this location.'))
return {}
class fill_inventory(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {'type' : 'form',
'arch' : inventory_form,
'fields' : inventory_fields,
'state' : [('end', 'Cancel', 'gtk-cancel'),('fill_inventory', 'Fill Inventory', 'gtk-apply', True) ]}
},
'fill_inventory' : {
'actions' : [],
'result' : {'type' : 'action', 'action': _fill_inventory, 'state' : 'end'}
},
}
fill_inventory("stock.fill_inventory")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,167 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import pooler
from tools.translate import _
invoice_form = """<?xml version="1.0"?>
<form string="Create invoices">
<separator colspan="4" string="Create invoices" />
<field name="journal_id"/>
<newline/>
<field name="group"/>
<newline/>
<field name="type"/>
<newline/>
<field name="invoice_date" />
</form>
"""
invoice_fields = {
'journal_id': {
'string': 'Destination Journal',
'type': 'many2one',
'relation': 'account.journal',
'required': True
},
'group': {
'string': 'Group by partner',
'type': 'boolean'
},
'type': {
'string': 'Type',
'type': 'selection',
'selection': [],
'required': True
},
'invoice_date': {'string': 'Invoiced date', 'type':'date' }
}
def _get_type(obj, cr, uid, data, context):
picking_obj = pooler.get_pool(cr.dbname).get('stock.picking')
usage = 'customer'
pick = picking_obj.browse(cr, uid, data['id'], context)
if pick.invoice_state == 'invoiced':
raise wizard.except_wizard(_('UserError'), _('Invoice is already created.'))
if pick.invoice_state == 'none':
raise wizard.except_wizard(_('UserError'), _('Invoice cannot be created from Picking.'))
if pick.move_lines:
usage = pick.move_lines[0].location_id.usage
if pick.type =='out':
invoice_fields['type']['selection'] = [
('out_invoice', 'Customer Invoice'),
('in_refund', 'Supplier Refund'),
]
elif pick.type =='in':
invoice_fields['type']['selection'] = [
('in_invoice', 'Supplier Invoice'),
('out_refund', 'Customer Refund'),
]
else:
invoice_fields['type']['selection']=[
('out_invoice', 'Customer Invoice'),
('in_invoice', 'Supplier Invoice'),
('out_refund', 'Customer Refund'),
('in_refund', 'Supplier Refund'),
]
if pick.type == 'out' and usage == 'supplier':
type = 'in_refund'
elif pick.type == 'out' and usage == 'customer':
type = 'out_invoice'
elif pick.type == 'in' and usage == 'supplier':
type = 'in_invoice'
elif pick.type == 'in' and usage == 'customer':
type = 'out_refund'
else:
type = 'out_invoice'
return {'type': type}
def _create_invoice(obj, cr, uid, data, context):
if data['form'].get('new_picking', False):
data['id'] = data['form']['new_picking']
data['ids'] = [data['form']['new_picking']]
pool = pooler.get_pool(cr.dbname)
picking_obj = pooler.get_pool(cr.dbname).get('stock.picking')
mod_obj = pool.get('ir.model.data')
act_obj = pool.get('ir.actions.act_window')
type = data['form']['type']
context['date_inv'] = data['form']['invoice_date']
res = picking_obj.action_invoice_create(cr, uid, data['ids'],
journal_id = data['form']['journal_id'], group=data['form']['group'],
type=type, context= context)
invoice_ids = res.values()
if not invoice_ids:
raise wizard.except_wizard(_('Error'), _('Invoice is not created'))
if type == 'out_invoice':
xml_id = 'action_invoice_tree1'
elif type == 'in_invoice':
xml_id = 'action_invoice_tree2'
elif type == 'out_refund':
xml_id = 'action_invoice_tree3'
else:
xml_id = 'action_invoice_tree4'
result = mod_obj._get_id(cr, uid, 'account', xml_id)
id = mod_obj.read(cr, uid, result, ['res_id'])
result = act_obj.read(cr, uid, id['res_id'])
result['res_id'] = invoice_ids
return result
class make_invoice_onshipping(wizard.interface):
states = {
'init': {
'actions': [_get_type],
'result': {
'type': 'form',
'arch': invoice_form,
'fields': invoice_fields,
'state': [
('end', 'Cancel', 'gtk-cancel'),
('create_invoice', 'Create invoice', 'gtk-apply', True)
]
}
},
'create_invoice': {
'actions': [],
'result': {
'type': 'action',
'action': _create_invoice,
'state': 'end'
}
},
}
make_invoice_onshipping("stock.invoice_onshipping")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,76 +0,0 @@
# -*- 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/>.
#
##############################################################################
import wizard
import pooler
import time
def _action_open_window(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
mod_obj = pool.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'product', 'product_search_form_view')
id = mod_obj.read(cr, uid, result, ['res_id'])
return {
'name': False,
'view_type': 'form',
"view_mode": 'tree,form',
'res_model': 'product.product',
'type': 'ir.actions.act_window',
'context':{'location': data['ids'][0],'from_date':data['form']['from_date'],'to_date':data['form']['to_date']},
'domain':[('type','<>','service')],
'search_view_id': id['res_id']
}
class product_by_location(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="View Stock of Products">
<separator string="Stock Location Analysis" colspan="4"/>
<field name="from_date"/>
<newline/>
<field name="to_date"/>
<newline/>
<label string=""/>
<label string="(Keep empty to open the current situation. Adjust HH:MM:SS to 00:00:00 to filter all resources of the day for the 'From' date and 23:59:59 for the 'To' date)" align="0.0" colspan="3"/>
</form>'''
form1_fields = {
'from_date': {
'string': 'From',
'type': 'datetime',
},
'to_date': {
'string': 'To',
'type': 'datetime',
},
}
states = {
'init': {
'actions': [],
'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, 'state': [('end', 'Cancel', 'gtk-cancel'),('open', 'Open Products', 'gtk-apply', True)]}
},
'open': {
'actions': [],
'result': {'type': 'action', 'action': _action_open_window, 'state':'end'}
}
}
product_by_location('stock.location.products')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,98 +0,0 @@
import wizard
import netsvc
import pooler
import time
from osv import osv
from tools.translate import _
inv_form = '''<?xml version="1.0"?>
<form string="Split Inventory Line">
<field name="prefix"/>
<newline/>
<field name="quantity"/>
</form>
'''
inv_fields = {
'prefix': {
'string': 'Prefix',
'type': 'char',
'size': 64,
},
'quantity': {
'string': 'Quantity per lot',
'type': 'float',
'default': 1,
}
}
def _check_production_lot(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
inv_obj = pool.get('stock.inventory.line').browse(cr, uid, data['id'])
if not inv_obj.prod_lot_id:
raise wizard.except_wizard(_('Caution!'), _('Before splitting the inventory lines, make sure the production lot is assigned to this product.'))
return data['form']
def _split_lines(self, cr, uid, data, context):
inv_id = data['id']
pool = pooler.get_pool(cr.dbname)
inv_line_obj = pool.get('stock.inventory.line')
prodlot_obj = pool.get('stock.production.lot')
ir_sequence_obj = pool.get('ir.sequence')
sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
if not sequence:
raise wizard.except_wizard(_('Error!'), _('No production sequence defined'))
if data['form']['prefix']:
sequence=data['form']['prefix']+'/'+(sequence or '')
inv = inv_line_obj.browse(cr, uid, [inv_id])[0]
quantity=data['form']['quantity']
prodlot_obj.write(cr, uid, inv.prod_lot_id.id, {'name':sequence})
if quantity <= 0 or inv.product_qty == 0:
return {}
quantity_rest = inv.product_qty%quantity
update_val = {
'product_qty': quantity,
}
new_line = []
for idx in range(int(inv.product_qty//quantity)):
if idx:
current_line = inv_line_obj.copy(cr, uid, inv.id, {'prod_lot_id': inv.prod_lot_id.id})
new_line.append(current_line)
else:
current_line = inv.id
inv_line_obj.write(cr, uid, [current_line], update_val)
if quantity_rest > 0:
idx = int(inv.product_qty//quantity)
update_val['product_qty']=quantity_rest
if idx:
current_line = inv_line_obj.copy(cr, uid, inv.id, {'prod_lot_id': inv.prod_lot_id.id})
new_line.append(current_line)
else:
current_line = inv.id
inv_line_obj.write(cr, uid, [current_line], update_val)
return {}
class wizard_split_inventory_lots(wizard.interface):
states = {
'init': {
'actions': [_check_production_lot],
'result': {'type': 'form', 'arch': inv_form, 'fields': inv_fields, 'state': [('end', 'Cancel', 'gtk-cancel'), ('split', 'Ok', 'gtk-apply', True)]},
},
'split': {
'actions': [_split_lines],
'result': {'type':'state', 'state':'end'}
}
}
wizard_split_inventory_lots('stock.inventory.line.split')