diff --git a/mrp_secondary_uom/README.rst b/mrp_secondary_uom/README.rst new file mode 100644 index 000000000..1cf9a471e --- /dev/null +++ b/mrp_secondary_uom/README.rst @@ -0,0 +1,30 @@ +======================= +MRP - Secondary UoM v10 +======================= + +This module Manage the Manufacturing process with secondary UoM. + +Installation +============ + +Just select it from available modules to install it, there is no need to extra installations. + +Configuration +============= + +After installing this module, Go to Inventory->Configuration->Setting->Products->Unit of Measures-> +Enable the different units of measure for products (TICK on Some 'products may be sold/purchased in different unit of +measures'). + +Features +======== + +* Allows to manage MRP with Secondary UoM. +* Products to Produce With Secondary UoM. +* Produced Products With Secondary UoM. + +Credits +======= +Developer: Nikhil krishnan @ cybrosys, nikhil@cybrosys.in + + diff --git a/mrp_secondary_uom/__init__.py b/mrp_secondary_uom/__init__.py new file mode 100644 index 000000000..656daadf5 --- /dev/null +++ b/mrp_secondary_uom/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Nikhil krishnan() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +import models diff --git a/mrp_secondary_uom/__manifest__.py b/mrp_secondary_uom/__manifest__.py new file mode 100644 index 000000000..3f00168e4 --- /dev/null +++ b/mrp_secondary_uom/__manifest__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Nikhil krishnan() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +{ + 'name': 'MRP - Secondary UoM', + 'version': '10.0.1.0', + 'category': 'Manufacturing', + 'summary': 'Secondary UoM in Manufacturing Order', + 'description': """ +Manage the Manufacturing process with secondary UoM +=================================================== +This module allows you to cover planning, ordering, stocks and the manufacturing with a Secondary UoM. It handles the +Products to Produce & Produced Products according to the production with Secondary UoM +----------------------------------------------------------------------------------------- +* Allows to manage MRP with Secondary UoM +* Products to Produce With Secondary UoM +* Produced Products With Secondary UoM +""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': "http://www.cybrosys.com", + 'depends': ['mrp'], + 'data': ['views/mrp_sec_uom.xml', + 'data/mrp_sec_uom_round.xml'], + 'images': ['static/description/banner.jpg'], + 'license': 'LGPL-3', + 'installable': True, + 'application': False, +} diff --git a/mrp_secondary_uom/data/mrp_sec_uom_round.xml b/mrp_secondary_uom/data/mrp_sec_uom_round.xml new file mode 100644 index 000000000..2949ee4f0 --- /dev/null +++ b/mrp_secondary_uom/data/mrp_sec_uom_round.xml @@ -0,0 +1,9 @@ + + + + + Secondary UoM Ratio + 10 + + + \ No newline at end of file diff --git a/mrp_secondary_uom/models/__init__.py b/mrp_secondary_uom/models/__init__.py new file mode 100644 index 000000000..b1fd4a670 --- /dev/null +++ b/mrp_secondary_uom/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Nikhil krishnan() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +import mrp_sec_uom +import change_production_qnty diff --git a/mrp_secondary_uom/models/change_production_qnty.py b/mrp_secondary_uom/models/change_production_qnty.py new file mode 100644 index 000000000..4f3072269 --- /dev/null +++ b/mrp_secondary_uom/models/change_production_qnty.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- + +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Nikhil krishnan() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +import math + + +class ChangeProductionQty(models.TransientModel): + _inherit = 'change.production.qty' + + mrp_sec_qty = fields.Float(string='Product Secondary Qty') + mrp_sec_uom = fields.Many2one('product.uom', string='Secondary Unit') + + @api.model + def default_get(self, fields): + res = super(ChangeProductionQty, self).default_get(fields) + prod_obj = self.env['mrp.production'] + prod = prod_obj.browse(self._context.get('active_id')) + if 'product_qty' in fields: + res.update({'product_qty': prod.product_qty}) + if 'mrp_sec_qty' in fields: + res.update({'mrp_sec_qty': prod.mrp_sec_qty}) + if 'mrp_sec_uom' in fields: + res.update({'mrp_sec_uom': prod.mrp_sec_uom.id}) + return res + + @api.model + def _update_product_to_produce(self, production, qty, ratio, sec_uom): + production_move = production.move_finished_ids.filtered(lambda x:x.product_id.id == production.product_id.id and x.state not in ('done', 'cancel')) + + if production_move: + production_move.write({ + 'product_uom_qty': qty, + 'stock_move_sec_uom': sec_uom.id, + 'ratio_sec_uom': ratio, + }) + else: + production_move = production._generate_finished_moves() + production_move = production.move_finished_ids.filtered(lambda x : x.state not in ('done', 'cancel') and production.product_id.id == x.product_id.id) + production_move.write({ + 'product_uom_qty': qty, + 'stock_move_sec_uom': sec_uom.id, + 'ratio_sec_uom': ratio, + }) + + @api.multi + def change_prod_qty(self): + for wizard in self: + production = wizard.mo_id + produced = sum(production.move_finished_ids.mapped('quantity_done')) + if wizard.product_qty < produced: + raise UserError(_("You have already processed %d. Please input a quantity higher than %d ")%(produced, produced)) + ratio = wizard.mrp_sec_qty/wizard.product_qty + production.write({'product_qty': wizard.product_qty, + 'mrp_sec_qty': wizard.mrp_sec_qty, + 'mrp_sec_uom': wizard.mrp_sec_uom.id, + 'mrp_ratio_sec_uom': ratio + }) + factor = production.product_uom_id._compute_quantity(production.product_qty - production.qty_produced, production.bom_id.product_uom_id) / production.bom_id.product_qty + boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id) + for line, line_data in lines: + production._update_raw_move(line, line_data) + operation_bom_qty = {} + for bom, bom_data in boms: + for operation in bom.routing_id.operation_ids: + operation_bom_qty[operation.id] = bom_data['qty'] + + self._update_product_to_produce(production, production.product_qty - production.qty_produced, + ratio, production.mrp_sec_uom) + moves = production.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel')) + moves.do_unreserve() + moves.action_assign() + for wo in production.workorder_ids: + operation = wo.operation_id + if operation_bom_qty.get(operation.id): + cycle_number = math.ceil(operation_bom_qty[operation.id] / operation.workcenter_id.capacity) # TODO: float_round UP + wo.duration_expected = (operation.workcenter_id.time_start + + operation.workcenter_id.time_stop + + cycle_number * operation.time_cycle * 100.0 / operation.workcenter_id.time_efficiency) + if production.product_id.tracking == 'serial': + quantity = 1.0 + else: + quantity = wo.qty_production - wo.qty_produced + quantity = quantity if (quantity > 0) else 0 + wo.qty_producing = quantity + if wo.qty_produced < wo.qty_production and wo.state == 'done': + wo.state = 'progress' + # assign moves; last operation receive all unassigned moves + # TODO: following could be put in a function as it is similar as code in _workorders_create + # TODO: only needed when creating new moves + moves_raw = production.move_raw_ids.filtered(lambda move: move.operation_id == operation and move.state not in ('done', 'cancel')) + if wo == production.workorder_ids[-1]: + moves_raw |= production.move_raw_ids.filtered(lambda move: not move.operation_id) + moves_finished = production.move_finished_ids.filtered(lambda move: move.operation_id == operation) #TODO: code does nothing, unless maybe by_products? + moves_raw.mapped('move_lot_ids').write({'workorder_id': wo.id}) + (moves_finished + moves_raw).write({'workorder_id': wo.id}) + if wo.move_raw_ids.filtered(lambda x: x.product_id.tracking != 'none') and not wo.active_move_lot_ids: + wo._generate_lot_ids() + return {} diff --git a/mrp_secondary_uom/models/mrp_sec_uom.py b/mrp_secondary_uom/models/mrp_sec_uom.py new file mode 100644 index 000000000..e99b268d0 --- /dev/null +++ b/mrp_secondary_uom/models/mrp_sec_uom.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Nikhil krishnan() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +from odoo import models, fields, api +import odoo.addons.decimal_precision as dp + + +class MRPSecUOM(models.Model): + _inherit = 'mrp.production' + + mrp_sec_qty = fields.Float('Secondary Quantity', readonly=True) + mrp_sec_uom = fields.Many2one('product.uom', 'Secondary Unit') + mrp_ratio_sec_uom = fields.Float('Ratio 2ndry Quantity', digits=dp.get_precision('Secondary UoM Ratio')) + + # Over write this fuction for add the new line of code: 'ratio_sec_uom': self.mrp_ratio_sec_uom, + def _generate_finished_moves(self): + move = self.env['stock.move'].create({ + 'name': self.name, + 'date': self.date_planned_start, + 'date_expected': self.date_planned_start, + 'product_id': self.product_id.id, + 'product_uom': self.product_uom_id.id, + 'product_uom_qty': self.product_qty, + 'ratio_sec_uom': self.mrp_ratio_sec_uom, + 'stock_move_sec_uom': self.mrp_sec_uom.id, + 'location_id': self.product_id.property_stock_production.id, + 'location_dest_id': self.location_dest_id.id, + 'move_dest_id': self.procurement_ids and self.procurement_ids[0].move_dest_id.id or False, + 'procurement_id': self.procurement_ids and self.procurement_ids[0].id or False, + 'company_id': self.company_id.id, + 'production_id': self.id, + 'origin': self.name, + 'group_id': self.procurement_group_id.id, + }) + move.action_confirm() + return move + + @api.model + def create(self, vals): + if vals.get('mrp_sec_qty'): + if vals.get('product_qty'): + vals['mrp_ratio_sec_uom'] = float(vals['mrp_sec_qty'])/float(vals['product_qty']) + return super(MRPSecUOM, self).create(vals) + + +class StockMoveSecUOM(models.Model): + _inherit = 'stock.move' + + stock_move_sec_qty_to_produce = fields.Float(string='To Produce (2ndry)', + compute='compute_stock_move_sec_qty_to_produce') + stock_move_sec_uom = fields.Many2one('product.uom', string='2ndry UoM') + stock_move_sec_qty_produced = fields.Float(string='Produced (2ndry)', + compute='compute_stock_move_sec_qty_produced') + ratio_sec_uom = fields.Float(string='Ratio 2ndry Quantity', digits=dp.get_precision('Secondary UoM Ratio')) + + def compute_stock_move_sec_qty_to_produce(self): + for rec in self: + rec.stock_move_sec_qty_to_produce = rec.ratio_sec_uom * rec.product_uom_qty + + def compute_stock_move_sec_qty_produced(self): + for rec in self: + rec.stock_move_sec_qty_produced = rec.ratio_sec_uom * rec.quantity_done + + +class MRPProductProduceSecUOM(models.TransientModel): + _inherit = 'mrp.product.produce' + + product_produce_sec_qty = fields.Float(string='2ndry Quantity') + ratio_sec_uom = fields.Float(string='Ratio 2ndry Quantity', digits=dp.get_precision('Secondary UoM Ratio')) + product_produce_sec_uom = fields.Many2one('product.uom', string='2ndry UoM') + + @api.model + def default_get(self, fields): + res = super(MRPProductProduceSecUOM, self).default_get(fields) + if self._context and self._context.get('active_id'): + production = self.env['mrp.production'].browse(self._context['active_id']) + serial_finished = (production.product_id.tracking == 'serial') + if serial_finished: + sec_qty = production.mrp_ratio_sec_uom + else: + + sec_qty = res['product_qty'] * production.mrp_ratio_sec_uom + + res['product_produce_sec_qty'] = sec_qty + res['product_produce_sec_uom'] = production.mrp_sec_uom.id + res['ratio_sec_uom'] = production.mrp_ratio_sec_uom + return res + + @api.onchange('product_qty', 'product_produce_sec_qty') + def onchange_product_qty(self): + sec_qty = self.product_qty * self.ratio_sec_uom + self.product_produce_sec_qty = sec_qty diff --git a/mrp_secondary_uom/static/description/5.png b/mrp_secondary_uom/static/description/5.png new file mode 100644 index 000000000..b4db1f4b9 Binary files /dev/null and b/mrp_secondary_uom/static/description/5.png differ diff --git a/mrp_secondary_uom/static/description/6.png b/mrp_secondary_uom/static/description/6.png new file mode 100644 index 000000000..a8a01be3f Binary files /dev/null and b/mrp_secondary_uom/static/description/6.png differ diff --git a/mrp_secondary_uom/static/description/Finished Products.png b/mrp_secondary_uom/static/description/Finished Products.png new file mode 100644 index 000000000..2db8a87ce Binary files /dev/null and b/mrp_secondary_uom/static/description/Finished Products.png differ diff --git a/mrp_secondary_uom/static/description/MRP Order.png b/mrp_secondary_uom/static/description/MRP Order.png new file mode 100644 index 000000000..283ed9a9c Binary files /dev/null and b/mrp_secondary_uom/static/description/MRP Order.png differ diff --git a/mrp_secondary_uom/static/description/banner.jpg b/mrp_secondary_uom/static/description/banner.jpg new file mode 100644 index 000000000..626395242 Binary files /dev/null and b/mrp_secondary_uom/static/description/banner.jpg differ diff --git a/mrp_secondary_uom/static/description/change.png b/mrp_secondary_uom/static/description/change.png new file mode 100644 index 000000000..5d44f1a06 Binary files /dev/null and b/mrp_secondary_uom/static/description/change.png differ diff --git a/mrp_secondary_uom/static/description/cybro_logo.png b/mrp_secondary_uom/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/mrp_secondary_uom/static/description/cybro_logo.png differ diff --git a/mrp_secondary_uom/static/description/icon.png b/mrp_secondary_uom/static/description/icon.png new file mode 100644 index 000000000..65c6a9f52 Binary files /dev/null and b/mrp_secondary_uom/static/description/icon.png differ diff --git a/mrp_secondary_uom/static/description/index.html b/mrp_secondary_uom/static/description/index.html new file mode 100644 index 000000000..65bd88804 --- /dev/null +++ b/mrp_secondary_uom/static/description/index.html @@ -0,0 +1,135 @@ +
+
+
+

MRP - Secondary UoM

+

Manage the Manufacturing process with secondary UoM

+

Cybrosys Technologies

+
+
+

Major Features:

+
    +
  •   Allows to manage MRP with Secondary UoM.
  • +
  •    Products to Produce With Secondary UoM.
  • +
  •    Produced Products With Secondary UoM.
  • +
+
+
+
+ +
+
+
+

+

This module allows you to cover planning, ordering, stocks and the manufacturing with a Secondary + UoM. It handles the Products to Produce & Produced Products according to the production with Secondary UoM.

+

+ +
+
+
+ +
+
+
+

+

As shown here, When we create a MO with a Primary and Secondary Product Quantities and UOMs. + After saving, Order is in 'Confirmed' state. Same time we can see a record + created in 'Finished Products' with secondary UoM.

+

+
+
+
+ +
+
+
+
+ +
+
+
+

+

We can change the Primary Quantity, Secondary Quantity and Secondary UoM at any time. There + will be an 'Update' Button to handle the same.

+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+

+

When we click on the 'Produce' button, The same window is appear with Secondary + Quantity and UoM.

+

If we Produce Partially or completely, It automatically calculate the Secondary quantity with same ratio.

+

+
+
+
+ +
+
+
+

+

Update the Produced Products records.

+

+
+ +
+
+ +
+
+
+
+ +
+

Need Any Help?

+ +
+ + + + + + + diff --git a/mrp_secondary_uom/static/description/partial production.png b/mrp_secondary_uom/static/description/partial production.png new file mode 100644 index 000000000..80ff5e60b Binary files /dev/null and b/mrp_secondary_uom/static/description/partial production.png differ diff --git a/mrp_secondary_uom/static/description/update.png b/mrp_secondary_uom/static/description/update.png new file mode 100644 index 000000000..e70d17136 Binary files /dev/null and b/mrp_secondary_uom/static/description/update.png differ diff --git a/mrp_secondary_uom/views/mrp_sec_uom.xml b/mrp_secondary_uom/views/mrp_sec_uom.xml new file mode 100644 index 000000000..368ed1faf --- /dev/null +++ b/mrp_secondary_uom/views/mrp_sec_uom.xml @@ -0,0 +1,64 @@ + + + + + mrp.production.uom.form + mrp.production + + + + + + + + + + + + + + + + + + + + + MRP Product Produce + mrp.product.produce + + + + + + + + + + + + + + + + + + + Change Product Qty + change.production.qty + + + + + + + + + + \ No newline at end of file