def get_bom_superset(regen=False): global superset_cobom if not regen and superset_cobom is not None: return superset_cobom prototypes = get_prototype_lib() boms = [] logger.info("Building superset composite BOM") for ident, prototype in prototypes.iteritems(): boms.append(prototype.obom) logger.info("Collating into superset composite BOM") superset_cobom = CompositeOutputBom(boms, name='ALL') superset_cobom.collapse_wires() return superset_cobom
def get_bom_superset(regen=False): global superset_cobom if not regen and superset_cobom is not None: return superset_cobom prototypes = get_prototype_lib() boms = [] logger.info("Building superset composite BOM") for ident, prototype in viewitems(prototypes): logger.info("Adding {0} to superset cobom...".format(ident)) boms.append(prototype.obom) logger.info("Collating into superset composite BOM") superset_cobom = CompositeOutputBom(boms, name='ALL') superset_cobom.collapse_wires() return superset_cobom
def _process(self, outfolder=None, manifestsfolder=None, label_manager=None, register=False, force=False, pb_class=None, stacked_pb=False, leaf_pb=True, session=None): self._force = force if pb_class is None: pb_class = TendrilProgressBar if stacked_pb is True: pb = pb_class(max=8) else: pb = DummyProgressBar(max=8) pb.next(note="Constructing Resources for Production Order Generation") if outfolder is None: if self._order_yaml_path is not None: outfolder = os.path.split(self._order_yaml_path)[0] else: raise AttributeError('Output folder needs to be defined') if manifestsfolder is None: manifestsfolder = os.path.join(outfolder, 'manifests') if not os.path.exists(manifestsfolder): os.makedirs(manifestsfolder) if self._sno is None: self._sno = serialnos.get_serialno( series='PROD', efield=self._title, register=register, session=session ) # Create Snomap if self._snomap_path is not None: with open(self._snomap_path, 'r') as f: self._snomap = SerialNumberMap(yaml.load(f), self._sno) else: self._snomap = SerialNumberMap({}, self._sno) self._snomap.set_session(session=session) if register is True: self._snomap.enable_creation() indent_sno = self._snomap.get_sno('indentsno') if register is True: serialnos.link_serialno(child=indent_sno, parent=self.serialno, verbose=False, session=session) # Create cards and deltas and so forth pb.next(note="Constructing Production Order Actions") actions = self.card_actions + self.delta_actions pb.next(note="Executing Production Order Actions") for action in actions: if register is False: action.scaffold = True action.set_session(session=session) action.commit( outfolder=manifestsfolder, indent_sno=indent_sno, prod_ord_sno=self._sno, register=register, session=session, pb_class=pb_class, stacked_pb=stacked_pb, leaf_pb=leaf_pb, ) self._snomap.disable_creation() pb.next(note="Constructing Composite Output BOM") cobom = CompositeOutputBom(self.bomlist) pb.next(note="Creating Indent(s)") self._process_indents( indent_sno=indent_sno, cobom=cobom, outfolder=outfolder, register=register, force=force, session=session ) pb.next(note="Generating Production Order Document") # Make production order doc self._last_generated_at = arrow.utcnow().isoformat() if self._first_generated_at is None: self._first_generated_at = arrow.utcnow().isoformat() self._dump_order_yaml(outfolder=outfolder, register=register, session=session) self._generate_doc(outfolder=outfolder, register=register, session=session) pb.next(note="Generating Labels") self.make_labels(label_manager=label_manager, pb_class=pb_class, stacked_pb=stacked_pb, leaf_pb=leaf_pb) pb.next(note="Finalizing Production Order") for action in actions: action.scaffold = False action.unset_session() self._snomap.dump_to_file(outfolder) self._snomap.unset_session() if register is True: docstore.register_document( serialno=self.serialno, docpath=os.path.join(outfolder, 'snomap.yaml'), doctype='SNO MAP', efield=self.title, verbose=False, session=session ) pb.finish() self._defined = True
class ProductPrototypeBase(PrototypeBase): def __init__(self, fpath): super(ProductPrototypeBase, self).__init__() self._fpath = fpath self._raw_data = None self._product_info = None self._cards = None self._card_names = None self._cables = None self._cable_names = None self._labels = None self._boms = None self._obom = None self._sourcing_errors = None self._indicative_cost_hierarchical_breakup = None self._load_product_info() def _load_product_info(self): with open(self._fpath, 'r') as f: self._raw_data = yaml.load(f) self._name = self._raw_data['name'] self._card_names = self._raw_data['cards'] self._cable_names = self._raw_data['cables'] self._labels = self._raw_data['labels'] # TODO Some products don't have a viable core. Allowances must be made # Eg QM anf QI. self._core = self._raw_data['derive_sno_from'] self._calibformat = self._raw_data['calibformat'] try: self._product_info = \ INSTANCE_PRODUCT_CLASSES.get_product_info_class( self._raw_data['productinfo']['line'], infodict=self._raw_data['productinfo'], parent=self ) except ImportError: self._product_info = ProductInfo( infodict=self._raw_data['productinfo'], parent=self) @property def ident(self): if self.info.version: return "{0} v{1}".format(self.name, self.version) else: return self.name @property def version(self): return self._product_info.version @property def name(self): return self._name @property def info(self): return self._product_info @property def core(self): return self._core @staticmethod def _parse_listing(listing): rval = [] for cname in listing: if cname is None: continue if isinstance(cname, dict): qty = cname['qty'] try: cname = cname['card'] except KeyError: cname = cname['cable'] else: qty = 1 cname = cname rval.append((cname, qty)) return rval @property def card_listing(self): return self._parse_listing(self._card_names) @property def cable_listing(self): return self._parse_listing(self._cable_names) @property def module_listing(self): return {k: v for k, v in (self.card_listing + self.cable_listing)} @staticmethod def _get_modules(parsed_listing): rval = [] pl = get_prototype_lib() for cname in parsed_listing: rval.append((pl[cname[0]], cname[1])) return rval @property def cards(self): if self._cards is None: self._cards = self._get_modules(self.card_listing) return self._cards @property def cables(self): if self._cables is None: self._cables = self._get_modules(self.cable_listing) return self._cables @property def labels(self): return self._labels def labelinfo(self, sno): return self._product_info.labelinfo(sno) @property def calibformat(self): return self._calibformat def get_component_snos(self): pass def make_labels(self, sno, label_manager=None): if label_manager is None: label_manager = manager labelinfo = self.labelinfo(sno) if labelinfo is not None: for l in self.labels: label_manager.add_label(l['type'], self.name, labelinfo[0], **labelinfo[1]) @property def desc(self): return self._product_info.desc def _get_status(self): self._status = self._product_info.status def _construct_components(self): components = [] for card, qty in self.cards: for i in range(qty): components.append(card) for cable, qty in self.cables: for i in range(qty): components.append(cable) return components def _construct_bom(self): self._boms = [x.obom for x in self._construct_components()] self._obom = CompositeOutputBom(self._boms, name=self.ident) self._obom.collapse_wires() @property def boms(self): if self._boms is None: self._construct_bom() return self._boms @property def obom(self): if self._obom is None: self._construct_bom() return self._obom @property def bom(self): raise NotImplementedError @property def indicative_cost(self): return self.obom.indicative_cost @property def sourcing_errors(self): if self._sourcing_errors is None: self._sourcing_errors = self.obom.sourcing_errors return self._sourcing_errors @property def indicative_cost_breakup(self): return self.obom.indicative_cost_breakup @property def indicative_cost_hierarchical_breakup(self): if self._indicative_cost_hierarchical_breakup is None: breakups = [ x.indicative_cost_hierarchical_breakup for x in self._construct_components() ] if len(breakups) == 1: return breakups[0] rval = HierachicalCostingBreakup(self.ident) for breakup in breakups: rval.insert(breakup.name, breakup) self._indicative_cost_hierarchical_breakup = rval return self._indicative_cost_hierarchical_breakup @property def _changelogpath(self): raise NotImplementedError def _reload(self): raise NotImplementedError def _register_for_changes(self): raise NotImplementedError def _validate(self): pass
def _construct_bom(self): self._boms = [x.obom for x in self._construct_components()] self._obom = CompositeOutputBom(self._boms, name=self.ident) self._obom.collapse_wires()
def new_indent(indent_sno=None): form = CreateIndentForm(parent_indent_sno=indent_sno) stage = {'crumbroot': '/inventory'} if form.validate_on_submit(): try: with get_session() as session: sno = form.indent_sno.sno.data if not sno: if indent_sno is not None: sno = form.get_supplementary_sno_default() register_serialno(sno=sno, efield="WEB FRONTEND INDENT", session=session) else: sno = get_serialno(series='IDT', efield='WEB FRONTEND INDENT', register=True, session=session) else: # additional sno validation? pass nindent = InventoryIndent(sno=sno, session=session) # Construct COBOM obom = create_obom_from_listing(form.components.data, 'MANUAL (WEB)') cobom = CompositeOutputBom([obom], name='MANUAL (WEB) {0}'.format(sno)) requested_by = get_username_from_full_name( full_name=form.user.data, session=session) icparams = { 'cobom': cobom, 'title': form.indent_title.data, 'desc': form.indent_desc.data, 'requested_by': requested_by, 'rdate': form.rdate.data or arrow.utcnow(), 'indent_type': form.indent_type.data, } nindent.create(**icparams) root_order_sno = form.root_order_sno.data prod_order_sno = form.prod_order_sno.data try: nindent.define_auth_chain(prod_order_sno=prod_order_sno, root_order_sno=root_order_sno, session=session) except AuthChainNotValidError: raise nindent.register_auth_chain(session=session) fe_workspace_path = os.path.join(TEMPDIR, 'frontend') if not os.path.exists(fe_workspace_path): os.makedirs(fe_workspace_path) workspace_path = os.path.join(fe_workspace_path, get_tempname()) os.makedirs(workspace_path) nindent.process(outfolder=workspace_path, register=True, session=session) shutil.rmtree(workspace_path) return redirect(url_for('.indent', indent_sno=str(sno))) except AuthChainNotValidError: stage['auth_not_valid'] = True if indent_sno is None: stage_crumbs = { 'breadcrumbs': [ Crumb(name="Inventory", path=""), Crumb(name="Indent", path="indent/"), Crumb(name="New", path="indent/new") ], } pagetitle = "Create New Indent" else: stage_crumbs = { 'breadcrumbs': [ Crumb(name="Inventory", path=""), Crumb(name="Indent", path="indent/"), Crumb(name=indent_sno, path="indent/" + indent_sno), Crumb(name="New", path='/'.join(["indent", indent_sno, "/new"])), ] } pagetitle = "New Supplementary Indent for " + indent_sno stage.update(stage_crumbs) return render_template('indent_new.html', stage=stage, form=form, pagetitle=pagetitle)
class ProductPrototypeBase(PrototypeBase): def __init__(self, fpath): super(ProductPrototypeBase, self).__init__() self._fpath = fpath self._raw_data = None self._product_info = None self._cards = None self._card_names = None self._cables = None self._cable_names = None self._labels = None self._boms = None self._obom = None self._sourcing_errors = None self._indicative_cost_hierarchical_breakup = None self._load_product_info() def _load_product_info(self): with open(self._fpath, 'r') as f: self._raw_data = yaml.load(f) self._name = self._raw_data['name'] self._card_names = self._raw_data['cards'] self._cable_names = self._raw_data['cables'] self._labels = self._raw_data['labels'] # TODO Some products don't have a viable core. Allowances must be made # Eg QM anf QI. self._core = self._raw_data['derive_sno_from'] self._calibformat = self._raw_data['calibformat'] try: self._product_info = \ INSTANCE_PRODUCT_CLASSES.get_product_info_class( self._raw_data['productinfo']['line'], infodict=self._raw_data['productinfo'], parent=self ) except ImportError: self._product_info = ProductInfo( infodict=self._raw_data['productinfo'], parent=self ) @property def ident(self): if self.info.version: return "{0} v{1}".format(self.name, self.version) else: return self.name @property def version(self): return self._product_info.version @property def name(self): return self._name @property def info(self): return self._product_info @property def core(self): return self._core @staticmethod def _parse_listing(listing): rval = [] for cname in listing: if cname is None: continue if isinstance(cname, dict): qty = cname['qty'] try: cname = cname['card'] except KeyError: cname = cname['cable'] else: qty = 1 cname = cname rval.append((cname, qty)) return rval @property def card_listing(self): return self._parse_listing(self._card_names) @property def cable_listing(self): return self._parse_listing(self._cable_names) @property def module_listing(self): return {k: v for k, v in (self.card_listing + self.cable_listing)} @staticmethod def _get_modules(parsed_listing): rval = [] pl = get_prototype_lib() for cname in parsed_listing: rval.append((pl[cname[0]], cname[1])) return rval @property def cards(self): if self._cards is None: self._cards = self._get_modules(self.card_listing) return self._cards @property def cables(self): if self._cables is None: self._cables = self._get_modules(self.cable_listing) return self._cables @property def labels(self): return self._labels def labelinfo(self, sno): return self._product_info.labelinfo(sno) @property def calibformat(self): return self._calibformat def get_component_snos(self): pass def make_labels(self, sno, label_manager=None): if label_manager is None: label_manager = manager labelinfo = self.labelinfo(sno) if labelinfo is not None: for l in self.labels: label_manager.add_label( l['type'], self.name, labelinfo[0], **labelinfo[1] ) @property def desc(self): return self._product_info.desc def _get_status(self): self._status = self._product_info.status def _construct_components(self): components = [] for card, qty in self.cards: for i in range(qty): components.append(card) for cable, qty in self.cables: for i in range(qty): components.append(cable) return components def _construct_bom(self): self._boms = [x.obom for x in self._construct_components()] self._obom = CompositeOutputBom(self._boms, name=self.ident) self._obom.collapse_wires() @property def boms(self): if self._boms is None: self._construct_bom() return self._boms @property def obom(self): if self._obom is None: self._construct_bom() return self._obom @property def bom(self): raise NotImplementedError @property def indicative_cost(self): return self.obom.indicative_cost @property def sourcing_errors(self): if self._sourcing_errors is None: self._sourcing_errors = self.obom.sourcing_errors return self._sourcing_errors @property def indicative_cost_breakup(self): return self.obom.indicative_cost_breakup @property def indicative_cost_hierarchical_breakup(self): if self._indicative_cost_hierarchical_breakup is None: breakups = [x.indicative_cost_hierarchical_breakup for x in self._construct_components()] if len(breakups) == 1: return breakups[0] rval = HierachicalCostingBreakup(self.ident) for breakup in breakups: rval.insert(breakup.name, breakup) self._indicative_cost_hierarchical_breakup = rval return self._indicative_cost_hierarchical_breakup @property def _changelogpath(self): raise NotImplementedError def _reload(self): raise NotImplementedError def _register_for_changes(self): raise NotImplementedError def _validate(self): pass