Esempio n. 1
0
def create_design():
    """Create new design. This method is always called via AJAX."""
    form = CreateDesignForm(request.form)
    validated, design_numbers = form.validate_on_submit()
    if validated:
        designs = []
        for design_number in design_numbers:
            variables = {
                'design_number': design_number,
                'name': form.name.data,
                'project': form.project.data,
                'revision': form.revision.data,
                'owner': form.owner.data
            }
            # TODO: Create both design and part in one transaction, so if Part create fails, design create fails
            # Create the design
            design = Design.create(**variables)
            # Create part -1 (dash one) on design item
            variables = {
                'design': design,
                'owner': design.owner,
                'part_identifier': 1
            }
            Part.create(**variables)
            designs.append(design.as_dict()
                           )  # For modal if user creates more than one Design
        jsonData = {'designs': designs}
        return jsonify(jsonData), 200, {'ContentType': 'application/json'}
    else:
        response = make_response(
            render_template('design/create_design_modal.html', form=form), 500)
        return response
Esempio n. 2
0
def create_proc():
    """Create new Procedure."""
    form = CreateProcedureForm(request.form)
    validated = form.validate_on_submit()
    if validated:
        kwargs = {
            'name': form.name.data,
            'owner': form.owner.data,
            'project': form.project.data
        }
        procedure = Procedure.create(**kwargs)
        part_ids = [] if request.form['parts'] == '' else request.form[
            'parts'].split(',')
        vendor_part_ids = [] if request.form[
            'vendor_parts'] == '' else request.form['vendor_parts'].split(',')

        for part_id in part_ids:
            part = Part.get_by_id(part_id)
            procedure.parts.append(part)

        for vendor_part_id in vendor_part_ids:
            part = VendorPart.get_by_id(vendor_part_id)
            procedure.vendor_parts.append(part)

        procedure.save()
        jsonData = {'success': True, 'url': procedure.get_url()}
        return jsonify(jsonData), 200, {'ContentType': 'application/json'}
    else:
        part_ids = [] if request.form['parts'] == '' else request.form[
            'parts'].split(',')
        vendor_part_ids = [] if request.form[
            'vendor_parts'] == '' else request.form['vendor_parts'].split(',')
        parts = []
        vendor_parts = []
        for part_id in part_ids:
            part = Part.get_by_id(part_id)
            parts.append(part)

        for vendor_part_id in vendor_part_ids:
            part = VendorPart.get_by_id(vendor_part_id)
            vendor_parts.append(part)
        variables = {
            'vendor_parts': vendor_parts,
            'parts': parts,
            'current_part_ids': request.form['parts'],
            'current_vendor_part_ids': request.form['vendor_parts'],
            'form': form
        }
        return make_response(
            render_template('procedure/create_procedure.html', **variables),
            500)
Esempio n. 3
0
def add_extra_product_component():
    form = AddExtraProductComponentForm(request.form)
    validated = form.validate_on_submit()
    if validated:
        quantity = form.quantity.data
        part_group = form.part_group.data
        part_id = form.part_id.data
        product_id = form.product_id.data
        product = Product.get_by_id(product_id)
        ordering = len(product.extra_components) + 1
        if part_group == 'Part':  # part_group from typeahead group, not class name
            part = Part.get_by_id(part_id)
            for i in range(quantity):
                epc = ExtraProductComponent.create(parent=product, part=part, ordering=ordering)
        elif part_group == 'Vendor Part':  # part_group from typeahead group, not class name
            vendor_part = VendorPart.get_by_id(part_id)
            for i in range(quantity):
                epc = ExtraProductComponent.create(parent=product, vendor_part=vendor_part, ordering=ordering)
        components_array = arrange_product_components(product)
        extra_components_array = arrange_extra_product_components(product)
        variables = {
            'success': True,
            'product': product,
            'components_array': components_array,
            'extra_components_array': extra_components_array
        }
        new_value = '{0} -  Quantity: {1}'.format(epc.get_part().get_descriptive_url(), quantity)
        product.add_change_log_entry(action='Add', field='Extra Component', new_value=new_value)
        return render_template('product/as-built/component_list.html', **variables)
    else:
        product_id = form.product_id.data
        product = Product.get_by_id(product_id)
        part = None
        if form.part_id.data:
            part_group = form.part_group.data
            part_id = form.part_id.data
            if part_group == 'Part':  # part_group from typeahead, not class name
                part = Part.get_by_id(part_id)
            elif part_group == 'Vendor Part':  # part_group from typeahead, not class name
                part = VendorPart.get_by_id(part_id)
        variables = {
            'form': form,
            'product': product,
            'part': part
        }
        response = make_response(render_template('product/add_product_component_modal.html', **variables), 500)
        return response
Esempio n. 4
0
def update_part_revision(procedure_id, part_id):
    # TODO: Change this away from hardcoded URL, but using ajax select field now which just calls this as api_url
    proc = Procedure.get_by_id(procedure_id)
    procedure = Procedure.get_by_id(procedure_id)
    new_part_id = request.form['value']
    part = Part.get_by_id(part_id)
    new_part = Part.get_by_id(new_part_id)

    # Remove association to part from old revision
    procedure.parts.remove(part)

    # Add new association to part from new revision
    procedure.parts.append(new_part)

    procedure.save()
    return render_template('procedure/procedure_part.html',
                           part=new_part,
                           proc=proc)
Esempio n. 5
0
def remove_part():
    procedure_id = request.form.get('procedure_id')
    part_type = request.form.get('part_type')
    part_id = request.form.get('part_id')
    proc = Procedure.get_by_id(procedure_id)
    part = None
    if part_type == "designs":
        part = Part.get_by_id(part_id)
        proc.parts.remove(part)
    elif part_type == "vendor_parts":
        part = VendorPart.get_by_id(part_id)
        proc.vendor_parts.remove(part)
    proc.add_change_log_entry(action='Remove',
                              field='Part',
                              original_value=part.get_descriptive_url())
    proc.save()
    jsonData = {'success': True, 'partId': part_id}
    return jsonify(jsonData), 200, {'ContentType': 'application/json'}
Esempio n. 6
0
def get_record_by_id_and_class(record_id, record_class):
    # TODO: Try to find a better way that doesn't involve so much dynamic loading
    record = None
    record_class = record_class.lower()  # Just in case
    if record_class == 'anomaly':
        from pid.anomaly.models import Anomaly
        record = Anomaly.get_by_id(record_id)
    elif record_class == 'asrun':
        from pid.asrun.models import AsRun
        record = AsRun.get_by_id(record_id)
    elif record_class == 'build':
        from pid.product.models import Build
        record = Build.get_by_id(record_id)
    elif record_class == 'design':
        from pid.design.models import Design
        record = Design.get_by_id(record_id)
    elif record_class == 'eco':
        from pid.eco.models import ECO
        record = ECO.get_by_id(record_id)
    elif record_class == 'part':
        from pid.part.models import Part
        record = Part.get_by_id(record_id)
    elif record_class == 'procedure':
        from pid.procedure.models import Procedure
        record = Procedure.get_by_id(record_id)
    elif record_class == 'product':
        from pid.product.models import Product
        record = Product.get_by_id(record_id)
    elif record_class == 'specification':
        from pid.specification.models import Specification
        record = Specification.get_by_id(record_id)
    elif record_class == 'task':
        from pid.task.models import Task
        record = Task.get_by_id(record_id)
    elif record_class == 'vendorbuild':
        from pid.vendorproduct.models import VendorBuild
        record = VendorBuild.get_by_id(record_id)
    elif record_class == 'vendorpart':
        from pid.vendorpart.models import VendorPart
        record = VendorPart.get_by_id(record_id)
    elif record_class == 'vendorproduct':
        from pid.vendorproduct.models import VendorProduct
        record = VendorProduct.get_by_id(record_id)
    return record
Esempio n. 7
0
def add_part():
    procedure_id = request.form.get('procedure_id')
    record_id = request.form.get('record_id')
    record_class = request.form.get('record_class')
    proc = Procedure.get_by_id(procedure_id)
    part = None
    if record_class == "part":
        part = Part.get_by_id(record_id)
        proc.parts.append(part)
    elif record_class == "vendorpart":
        part = VendorPart.get_by_id(record_id)
        proc.vendor_parts.append(part)
    proc.add_change_log_entry(action='Add',
                              field='Part',
                              new_value=part.get_descriptive_url())
    proc.save()
    return render_template('procedure/procedure_part.html',
                           part=part,
                           proc=proc)
Esempio n. 8
0
def get_procedure_modal():
    form = CreateProcedureForm(request.form)
    vendor_parts = []
    parts = []
    table = request.form.get('table', None)
    part_id = request.form.get('part_id', None)
    if table:
        if table == 'vendor_parts':
            vendor_parts.append(VendorPart.get_by_id(part_id))
        elif table == 'designs':
            parts.append(Part.get_by_id(part_id))

    variables = {
        'vendor_parts': vendor_parts,
        'parts': parts,
        'current_part_ids': ','.join([str(x.id) for x in parts]),
        'current_vendor_part_ids': ','.join([str(x.id) for x in vendor_parts]),
        'form': form
    }
    return render_template('procedure/create_procedure.html', **variables)
Esempio n. 9
0
def revise_design():
    form = ReviseDesignForm(request.form)
    validated = form.validate_on_submit()
    if not validated:
        design_id = form.design_id.data
        design = Design.get_by_id(design_id)
        variables = {'design': design, 'form': form}
        return make_response(
            render_template('design/revise_design_modal.html', **variables),
            500)
    old_design_id = form.design_id.data
    new_revision = form.revision.data
    reason = form.revision_reason.data
    new_owner = form.owner.data
    include_parts = request.form['include_parts']
    old_design = Design.get_by_id(old_design_id)
    # Get the old bits while we can
    parts = old_design.parts
    links = old_design.links
    documents = old_design.documents
    images = old_design.images
    references_to = old_design.references_to
    # TODO: Duplicate anomalies, ecos, specifications, produres, family, changelog, revisionlog
    replace_values = {
        'revision': new_revision,
        'owner': new_owner,
        'created_by': current_user,
        'state': old_design.workflow.initial_state,
        'export_control': old_design.
        export_control,  # Because make_transient uses default values
        'self_approved': Design.self_approved.default.arg
    }
    design = old_design.clone(
        replace_values
    )  # After this point, old_design is the same as design, a cloned instance
    # Clone all parts
    if include_parts == 'all':
        for old_part in parts:
            # TODO: Parent? Changelog?
            components = old_part.components
            replace_values = {'design': design}
            part = old_part.clone(replace_values)
            for old_component in components:
                replace_values = {
                    'parent': part,
                    'part': old_component.part,
                    'vendor_part': old_component.vendor_part,
                    'quantity': old_component.
                    quantity  # Because make_transient uses default values
                }
                old_component.clone(replace_values)
    # Clone selected parts
    else:
        include_selected_parts = request.form.getlist('include_selected_parts')
        for part_id in include_selected_parts:
            # TODO: Parent? Changelog?
            old_part = Part.get_by_id(part_id)
            components = old_part.components
            replace_values = {'design': design}
            part = old_part.clone(replace_values)
            for old_component in components:
                replace_values = {
                    'parent': part,
                    'part': old_component.part,
                    'vendor_part': old_component.vendor_part,
                    'quantity': old_component.
                    quantity  # Because make_transient uses default values
                }
                old_component.clone(replace_values)
    # Clone links
    for old_link in links:
        link = old_link.clone()
        design.links.append(link)
    # Clone documents
    for old_document in documents:
        document = old_document.clone_document(design)
        design.documents.append(document)
    # Clone images
    for old_image in images:
        image = old_image.clone_image(design)
        design.images.append(image)
    # Clone what this references
    for reference in references_to:
        Reference.create(by_id=design.id,
                         by_class=design.get_class_name(),
                         to_id=reference.to_id,
                         to_class=reference.to_class)
    # Create new change log and new workflow log
    design.change_log = ChangeLog.create()
    design.workflow_log = WorkflowLog.create()
    # Add supervisor approval if user is a padawan
    if current_user.padawan:
        approver = Approver.create(approver_id=current_user.supervisor_id,
                                   capacity='Supervisor')
        design.approvers.append(approver)
    design.save()

    # Update any references in part components from old revision to new revision
    PartComponent.update_part_component_references(design)

    # Update revision log
    design.revision_log.add_entry(design.revision, reason, current_user)

    jsonData = {'success': True, 'url': design.get_url()}
    return jsonify(jsonData), 200, {'ContentType': 'application/json'}
Esempio n. 10
0
    def validate(self):
        """Validate the form."""
        initial_validation = super(CreateBuildForm, self).validate()
        errors = False
        data = {}
        if not initial_validation:
            errors = True

        part = Part.get_by_id(self.part_id.data)
        existing_serial_numbers = Product.get_serial_numbers_for_design_number_and_part_identifier(
            part.design.design_number, part.part_identifier)

        if self.product_type.data == 's/n':
            # TODO: Try to move some of this to an external function, very messy now
            return_serial_numbers = []
            # TODO: Improve these replaces
            serial_numbers = self.serial_numbers.data.strip().replace(
                ' , ', ',').replace(', ', ',').replace(' ,', ',').replace(
                    ' ', ',')  # In case user uses space instead of comma
            if len(serial_numbers) == 0:
                self.serial_numbers.errors.append('No S/N(s) entered')
                errors = True
            else:
                # First check for comma separated serial_numbers
                if ',' in serial_numbers:
                    serial_numbers_array = serial_numbers.split(',')
                    # In these, check for ranges and validate and append
                    for sn in serial_numbers_array:
                        if '-' in sn:
                            serial_numbers_range_low = sn.split('-')[0]
                            serial_numbers_range_high = sn.split('-')[1]
                            validated_low = self.validate_serial_number(
                                serial_numbers_range_low)
                            validated_high = self.validate_serial_number(
                                serial_numbers_range_high)
                            if validated_low and validated_high:
                                for i in range(int(validated_low),
                                               int(validated_high) + 1):
                                    validated_sn = self.validate_serial_number(
                                        i)
                                    if validated_sn in existing_serial_numbers:
                                        self.serial_numbers.errors.append(
                                            'S/N {0} already exists'.format(
                                                validated_sn))
                                        errors = True
                                    else:
                                        return_serial_numbers.append(
                                            validated_sn)
                            else:
                                self.serial_numbers.errors.append(
                                    'Invalid S/N(s) entered')
                                errors = True
                        # If not range, append the validated values
                        else:
                            validated_sn = self.validate_serial_number(sn)
                            if validated_sn:
                                if validated_sn in existing_serial_numbers:
                                    self.serial_numbers.errors.append(
                                        'S/N {0} already exists'.format(
                                            validated_sn))
                                    errors = True
                                else:
                                    return_serial_numbers.append(validated_sn)
                            else:
                                self.serial_numbers.errors.append(
                                    'Invalid S/N(s) entered')
                                errors = True
                # Only range present
                elif '-' in serial_numbers:
                    serial_numbers_range_low = serial_numbers.split('-')[0]
                    serial_numbers_range_high = serial_numbers.split('-')[1]
                    validated_low = self.validate_serial_number(
                        serial_numbers_range_low)
                    validated_high = self.validate_serial_number(
                        serial_numbers_range_high)
                    if validated_low and validated_high:
                        for i in range(int(validated_low),
                                       int(validated_high) + 1):
                            validated_sn = self.validate_serial_number(i)
                            if validated_sn in existing_serial_numbers:
                                self.serial_numbers.errors.append(
                                    'S/N {0} already exists'.format(
                                        validated_sn))
                                errors = True
                            else:
                                return_serial_numbers.append(validated_sn)
                    else:
                        self.serial_numbers.errors.append(
                            'Invalid S/N(s) entered')
                        errors = True
                    pass
                # Only one S/N present most likely, just append it after validating
                else:
                    validated_sn = self.validate_serial_number(serial_numbers)
                    if validated_sn:
                        if validated_sn in existing_serial_numbers:
                            self.serial_numbers.errors.append(
                                'S/N {0} already exists'.format(validated_sn))
                            errors = True
                        else:
                            return_serial_numbers.append(validated_sn)
                    else:
                        self.serial_numbers.errors.append(
                            'Invalid S/N(s) entered')
                        errors = True
            data['serial_numbers'] = return_serial_numbers
        elif self.product_type.data == 'lot':
            return_lot_record = None
            lot_record = self.lot_record.data.strip()
            if len(lot_record) == 0:
                self.lot_record.errors.append('No LOT record entered')
                errors = True
            else:
                if lot_record[0] != 'L':
                    # No biggie, just need to append L to beginning of number
                    validated_lot_record = self.validate_serial_number(
                        lot_record)
                    if validated_lot_record:
                        return_lot_record = 'L{0}'.format(validated_lot_record)
                    else:
                        self.lot_record.errors.append(
                            'Invalid LOT record entered')
                        errors = True
                else:
                    # Remove 'L' from beginning before validating, then add again.
                    validated_lot_record = self.validate_serial_number(
                        lot_record[1:])
                    if validated_lot_record:
                        return_lot_record = 'L{0}'.format(validated_lot_record)
                    else:
                        self.lot_record.errors.append(
                            'Invalid LOT record entered')
                        errors = True
            if lot_record in existing_serial_numbers:
                self.lot_record.errors.append(
                    'LOT record {0} already exists'.format(lot_record))
                errors = True
            else:
                data['lot_record'] = return_lot_record
        elif self.product_type.data == 'stock':
            # TODO: Check if STCK already exists
            if 'STCK' in existing_serial_numbers:
                self.product_type.errors.append('STCK already exists')
                errors = True
            else:
                data['is_stock'] = True

        if errors:
            return False, None

        return True, data
Esempio n. 11
0
def create_build():
    """Create new Build. Also creates one or more Products."""
    form = CreateBuildForm(request.form)
    if request.method == 'GET':
        part = Part.get_by_id(request.args.get('part_id'))
        existing_build_id = request.args.get('existing_build_id')
        if existing_build_id:
            existing_build = Build.get_by_id(existing_build_id)
            build_identifier = existing_build.build_identifier
        else:
            build_identifier = Build.get_next_build_identifier_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier)
        lot_identifier = Product.get_next_lot_number_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier)
        existing_serial_numbers = ','.join(Product.get_serial_numbers_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier))
        # Pre-populate with values from design
        form.project.data = part.design.project
        variables = {
            'form': form,
            'part': part,
            'build_identifier': build_identifier,
            'lot_identifier': lot_identifier,
            'existing_serial_numbers': existing_serial_numbers,
            'existing_build_id': existing_build_id
        }
        return render_template('product/create_build_modal.html', **variables)
    validated, data = form.validate_on_submit()
    if validated:
        part = Part.get_by_id(form.part_id.data)
        vendor = form.vendor.data
        owner = form.owner.data
        build_identifier = form.build_identifier.data
        # Create build
        if form.existing_build_id.data:
            build = Build.get_by_id(form.existing_build_id.data)
        else:
            build = Build.create(part=part, vendor=vendor, owner=owner, build_identifier=build_identifier)
        # For each s/n in s/n, create product
        revision = part.design.revision
        summary = part.design.summary
        hardware_type = form.hardware_type.data
        project = form.project.data
        # Create serial numbers
        serial_numbers = data.get('serial_numbers', [])
        for sn in serial_numbers:
            product = Product.create(serial_number=sn, part=part, build=build, revision=revision, summary=summary,
                                     hardware_type=hardware_type, project=project, owner=owner)
            # Create Product Components
            for part_component in part.components:
                for i in range(part_component.quantity):
                    if part_component.part:
                        ProductComponent.create(parent=product, part=part_component.part, ordering=part_component.ordering)
                    elif part_component.vendor_part:
                        ProductComponent.create(parent=product, vendor_part=part_component.vendor_part, ordering=part_component.ordering)
        # Or create LOT product
        lot_record = data.get('lot_record', None)
        if lot_record:
            product = Product.create(serial_number=lot_record, part=part, build=build, revision=revision,
                                     summary=summary, hardware_type=hardware_type, product_type='LOT',
                                     project=project, owner=owner)
            # Create Product Components
            for part_component in part.components:
                for i in range(part_component.quantity):
                    if part_component.part:
                        ProductComponent.create(parent=product, part=part_component.part, ordering=part_component.ordering)
                    elif part_component.vendor_part:
                        ProductComponent.create(parent=product, vendor_part=part_component.vendor_part, ordering=part_component.ordering)
        # Or create STOCK product
        is_stock = data.get('is_stock', False)
        if is_stock:
            product = Product.create(serial_number='STCK', part=part, build=build, revision=revision,
                                     summary=summary, hardware_type=hardware_type, product_type='STOCK',
                                     project=project, owner=owner)

        jsonData = {
            'success': True,
            'product_number': product.product_number.replace(' ', '-')  # Slugify product_number
        }
        return jsonify(jsonData), 200, {'ContentType': 'application/json'}
    else:
        part = Part.get_by_id(request.form['part_id'])
        build_identifier = Build.get_next_build_identifier_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier)
        lot_identifier = Product.get_next_lot_number_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier)
        existing_serial_numbers = ','.join(Product.get_serial_numbers_for_design_number_and_part_identifier(part.design.design_number, part.part_identifier))
        variables = {
            'form': form,
            'part': part,
            'build_identifier': build_identifier,
            'lot_identifier': lot_identifier,
            'existing_serial_numbers': existing_serial_numbers
        }
        response = make_response(render_template('product/create_build_modal.html', **variables), 500)
        return response
Esempio n. 12
0
 def get_nlas_for_vendor_part(self):
     return Part.get_nlas_for_vendor_part(self)