Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
    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
Esempio n. 4
0
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
Esempio n. 5
0
 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()
Esempio n. 6
0
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)
Esempio n. 7
0
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
Esempio n. 8
0
 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()