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:
Mod2 (OpenERP) 2010-07-01 19:10:10 +05:30 committed by Harry (OpenERP)
parent 3bc5b6d6a1
commit 62a8a4ac5b
21 changed files with 330 additions and 135 deletions

View File

@ -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:

View File

@ -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}"

View File

@ -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):

View File

@ -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

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
27 access_mrp_production_order mrp.production.order model_mrp_production_order mrp.group_mrp_user 1 0 0 0
28 access_report_workcenter_load report.workcenter.load model_report_workcenter_load mrp.group_mrp_manager 1 0 0 0
29 access_report_mrp_inout report.mrp.inout model_report_mrp_inout mrp.group_mrp_manager 1 0 0 0
30 access_product_product_manager product.product manager model_product_product mrp.group_mrp_manager 1 1 1 1

View File

@ -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.
-

View File

@ -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):

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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="['&amp;', ('date_planned::date','&lt;', 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>

View File

@ -45,6 +45,7 @@
'mrp_repair_report.xml',
],
'demo_xml': [],
'test': ['test/test_mrp_repair.yml'],
'installable': True,
'active': False,
'certificate': '0060814381277',

View File

@ -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 )

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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&lt;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&lt;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"/>

View File

@ -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>

View File

@ -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 ",),
}

View File

@ -26,6 +26,7 @@
<separator string="Accounting Stock Properties" colspan="2"/>
<field name="property_stock_account_input_categ" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]"/>
<field name="property_stock_account_output_categ" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]"/>
<field name="property_stock_variation"/>
<field name="property_stock_journal"/>
</group>
</form>