def _run_manufacture(self, procurements): productions_values_by_company = defaultdict(list) errors = [] for procurement, rule in procurements: bom = self._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) if not bom: msg = _('There is no Bill of Material of type manufacture or kit found for the product %s. Please define a Bill of Material for this product.') % (procurement.product_id.display_name,) errors.append((procurement, msg)) productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom)) if errors: raise ProcurementException(errors) for company_id, productions_values in productions_values_by_company.items(): # create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(productions_values) self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) productions.filtered(lambda p: p.move_raw_ids).action_confirm() for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[0].raw_material_production_id or False orderpoint = production.orderpoint_id if orderpoint: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': orderpoint}, subtype_id=self.env.ref('mail.mt_note').id) if origin_production: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': origin_production}, subtype_id=self.env.ref('mail.mt_note').id) return True
def _run_manufacture(self, procurements): productions_values_by_company = defaultdict(list) errors = [] for procurement, rule in procurements: bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom)) if errors: raise ProcurementException(errors) for company_id, productions_values in productions_values_by_company.items(): # create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(productions_values) self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions._create_workorder() productions.action_confirm() for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[0].raw_material_production_id or False orderpoint = production.orderpoint_id if orderpoint: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': orderpoint}, subtype_id=self.env.ref('mail.mt_note').id) if origin_production: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': origin_production}, subtype_id=self.env.ref('mail.mt_note').id) return True
def _run_manufacture(self, procurements): productions_values_by_company = defaultdict(list) errors = [] for procurement, rule in procurements: if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0: # If procurement contains negative quantity, don't create a MO that would be for a negative value. continue bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom)) if errors: raise ProcurementException(errors) for company_id, productions_values in productions_values_by_company.items(): # create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(productions_values) self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions._create_workorder() productions.filtered(lambda p: not p.orderpoint_id).action_confirm() for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[0].raw_material_production_id or False orderpoint = production.orderpoint_id if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual': production.message_post( body=_('This production order has been created from Replenishment Report.'), message_type='comment', subtype_xmlid='mail.mt_note') elif orderpoint: production.message_post_with_view( 'mail.message_origin_link', values={'self': production, 'origin': orderpoint}, subtype_id=self.env.ref('mail.mt_note').id) elif origin_production: production.message_post_with_view( 'mail.message_origin_link', values={'self': production, 'origin': origin_production}, subtype_id=self.env.ref('mail.mt_note').id) return True
def _run_buy(self, procurements): procurements_by_po_domain = defaultdict(list) errors = [] for procurement, rule in procurements: # Get the schedule date in order to find a valid seller procurement_date_planned = fields.Datetime.from_string( procurement.values['date_planned']) schedule_date = ( procurement_date_planned - relativedelta(days=procurement.company_id.po_lead)) supplier = False if procurement.values.get('supplierinfo_id'): supplier = procurement.values['supplierinfo_id'] else: supplier = procurement.product_id.with_company( procurement.company_id.id)._select_seller( partner_id=procurement.values.get("supplierinfo_name"), quantity=procurement.product_qty, date=schedule_date.date(), uom_id=procurement.product_uom) # Fall back on a supplier for which no price may be defined. Not ideal, but better than # blocking the user. supplier = supplier or procurement.product_id._prepare_sellers( False).filtered(lambda s: not s.company_id or s.company_id == procurement.company_id)[:1] if not supplier: msg = _( 'There is no matching vendor price to generate the purchase order for product %s (no vendor defined, minimum quantity not reached, dates not valid, ...). Go on the product form and complete the list of vendors.' ) % (procurement.product_id.display_name) errors.append((procurement, msg)) partner = supplier.name # we put `supplier_info` in values for extensibility purposes procurement.values['supplier'] = supplier procurement.values['propagate_cancel'] = rule.propagate_cancel domain = rule._make_po_get_domain(procurement.company_id, procurement.values, partner) procurements_by_po_domain[domain].append((procurement, rule)) if errors: raise ProcurementException(errors) for domain, procurements_rules in procurements_by_po_domain.items(): # Get the procurements for the current domain. # Get the rules for the current domain. Their only use is to create # the PO if it does not exist. procurements, rules = zip(*procurements_rules) # Get the set of procurement origin for the current domain. origins = set([p.origin for p in procurements]) # Check if a PO exists for the current domain. po = self.env['purchase.order'].sudo().search( [dom for dom in domain], limit=1) company_id = procurements[0].company_id if not po: # We need a rule to generate the PO. However the rule generated # the same domain for PO and the _prepare_purchase_order method # should only uses the common rules's fields. vals = rules[0]._prepare_purchase_order( company_id, origins, [p.values for p in procurements]) # The company_id is the same for all procurements since # _make_po_get_domain add the company in the domain. # We use SUPERUSER_ID since we don't want the current user to be follower of the PO. # Indeed, the current user may be a user without access to Purchase, or even be a portal user. po = self.env['purchase.order'].with_company( company_id).with_user(SUPERUSER_ID).create(vals) else: # If a purchase order is found, adapt its `origin` field. if po.origin: missing_origins = origins - set(po.origin.split(', ')) if missing_origins: po.write({ 'origin': po.origin + ', ' + ', '.join(missing_origins) }) else: po.write({'origin': ', '.join(origins)}) procurements_to_merge = self._get_procurements_to_merge( procurements) procurements = self._merge_procurements(procurements_to_merge) po_lines_by_product = {} grouped_po_lines = groupby(po.order_line.filtered( lambda l: not l.display_type and l.product_uom == l.product_id. uom_po_id).sorted(lambda l: l.product_id.id), key=lambda l: l.product_id.id) for product, po_lines in grouped_po_lines: po_lines_by_product[product] = self.env[ 'purchase.order.line'].concat(*list(po_lines)) po_line_values = [] for procurement in procurements: po_lines = po_lines_by_product.get( procurement.product_id.id, self.env['purchase.order.line']) po_line = po_lines._find_candidate(*procurement) if po_line: # If the procurement can be merge in an existing line. Directly # write the new values on it. vals = self._update_purchase_order_line( procurement.product_id, procurement.product_qty, procurement.product_uom, company_id, procurement.values, po_line) po_line.write(vals) else: # If it does not exist a PO line for current procurement. # Generate the create values for it and add it to a list in # order to create it in batch. partner = procurement.values['supplier'].name po_line_values.append( self.env['purchase.order.line']. _prepare_purchase_order_line_from_procurement( procurement.product_id, procurement.product_qty, procurement.product_uom, procurement.company_id, procurement.values, po)) self.env['purchase.order.line'].sudo().create(po_line_values)
def _run_manufacture(self, procurements): productions_values_by_company = defaultdict(list) errors = [] for procurement, rule in procurements: bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) if not bom: msg = _('There is no Bill of Material of type manufacture or kit found for the product %s. Please define a Bill of Material for this product.') % ( procurement.product_id.display_name,) errors.append((procurement, msg)) productions_values_by_company[procurement.company_id.id].append( rule._prepare_mo_vals(*procurement, bom)) if errors: raise ProcurementException(errors) for company_id, productions_values in productions_values_by_company.items(): # creck if already exists someone mrp production order with the same production productions_values_check = [] for p in productions_values: print(">>>>>>>>>>>>>>>>>>>>> p:", p) current_qty = p['product_qty'] mrp_production_ids = self.env['mrp.production'].search([ ('product_id', '=', p['product_id']), ('origin', '=', p['origin']), ('state', 'not in', ('cancel', 'done', 'draft'))], order='id') if mrp_production_ids: mrp_qty = sum(m.product_qty for m in mrp_production_ids) diff_qty = current_qty-mrp_qty if diff_qty > 0: p['product_qty'] = diff_qty productions_values_check.append(p) else: break else: productions_values_check.append(p) productions_values = productions_values_check print(">>>>>>>>>>>>>>>>>>>>> productions_values_check:", productions_values_check) # create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) productions = self.env['mrp.production'].with_user( SUPERUSER_ID).sudo().with_company(company_id).create(productions_values) self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions._create_workorder() productions.filtered(lambda p: p.move_raw_ids).action_confirm() for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[ 0].raw_material_production_id or False orderpoint = production.orderpoint_id if orderpoint: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': orderpoint}, subtype_id=self.env.ref('mail.mt_note').id) if origin_production: production.message_post_with_view('mail.message_origin_link', values={'self': production, 'origin': origin_production}, subtype_id=self.env.ref('mail.mt_note').id) return True