mrp_repair:
* [ADD] YML * [IMP] useability mrp: * [IMP] Add contrains in mrp.production model to check Order quantity could not be negative or zero. * [IMP] Improve log message on ready production order * [IMP] useability in Work center, route and BOM * [FIX+IMP] change Cost price Wizard * [FIX] yml problem in mrp_phantom and mrp_procurement * [FIX] produce wiazrd stock: * [FIX] Change Cost price wizard * [IMP] Add property_stock_variation in product category view mrp_operations, procurement, resource bzr revid: hmo@tinyerp.com-20100701134010-z3sdg19w0cj49joc
This commit is contained in:
parent
3bc5b6d6a1
commit
62a8a4ac5b
|
@ -20,6 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
from mx import DateTime
|
||||
from datetime import datetime, timedelta
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
import ir
|
||||
|
@ -99,8 +100,8 @@ class mrp_routing_workcenter(osv.osv):
|
|||
'name': fields.char('Name', size=64, required=True),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of routing workcenters."),
|
||||
'cycle_nbr': fields.float('Number of Cycles', required=True,
|
||||
help="Time in hours for doing one cycle."),
|
||||
'hour_nbr': fields.float('Number of Hours', required=True, help="Cost per hour"),
|
||||
help="Number of operations this workcenter can do."),
|
||||
'hour_nbr': fields.float('Number of Hours', required=True, help="Time in hours for doing one cycle."),
|
||||
'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade',
|
||||
help="Routing indicates all the workcenters used, for how long and/or cycles." \
|
||||
"If Routing is indicated then,the third tab of a production order (workcenters) will be automatically pre-completed."),
|
||||
|
@ -372,8 +373,6 @@ def rounding(f, r):
|
|||
|
||||
class many2many_domain(fields.many2many):
|
||||
def set(self, cr, obj, id, name, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(many2many_domain, self).set(cr, obj, id, name, values, user=user,
|
||||
context=context)
|
||||
|
||||
|
@ -392,8 +391,6 @@ class many2many_domain(fields.many2many):
|
|||
|
||||
class one2many_domain(fields.one2many):
|
||||
def set(self, cr, obj, id, field, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(one2many_domain, self).set(cr, obj, id, field, values,
|
||||
user=user, context=context)
|
||||
|
||||
|
@ -416,7 +413,6 @@ class mrp_production(osv.osv):
|
|||
_name = 'mrp.production'
|
||||
_description = 'Manufacturing Order'
|
||||
_date_name = 'date_planned'
|
||||
_log_create = True
|
||||
|
||||
def _production_calc(self, cr, uid, ids, prop, unknow_none, context={}):
|
||||
""" Calculates total hours and total no. of cycles for a production order.
|
||||
|
@ -485,10 +481,10 @@ class mrp_production(osv.osv):
|
|||
'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True,
|
||||
help="This is the internal picking list that brings the finished product to the production plan"),
|
||||
'move_prod_id': fields.many2one('stock.move', 'Move product', readonly=True),
|
||||
'move_lines': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consumme', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_lines2': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Consummed Products', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'move_created_ids': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_created_ids2': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'move_lines': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consumme', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
|
||||
'move_lines2': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Consummed Products', domain=[('state','in', ('done', 'cancel'))], readonly=True),
|
||||
'move_created_ids': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
|
||||
'move_created_ids2': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','in', ('done', 'cancel'))], readonly=True),
|
||||
'product_lines': fields.one2many('mrp.production.product.line', 'production_id', 'Scheduled goods'),
|
||||
'workcenter_lines': fields.one2many('mrp.production.workcenter.line', 'production_id', 'Work Centers Utilisation'),
|
||||
'state': fields.selection([('draft','Draft'),('picking_except', 'Picking Exception'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Cancelled'),('done','Done')],'State', readonly=True,
|
||||
|
@ -508,7 +504,18 @@ class mrp_production(osv.osv):
|
|||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c),
|
||||
}
|
||||
_order = 'date_planned asc, priority desc';
|
||||
|
||||
|
||||
def _check_qty(self, cr, uid, ids):
|
||||
orders = self.browse(cr, uid, ids)
|
||||
for order in orders:
|
||||
if order.product_qty <= 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_qty, 'Order quantity cannot be negative or zero !', ['product_qty']),
|
||||
]
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
productions = self.read(cr, uid, ids, ['state'])
|
||||
unlink_ids = []
|
||||
|
@ -638,15 +645,23 @@ class mrp_production(osv.osv):
|
|||
""" Changes the production state to Ready and location id of stock move.
|
||||
@return: True
|
||||
"""
|
||||
for (id,name) in self.name_get(cr, uid, ids):
|
||||
message = _('Manufacturing Order ') + " '" + name + "' "+ _("is ready to produce.")
|
||||
self.log(cr, uid, id, message)
|
||||
move_obj = self.pool.get('stock.move')
|
||||
self.write(cr, uid, ids, {'state': 'ready'})
|
||||
for production in self.browse(cr, uid, ids):
|
||||
|
||||
for (production_id,name) in self.name_get(cr, uid, ids):
|
||||
production = self.browse(cr, uid, production_id)
|
||||
if production.move_prod_id:
|
||||
move_obj.write(cr, uid, [production.move_prod_id.id],
|
||||
{'location_id': production.location_dest_id.id})
|
||||
|
||||
message = ("%s %s %s %s %s %s") % (
|
||||
_('Manufacturing Order '),
|
||||
name,
|
||||
_("scheduled the"),
|
||||
datetime.strptime(production.date_planned,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d'),
|
||||
_("for"),
|
||||
production.product_id.name)
|
||||
self.log(cr, uid, production_id, message)
|
||||
return True
|
||||
|
||||
def action_production_end(self, cr, uid, ids):
|
||||
|
@ -680,9 +695,10 @@ class mrp_production(osv.osv):
|
|||
@param production_mode: specify production mode (consume/consume&produce).
|
||||
@return: True
|
||||
"""
|
||||
|
||||
stock_mov_obj = self.pool.get('stock.move')
|
||||
production = self.browse(cr, uid, production_id)
|
||||
|
||||
|
||||
raw_product_todo = []
|
||||
final_product_todo = []
|
||||
|
||||
|
@ -692,6 +708,7 @@ class mrp_production(osv.osv):
|
|||
continue
|
||||
produced_qty += produced_product.product_qty
|
||||
|
||||
|
||||
if production_mode in ['consume','consume_produce']:
|
||||
consumed_products = {}
|
||||
for consumed_product in production.move_lines2:
|
||||
|
@ -700,12 +717,13 @@ class mrp_production(osv.osv):
|
|||
if not consumed_products.get(consumed_product.product_id.id, False):
|
||||
consumed_products[consumed_product.product_id.id] = 0
|
||||
consumed_products[consumed_product.product_id.id] -= consumed_product.product_qty
|
||||
|
||||
|
||||
for raw_product in production.move_lines:
|
||||
for f in production.product_lines:
|
||||
if f.product_id.id==raw_product.product_id.id:
|
||||
consumed_qty = consumed_products.get(raw_product.product_id.id, 0)
|
||||
rest_qty = production_qty * f.product_qty / production.product_qty - consumed_qty
|
||||
|
||||
if rest_qty > 0:
|
||||
stock_mov_obj.action_consume(cr, uid, [raw_product.id], rest_qty, production.location_src_id.id, context=context)
|
||||
|
||||
|
@ -854,7 +872,7 @@ class mrp_production(osv.osv):
|
|||
'company_id': production.company_id.id,
|
||||
}
|
||||
res_final_id = move_obj.create(cr, uid, data)
|
||||
|
||||
|
||||
self.write(cr, uid, [production.id], {'move_created_ids': [(6, 0, [res_final_id])]})
|
||||
moves = []
|
||||
for line in production.product_lines:
|
||||
|
|
|
@ -67,16 +67,38 @@
|
|||
<field name="group_id" select="1"/>
|
||||
<field name="composition" select="1"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="description"/>
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_mrp_property_search" model="ir.ui.view">
|
||||
<field name="name">mrp.property.search</field>
|
||||
<field name="model">mrp.property</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search">
|
||||
<group col='15' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="group_id" widget="selection" />
|
||||
<field name="composition"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Property Group" icon="terp-personal" domain="[]" context="{'group_by':'group_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mrp_property_action" model="ir.actions.act_window">
|
||||
<field name="name">Properties</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.property</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_mrp_property_search"/>
|
||||
</record>
|
||||
<menuitem name="Master Bill of Materials"
|
||||
id="menu_mrp_property"
|
||||
|
@ -105,6 +127,9 @@
|
|||
<tree string="Work Center">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="resource_id"/>
|
||||
<field name="resource_type"/>
|
||||
<field name="company_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -148,12 +173,37 @@
|
|||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Search Views -->
|
||||
|
||||
<record id="view_mrp_workcenter_search" model="ir.ui.view">
|
||||
<field name="name">mrp.workcenter.search</field>
|
||||
<field name="model">mrp.workcenter</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search for mrp workcenter">
|
||||
<group col='15' colspan='4'>
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="resource_type"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended">
|
||||
<filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'resource_type'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}"/>
|
||||
<filter string="Resource" icon="terp-personal" domain="[]" context="{'group_by':'resource_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_workcenter_action" model="ir.actions.act_window">
|
||||
<field name="name">Work Centers</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.workcenter</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="mrp_workcenter_tree_view"/>
|
||||
<field name="search_view_id" ref="view_mrp_workcenter_search"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
|
@ -186,7 +236,8 @@
|
|||
<field name="workcenter_id" select="1"/>
|
||||
<field name="cycle_nbr"/>
|
||||
<field name="hour_nbr"/>
|
||||
<field colspan="4" name="note"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="note" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -298,15 +349,22 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Search Bill Of Material">
|
||||
<group col='4' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="code" string="Reference"/>
|
||||
<field name="product_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="name"/>
|
||||
<field name="code" string="Reference"/>
|
||||
<field name="product_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By" colspan="4" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string='Default UOM' icon="terp-mrp" domain="[]" context="{'group_by' : 'product_uom'}" />
|
||||
<separator orientation="vertical"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" />
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_start'}"/>
|
||||
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
@ -325,10 +383,11 @@
|
|||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<field name="method"/>
|
||||
<field name="type"/>
|
||||
<field name="method" groups="base.group_extended"/>
|
||||
<field name="routing_id" groups="base.group_extended"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="date_start" groups="base.group_extended"/>
|
||||
<field name="date_stop" groups="base.group_extended"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -405,7 +464,8 @@
|
|||
<field colspan="1" name="indice"/>
|
||||
<field colspan="1" name="date"/>
|
||||
<field name="author_id" readonly="1"/>
|
||||
<field colspan="4" name="description"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -589,11 +649,7 @@
|
|||
<field name="product_qty" string="Qty"/>
|
||||
<field name="product_uom" string="UOM"/>
|
||||
<field name="location_id" string="Source Loc."/>
|
||||
<field name="state" invisible="1"/>
|
||||
<button name="%(stock.move_consume)d"
|
||||
string="Consume Products" type="action"
|
||||
icon="gtk-go-forward" context="{'consume': True}"
|
||||
states="draft,waiting,confirmed,assigned" />
|
||||
<field name="state" invisible="1"/>
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="Scrap Products" type="action"
|
||||
icon="gtk-convert" context="{'scrap': True}"
|
||||
|
|
|
@ -24,17 +24,43 @@ from tools.translate import _
|
|||
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
_inherit = "product.product"
|
||||
|
||||
def get_product_accounts(self, cr, uid, product_id, context={}):
|
||||
""" To get the stock input account, stock output account and stock journal related to product.
|
||||
@param product_id: product id
|
||||
@return: dictionary which contains information regarding stock input account, stock output account and stock journal
|
||||
"""
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product_id, False)
|
||||
|
||||
stock_input_acc = product_obj.property_stock_account_input and product_obj.property_stock_account_input.id or False
|
||||
if not stock_input_acc:
|
||||
stock_input_acc = product_obj.categ_id.property_stock_account_input_categ and product_obj.categ_id.property_stock_account_input_categ.id or False
|
||||
|
||||
stock_output_acc = product_obj.property_stock_account_output and product_obj.property_stock_account_output.id or False
|
||||
if not stock_output_acc:
|
||||
stock_output_acc = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id or False
|
||||
|
||||
journal_id = product_obj.categ_id.property_stock_journal and product_obj.categ_id.property_stock_journal.id or False
|
||||
|
||||
res = {}
|
||||
res.update({'stock_account_input': stock_input_acc})
|
||||
res.update({'stock_account_output': stock_output_acc})
|
||||
res.update({'stock_journal': journal_id})
|
||||
|
||||
return res
|
||||
|
||||
|
||||
_columns = {
|
||||
"bom_ids": fields.one2many('mrp.bom', 'product_id','Bill of Materials'),
|
||||
}
|
||||
|
||||
def do_change_standard_price(self, cr, uid, ids, datas, context={}):
|
||||
""" Changes the Standard Price of Product and parent products and creates an account move accordingly.
|
||||
@param datas: dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
|
||||
@param context: A standard dictionary
|
||||
@return:
|
||||
"""
|
||||
#TODO : TO Check
|
||||
res = super(product_product, self).do_change_standard_price(cr, uid, ids, datas, context=context)
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
def _compute_price(bom):
|
||||
|
|
|
@ -27,3 +27,4 @@
|
|||
"access_mrp_production_order","mrp.production.order","model_mrp_production_order","mrp.group_mrp_user",1,0,0,0
|
||||
"access_report_workcenter_load","report.workcenter.load","model_report_workcenter_load","mrp.group_mrp_manager",1,0,0,0
|
||||
"access_report_mrp_inout","report.mrp.inout","model_report_mrp_inout","mrp.group_mrp_manager",1,0,0,0
|
||||
"access_product_product_manager","product.product manager","model_product_product","mrp.group_mrp_manager",1,1,1,1
|
||||
|
|
|
|
@ -20,6 +20,9 @@
|
|||
type: product
|
||||
uom_id: product_uom_litre0
|
||||
uom_po_id: product_uom_litre0
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Orange.
|
||||
-
|
||||
|
@ -35,6 +38,9 @@
|
|||
type: product
|
||||
uom_id: product.product_uom_kgm
|
||||
uom_po_id: product.product_uom_kgm
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Sugar.
|
||||
-
|
||||
|
@ -50,6 +56,9 @@
|
|||
type: product
|
||||
uom_id: product.product_uom_kgm
|
||||
uom_po_id: product.product_uom_kgm
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Water.
|
||||
-
|
||||
|
@ -61,6 +70,9 @@
|
|||
type: consu
|
||||
uom_id: product_uom_litre0
|
||||
uom_po_id: product_uom_litre0
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I define the BoM to produce an orange juice.
|
||||
-
|
||||
|
|
|
@ -221,8 +221,7 @@
|
|||
-
|
||||
!record {model: stock.partial.picking, id: stock_partial_picking0}:
|
||||
date: '2010-04-30 16:53:36'
|
||||
partner_id: base.res_partner_maxtor
|
||||
address_id: base.res_partner_address_wong
|
||||
|
||||
-
|
||||
I make my picking done.
|
||||
-
|
||||
|
@ -231,8 +230,6 @@
|
|||
picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Wong'),('state','=','assigned')])
|
||||
partial = self.browse(cr, uid, 1, context)
|
||||
partial_datas = {
|
||||
'partner_id' : partial.partner_id and partial.partner_id.id or False,
|
||||
'address_id' : partial.address_id and partial.address_id.id or False,
|
||||
'delivery_date' : partial.date
|
||||
}
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids):
|
||||
|
@ -260,8 +257,7 @@
|
|||
-
|
||||
!record {model: stock.partial.picking, id: stock_partial_picking0}:
|
||||
date: '2010-04-30 16:53:36'
|
||||
partner_id: base.res_partner_maxtor
|
||||
address_id: base.res_partner_address_wong
|
||||
|
||||
-
|
||||
I make my picking done.
|
||||
-
|
||||
|
@ -270,8 +266,6 @@
|
|||
picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Tang'),('state','=','assigned')])
|
||||
partial = self.browse(cr, uid, 1, context)
|
||||
partial_datas = {
|
||||
'partner_id': partial.partner_id and partial.partner_id.id or False,
|
||||
'address_id': partial.address_id and partial.address_id.id or False,
|
||||
'delivery_date': partial.date
|
||||
}
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids):
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<field name="product_qty"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="change_prod_qty" string="Validate"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<field name="number"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="print_report" string="Print"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
@ -27,7 +27,7 @@
|
|||
src_model="product.product"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
key2="client_print_multi"
|
||||
id="action_view_mrp_product_price_wizard"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -43,6 +43,7 @@ class mrp_product_produce(osv.osv_memory):
|
|||
context['active_id'], context=context)
|
||||
done = 0.0
|
||||
for move in prod.move_created_ids2:
|
||||
if not move.scraped:
|
||||
done += move.product_qty
|
||||
return (prod.product_qty - done) or prod.product_qty
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
<separator string="" colspan="4" />
|
||||
<label string="" colspan="2" />
|
||||
<group col="2" colspan="1">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="do_produce" string="Confirm"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<field name="measure_unit"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="print_report" string="Print"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
@ -28,8 +28,8 @@
|
|||
res_model="mrp.workcenter.load"
|
||||
src_model="mrp.workcenter"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
target="new"
|
||||
key2="client_print_multi"
|
||||
id="action_mrp_workcenter_load_wizard"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -72,10 +72,10 @@
|
|||
<group colspan="8" col="8">
|
||||
<field name="state"/>
|
||||
<button name="button_draft" string="Set Draft" states="cancel" icon="gtk-convert"/>
|
||||
<button name="button_start_working" string="Start" states="draft" icon="gtk-execute"/>
|
||||
<button name="button_start_working" string="Start" states="draft" icon="gtk-go-forward"/>
|
||||
<button name="button_resume" string="Resume" states="pause" icon="gtk-media-pause"/>
|
||||
<button name="button_cancel" string="Cancel" states="draft,startworking" icon="gtk-cancel"/>
|
||||
<button name="button_pause" string="Pause" states="startworking" icon="gtk-execute"/>
|
||||
<button name="button_pause" string="Pause" states="startworking" icon="gtk-media-pause"/>
|
||||
<button name="button_done" string="Finished" states="startworking" icon="gtk-ok"/>
|
||||
</group>
|
||||
</page>
|
||||
|
@ -89,16 +89,33 @@
|
|||
<field name="model">mrp.production.workcenter.line</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Work Orders">
|
||||
<group col='6' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="workcenter_id"/>
|
||||
<field name="production_id"/>
|
||||
</group>
|
||||
<search string="Search Work Orders">
|
||||
<group col='9' colspan='4'>
|
||||
<filter icon="terp-document-new" string="Draft"
|
||||
domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-check" string="In Progress" name="Current"
|
||||
default="1"
|
||||
domain="[('state','=','startworking')]"/>
|
||||
<filter icon="terp-gtk-media-pause" string="Pending"
|
||||
domain="[('state','=','pause')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-gnome-cpu-frequency-applet+" string="Late"
|
||||
domain="['&', ('date_planned::date','<', current_date), ('state', 'in', ('draft', 'confirmed', 'ready'))]"
|
||||
help="Production started late" />
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
<field name="workcenter_id" widget="selection"/>
|
||||
<field name="production_id" />
|
||||
<field name="state" />
|
||||
<field name="date_planned" widget="date"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By" colspan="10" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product'}"/>
|
||||
<filter string="Workcenter" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'workcenter_id'}"/>
|
||||
<filter string="Production" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'production_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_planned'}"/>
|
||||
</group>
|
||||
</search>
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
'mrp_repair_report.xml',
|
||||
],
|
||||
'demo_xml': [],
|
||||
'test': ['test/test_mrp_repair.yml'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'certificate': '0060814381277',
|
||||
|
|
|
@ -344,7 +344,7 @@ class mrp_repair(osv.osv):
|
|||
'origin': invoice.origin+', '+repair.name,
|
||||
'comment':(comment and (invoice.comment and invoice.comment+"\n"+comment or comment)) or (invoice.comment and invoice.comment or ''),
|
||||
}
|
||||
invoice_obj.write(cr, uid, [inv_id], invoice_vals, context=context)
|
||||
inv_obj.write(cr, uid, [inv_id], invoice_vals, context=context)
|
||||
else:
|
||||
if not repair.partner_id.property_account_receivable:
|
||||
raise osv.except_osv(_('Error !'), _('No account defined for partner "%s".') % repair.partner_id.name )
|
||||
|
|
|
@ -100,8 +100,8 @@
|
|||
<group col="13" colspan="4">
|
||||
<field name="state"/>
|
||||
<button name="repair_confirm" states="draft" string="Confirm Repair" icon="gtk-apply"/>
|
||||
<button name="repair_ready" states="confirmed" string="Start Repair" icon="gtk-execute"/>
|
||||
<button name="action_repair_start" states="ready" string="Start Repair" icon="gtk-execute"/>
|
||||
<button name="repair_ready" states="confirmed" string="Start Repair" icon="gtk-go-forward"/>
|
||||
<button name="action_repair_start" states="ready" string="Start Repair" icon="gtk-go-forward"/>
|
||||
<button name="action_repair_end" states="under_repair" string="End Repair" icon="gtk-ok"/>
|
||||
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice" icon="gtk-convert"/>
|
||||
<button name="invoice_corrected" states="invoice_except" string="Invoice Corrected" icon="gtk-apply"/>
|
||||
|
@ -179,26 +179,30 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Search Reair Orders">
|
||||
<group col='4' colspan='4'>
|
||||
<field name="name" />
|
||||
<field name="product_id" />
|
||||
<filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-check" string="Confirmed" domain="[('state','=', 'confirmed)]" name="current" />
|
||||
<filter icon="terp-emblem-important" string="Ready To Repair" domain="[('state','=','ready')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-dolar" string="invoiced" domain="[('state','=','2binvoiced')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="state" />
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="10" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'guarantee_limit'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_order_form" model="ir.actions.act_window">
|
||||
<field name="name">New Repair</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="action_repair_order_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repair Orders</field>
|
||||
|
@ -207,49 +211,9 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_repair_order_form_filter"/>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_quotation_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs in quotation</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_progress_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs in progress</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','under_repair')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_ready_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs Ready to Start</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','!=','draft'),('state','!=','under_repair'),('state','!=','2binvoiced'),('state','!=','invoice_except'),('state','!=','done'),('state','!=','cancel'),]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_2binvoiced_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs to be invoiced</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','2binvoiced')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_repair_order_tree" id="menu_repair_order" parent="mrp.menu_mrp_manufacturing" name="Repairs" sequence="50"/>
|
||||
<menuitem action="action_repair_order_tree" id="menu_repair_order" parent="mrp.menu_mrp_manufacturing" name="Repair Orders" sequence="50"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
- |
|
||||
In order to test "mrp_repair" module, I start with creating repairt order, confirm it, and start repair.
|
||||
|
||||
- |
|
||||
Given that I have already stock move line created.
|
||||
-
|
||||
!record {model: stock.move, id: stock_move_pcbasicpc0}:
|
||||
company_id: base.main_company
|
||||
date: '2010-06-24 20:10:28'
|
||||
date_expected: '2010-06-24 20:10:55'
|
||||
date_planned: '2010-06-24 20:10:28'
|
||||
location_dest_id: stock.stock_location_stock
|
||||
location_id: stock.stock_location_stock
|
||||
name: '[PC1] Basic PC'
|
||||
product_id: product.product_product_pc1
|
||||
product_qty: 1.0
|
||||
product_uom: product.product_uom_unit
|
||||
product_uos_qty: 1.0
|
||||
|
||||
- |
|
||||
I start by creating new Repair order for "Basic Pc" product.
|
||||
-
|
||||
!record {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
address_id: base.res_partner_address_1
|
||||
guarantee_limit: '2010-06-24'
|
||||
invoice_method: 'after_repair'
|
||||
partner_invoice_id: base.res_partner_address_1
|
||||
location_dest_id: stock.stock_location_14
|
||||
location_id: stock.stock_location_14
|
||||
move_id: 'stock_move_pcbasicpc0'
|
||||
name: RMA00004
|
||||
operations:
|
||||
- location_dest_id: stock.location_production
|
||||
location_id: stock.stock_location_stock
|
||||
name: '[HDD1] HDD Seagate 7200.8 80GB'
|
||||
price_unit: 50.0
|
||||
product_id: product.product_product_hdd1
|
||||
product_uom: product.product_uom_unit
|
||||
product_uom_qty: 1.0
|
||||
state: draft
|
||||
to_invoice: 1
|
||||
type: add
|
||||
partner_id: base.res_partner_9
|
||||
product_id: product.product_product_pc1
|
||||
|
||||
- |
|
||||
I check that Repair order is in "Draft" state.
|
||||
-
|
||||
!assert {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
- state == 'draft'
|
||||
|
||||
- |
|
||||
I confirm This Repair order.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: repair_confirm, ref: mrp_repair_rma0}
|
||||
|
||||
- |
|
||||
I start the repairing process by click on "Start Repair" Button.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: repair_ready, ref: mrp_repair_rma0}
|
||||
|
||||
- |
|
||||
I check that state is "Under Repair".
|
||||
-
|
||||
!assert {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
- state == 'under_repair'
|
||||
- |
|
||||
Repairing Process for product is Done and I End Repair process by click on "End Repair" button.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: action_repair_end, ref: mrp_repair_rma0}
|
||||
- |
|
||||
I select invoiced after repair option in this "RMA00004" Repair order.
|
||||
so I create Invoice by click on "Make Invoice" wizard.
|
||||
-
|
||||
!record {model: mrp.repair.make_invoice, id: mrp_repair_make_invoice_0}:
|
||||
group: 1
|
||||
- |
|
||||
I click on "Create Invoice" button of this wizard to make invoice.
|
||||
-
|
||||
!python {model: mrp.repair.make_invoice}: |
|
||||
self.make_invoices(cr, uid, [ref("mrp_repair_make_invoice_0")], {"active_ids": [ref("mrp_repair.mrp_repair_rma0")]})
|
||||
- |
|
||||
I check that Invoice is created for this repair order.
|
||||
-
|
||||
!python {model: mrp.repair}: |
|
||||
obj_lines = self.pool.get('account.invoice.line')
|
||||
inv_obj = self.pool.get('account.invoice')
|
||||
repair_id = self.browse(cr, uid, [ref('mrp_repair_rma0')], context=context)[0]
|
||||
invoice_ids = inv_obj.search(cr, uid, [('partner_id', '=', repair_id.partner_invoice_id.id)])
|
||||
invoice_id = inv_obj.browse(cr, uid, invoice_ids)[0]
|
||||
|
||||
assert repair_id.partner_invoice_id == invoice_id.partner_id
|
||||
|
||||
for operation in repair_id.operations:
|
||||
if operation.to_invoice == True:
|
||||
line_ids = obj_lines.search(cr, uid, [('product_id', '=', operation.product_id.id), ('invoice_id', '=', invoice_id.id), ('price_unit', '=', operation.price_unit)])
|
||||
if line_ids:
|
||||
line_id = obj_lines.browse(cr, uid, line_ids)[0]
|
||||
assert line_id.product_id == operation.product_id
|
|
@ -10,12 +10,12 @@
|
|||
<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 invoice(s) ?" />
|
||||
<field name="group"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<separator colspan="4" string="Do you really want to create the invoice(s) ?" />
|
||||
<field name="group"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="make_invoices" string="Create Invoice"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<field name="model">procurement.order</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Procurement Lines" colors="red:date_planned<current_date and state in ('exception');black:state=='running';green:state=='confirmed';gray:state in ['done','cancel'];blue:state in ('ready')">
|
||||
<tree string="Procurement Lines" colors="red:date_planned<current_date and state in ('exception');black:state=='running';darkgreen:state=='confirmed';gray:state in ['done','cancel'];blue:state in ('ready')">
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="origin"/>
|
||||
<field name="product_id"/>
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
<field name="manager"/>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Manager" icon="terp-personal" domain="[]" context="{'group_by':'manager'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -58,6 +62,8 @@
|
|||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Resource" icon="terp-personal" domain="[]" context="{'group_by':'resource_id'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_from'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
|
|
@ -69,6 +69,8 @@ class product_product(osv.osv):
|
|||
property_obj=self.pool.get('ir.property')
|
||||
product_obj=self.browse(cr,uid,ids)[0]
|
||||
account_variation = product_obj.categ_id.property_stock_variation
|
||||
account_variation_id = account_variation and account_variation.id or False
|
||||
if not account_variation_id: raise osv.except_osv(_('Error!'), _('Variation Account is not specified for Product Category: %s' % (product_obj.categ_id.name)))
|
||||
move_ids = []
|
||||
loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
|
||||
for rec_id in ids:
|
||||
|
@ -82,13 +84,10 @@ class product_product(osv.osv):
|
|||
product = self.browse(cr, uid, rec_id, context=c)
|
||||
qty = product.qty_available
|
||||
diff = product.standard_price - new_price
|
||||
assert diff, _("Could not find any difference between standard price and new price!")
|
||||
if not diff: raise osv.except_osv(_('Error!'), _("Could not find any difference between standard price and new price!"))
|
||||
if qty:
|
||||
location_account = account_variation and account_variation.id or False
|
||||
|
||||
company_id = location.company_id and location.company_id.id or False
|
||||
assert location_account, _('Inventory Account is not specified for Location: %s' % (location.name))
|
||||
assert company_id, _('Company is not specified in Location')
|
||||
if not company_id: raise osv.except_osv(_('Error!'), _('Company is not specified in Location'))
|
||||
#
|
||||
# Accounting Entries
|
||||
#
|
||||
|
@ -129,8 +128,8 @@ class product_product(osv.osv):
|
|||
'move_id': move_id,
|
||||
})
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': location.name,
|
||||
'account_id': location_account,
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_variation_id,
|
||||
'credit': amount_diff,
|
||||
'move_id': move_id
|
||||
})
|
||||
|
@ -155,8 +154,8 @@ class product_product(osv.osv):
|
|||
'move_id': move_id
|
||||
})
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': location.name,
|
||||
'account_id': location_account,
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_variation_id,
|
||||
'debit': amount_diff,
|
||||
'move_id': move_id
|
||||
})
|
||||
|
@ -429,7 +428,7 @@ class product_category(osv.osv):
|
|||
'property_stock_variation': fields.property('account.account',
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Stock variation Account",
|
||||
string="Stock Variation Account",
|
||||
method=True, view_load=True,
|
||||
help="This account will be used in product when valuation type is real-time valuation ",),
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<separator string="Accounting Stock Properties" colspan="2"/>
|
||||
<field name="property_stock_account_input_categ" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="property_stock_account_output_categ" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="property_stock_variation"/>
|
||||
<field name="property_stock_journal"/>
|
||||
</group>
|
||||
</form>
|
||||
|
|
Loading…
Reference in New Issue