def test_invalid_product_import_using_invalid_file(self):
        valid_test_file = os.path.join(os.getcwd(),
                                       "tests",
                                       "data",
                                       "create_cisco_test_data.json")

        product_file = ImportProductsExcelFile(valid_test_file)

        with self.assertRaises(InvalidExcelFileFormat):
            product_file.verify_file()
    def test_invalid_product_import_using_excel_file_with_invalid_table_name(self):
        valid_test_file = os.path.join(os.getcwd(),
                                       "tests",
                                       "data",
                                       "excel_import_products_test-invalid_table_name.xlsx")

        product_file = ImportProductsExcelFile(valid_test_file)

        with self.assertRaises(InvalidImportFormatException):
            product_file.verify_file()
Example #3
0
    def clean(self):
        # validation of the import products excel file
        uploaded_file = self.cleaned_data.get("excel_file")

        if uploaded_file is None:
            raise forms.ValidationError("invalid upload, file has no content.")

        if len(uploaded_file.name.split('.')) == 1:
            raise forms.ValidationError("file type is not supported.")

        if uploaded_file.name.split('.')[-1] not in self.FILE_EXT_WHITELIST:
            raise forms.ValidationError("only .xlsx files is allowed")

        # verify that content can be read
        try:
            tmp = tempfile.NamedTemporaryFile(suffix="." + uploaded_file.name.split(".")[-1])

            tmp.write(uploaded_file.read())

            import_product = ImportProductsExcelFile(tmp.name)
            import_product.verify_file()

            # with this implementation, only 20000 items can be imported using a single excel file
            if import_product.amount_of_products > 20000:
                raise forms.ValidationError("Excel files with more than 20000 "
                                            "entries are currently not supported "
                                            "(found %s entries), please upload "
                                            "multiple smaller files" % import_product.amount_of_products)

            tmp.close()

        except InvalidImportFormatException as ex:
            msg = "Invalid structure in Excel file (%s)" % ex
            logger.info(msg)
            raise forms.ValidationError(msg)

        except InvalidExcelFileFormat:
            logger.debug("Invalid excel file format")
            raise forms.ValidationError("Invalid excel file format")

        except forms.ValidationError:
            raise

        except Exception as ex:
            logger.warn("Unexpected error while uploading file", ex)
            raise forms.ValidationError("Unexpected error occurred during upload (%s)" % ex)
Example #4
0
def import_products(request):
    """view for the import of products using Excel

    :param request:
    :return:
    """
    context = {}
    if request.method == "POST":
        form = ImportProductsFileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            # file is valid, execute the import
            uploaded_file = request.FILES['excel_file']

            tmp = tempfile.NamedTemporaryFile(suffix="." + uploaded_file.name.split(".")[-1])

            uploaded_file.open()
            tmp.write(uploaded_file.read())

            try:
                import_products_excel = ImportProductsExcelFile(tmp.name)
                import_products_excel.verify_file()
                import_products_excel.import_products_to_database()

                context['import_valid_imported_products'] = import_products_excel.valid_imported_products
                context['import_invalid_products'] = import_products_excel.invalid_products
                context['import_messages'] = import_products_excel.import_result_messages
                context['import_result'] = "success"

            except Exception as ex:
                msg = "unexpected error occurred during import (%s)" % ex
                logger.error(msg, ex)
                context['import_messages'] = msg
                context['import_result'] = "error"

            finally:
                tmp.close()

    else:
        form = ImportProductsFileUploadForm()

    context['form'] = form

    return render_to_response("productdb/settings/import_products.html",
                              context=context,
                              context_instance=RequestContext(request))
Example #5
0
    def clean(self):
        # validation of the import products excel file
        uploaded_file = self.cleaned_data.get("excel_file")

        if uploaded_file is None:
            raise forms.ValidationError("invalid upload, file has no content.")

        if len(uploaded_file.name.split('.')) == 1:
            raise forms.ValidationError("file type is not supported.")

        if uploaded_file.name.split('.')[-1] not in self.FILE_EXT_WHITELIST:
            raise forms.ValidationError("only .xlsx files is allowed")

        # verify that content can be read
        try:
            tmp = tempfile.NamedTemporaryFile(
                suffix="." + uploaded_file.name.split(".")[-1])

            tmp.write(uploaded_file.read())

            import_product = ImportProductsExcelFile(tmp.name)
            import_product.verify_file()

            tmp.close()

        except InvalidImportFormatException as ex:
            msg = "Invalid structure in Excel file (%s)" % ex
            logger.info(msg)
            raise forms.ValidationError(msg)

        except InvalidExcelFileFormat:
            logger.debug("Invalid excel file format")
            raise forms.ValidationError("Invalid excel file format")

        except forms.ValidationError:
            raise

        except Exception as ex:
            logger.warn("Unexpected error while uploading file", ex)
            raise forms.ValidationError(
                "Unexpected error occurred during upload (%s)" % ex)
Example #6
0
    def clean(self):
        # validation of the import products excel file
        uploaded_file = self.cleaned_data.get("excel_file")

        if uploaded_file is None:
            raise forms.ValidationError("invalid upload, file has no content.")

        if len(uploaded_file.name.split('.')) == 1:
            raise forms.ValidationError("file type is not supported.")

        if uploaded_file.name.split('.')[-1] not in self.FILE_EXT_WHITELIST:
            raise forms.ValidationError("only .xlsx files is allowed")

        # verify that content can be read
        try:
            tmp = tempfile.NamedTemporaryFile(suffix="." + uploaded_file.name.split(".")[-1])

            tmp.write(uploaded_file.read())

            import_product = ImportProductsExcelFile(tmp.name)
            import_product.verify_file()

            tmp.close()

        except InvalidImportFormatException as ex:
            msg = "Invalid structure in Excel file (%s)" % ex
            logger.info(msg)
            raise forms.ValidationError(msg)

        except InvalidExcelFileFormat:
            logger.debug("Invalid excel file format")
            raise forms.ValidationError("Invalid excel file format")

        except forms.ValidationError:
            raise

        except Exception as ex:
            logger.warn("Unexpected error while uploading file", ex)
            raise forms.ValidationError("Unexpected error occurred during upload (%s)" % ex)
    def prepare_import_products_excel_file(filename, verify_file=True, start_import=True):
        """
        helping method, that creates a new ImportProductsExcelFile instance based on a "filename" in the test data
        directory
        """
        valid_test_file = os.path.join(os.getcwd(),
                                       "tests",
                                       "data",
                                       filename)

        product_file = ImportProductsExcelFile(valid_test_file)
        if verify_file:
            product_file.verify_file()
        if start_import:
            product_file.import_products_to_database()

        return product_file
    def test_valid_product_import_using_excel_with_currency_column(self):
        """
        test a valid product import using the standard Excel template with separate list price and currency columns
        """
        test_product_ids = [
            'WS-C2960S-48FPD-L',
            'WS-C2960S-48LPD-L',
            'WS-C2960S-24PD-L',
            'WS-C2960S-48TD-L',
            'WS-C2960S-24TD-L',
            'WS-C2960S-48FPS-L',
            'WS-C2960S-48LPS-L',
            'WS-C2960S-24PS-L',
            'CAB-STK-E-0.5M',
            'CAB-STK-E-1M=',
            'CAB-STK-E-1M',
            'CAB-STK-E-3M=',
            'CAB-CONSOLE-RJ45=',
            'CAB-CONSOLE-USB=',
            'EX4200-24F',
            'EX4200-24F-DC',
            'WS-C2960S-48TS-L',
            'WS-C2960S-24TS-L',
            'WS-C2960S-48TS-S',
            'WS-C2960S-24TS-S',
            'C2960S-STACK',
            'C2960S-STACK=',
            'CAB-STK-E-0.5M=',
            'EX4200-24F-S',
            'EX4200-24PX',
        ]
        products = [
            {
                'product id': 'WS-C2960S-48FPD-L',
                'description': 'Catalyst 2960S 48 GigE PoE 740W, 2 x 10G SFP+ LAN Base',
                'list price': 8795,
                'currency': 'USD',
                'vendor': 'Cisco Systems',
            },
            {
                'product id': 'CAB-STK-E-1M',
                'description': 'Cisco FlexStack 1m stacking cable',
                'list price': 100,
                'currency': 'USD',
                'vendor': 'unassigned',
            },
            {
                'product id': 'CAB-STK-E-1M=',
                'description': 'Cisco Bladeswitch 1M stack cable',
                'list price': None,
                'currency': 'USD',
                'vendor': 'Cisco Systems',
            },

        ]
        valid_test_file = os.path.join(os.getcwd(),
                                       "tests",
                                       "data",
                                       "excel_import_products_test.xlsx")

        product_file = ImportProductsExcelFile(valid_test_file)
        product_file.verify_file()

        self.assertTrue(product_file.valid_file, "given excel file has no valid format")

        product_file.import_products_to_database()

        self.assertEqual(product_file.valid_imported_products, 25)
        self.assertEqual(product_file.invalid_products, 0)
        self.assertEqual(product_file.amount_of_products, 25)
        self.assertIsNotNone(product_file.import_result_messages)

        # verify that the expected products are created in the database
        for pid in test_product_ids:
            Product.objects.get(product_id=pid)

        # look at the imported values from the
        for product in products:
            p = Product.objects.get(product_id=product['product id'])
            self.assertEqual(p.description, product['description'])
            self.assertEqual(p.list_price, product['list price'], p.product_id)
            self.assertEqual(p.currency, product['currency'])
            self.assertEqual(p.vendor.name, product['vendor'])
Example #9
0
def import_price_list(self, job_file_id, create_notification_on_server=True, user_for_revision=None):
    """
    import products from the given price list
    """
    def update_task_state(status_message):
        """Update the status message of the task, which is displayed in the watch view"""
        self.update_state(state=TaskState.PROCESSING, meta={
            "status_message": status_message
        })

    update_task_state("Try to import uploaded file...")

    try:
        import_excel_file = JobFile.objects.get(id=job_file_id)

    except:
        msg = "Cannot find file that was uploaded."
        logger.error(msg, exc_info=True)
        result = {
            "error_message": msg
        }
        return result

    # verify that file exists
    try:
        import_products_excel = ImportProductsExcelFile(
            path_to_excel_file=import_excel_file.file,
            user_for_revision=User.objects.get(username=user_for_revision)
        )
        import_products_excel.verify_file()
        update_task_state("File valid, start updating the database...")

        import_products_excel.import_products_to_database(status_callback=update_task_state)
        update_task_state("Database import finished, processing results...")

        summary_msg = "User <strong>%s</strong> imported a Product list, %s Products " \
                      "changed." % (user_for_revision, import_products_excel.valid_imported_products)
        detail_msg = "<div style=\"text-align:left;\">%s " \
                     "Products successful updated. " % import_products_excel.valid_imported_products

        if import_products_excel.invalid_products != 0:
            detail_msg += "%s entries are invalid. Please check the following messages for " \
                          "more details." % import_products_excel.invalid_products

        if len(import_products_excel.import_result_messages) != 0:
            detail_msg += "<ul>"
            for e in import_products_excel.import_result_messages:
                detail_msg += "<li>%s</li>" % e
            detail_msg += "</ul></div>"

        # if the task was executed eager, set state to SUCCESS (required for testing)
        if self.request.is_eager:
            self.update_state(state=TaskState.SUCCESS, meta={
                "status_message": detail_msg
            })

        if create_notification_on_server:
            NotificationMessage.objects.create(
                title="Import product list",
                type=NotificationMessage.MESSAGE_INFO,
                summary_message=summary_msg,
                detailed_message=detail_msg
            )

        # drop the file
        import_excel_file.delete()

        result = {
            "status_message": detail_msg
        }

    except InvalidImportFormatException as ex:
        msg = "import failed, invalid file format (%s)" % ex
        logger.error(msg, ex)
        result = {
            "error_message": msg
        }

    except Exception as ex:
        msg = "Unexpected exception occurred while importing product list (%s)" % ex
        logger.error(msg, ex)
        result = {
            "error_message": msg
        }

    return result
Example #10
0
def import_price_list(self,
                      job_file_id,
                      create_notification_on_server=True,
                      user_for_revision=None):
    """
    import products from the given price list
    """
    def update_task_state(status_message):
        """Update the status message of the task, which is displayed in the watch view"""
        self.update_state(state=TaskState.PROCESSING,
                          meta={"status_message": status_message})

    update_task_state("Try to import uploaded file...")

    try:
        import_excel_file = JobFile.objects.get(id=job_file_id)

    except:
        msg = "Cannot find file that was uploaded."
        logger.error(msg, exc_info=True)
        result = {"error_message": msg}
        return result

    # verify that file exists
    try:
        import_products_excel = ImportProductsExcelFile(
            path_to_excel_file=import_excel_file.file,
            user_for_revision=User.objects.get(username=user_for_revision))
        import_products_excel.verify_file()
        update_task_state("File valid, start updating the database...")

        import_products_excel.import_products_to_database(
            status_callback=update_task_state)
        update_task_state("Database import finished, processing results...")

        summary_msg = "User <strong>%s</strong> imported a Product list, %s Products " \
                      "changed." % (user_for_revision, import_products_excel.valid_imported_products)
        detail_msg = "<div style=\"text-align:left;\">%s " \
                     "Products successful updated. " % import_products_excel.valid_imported_products

        if import_products_excel.invalid_products != 0:
            detail_msg += "%s entries are invalid. Please check the following messages for " \
                          "more details." % import_products_excel.invalid_products

        if len(import_products_excel.import_result_messages) != 0:
            detail_msg += "<ul>"
            for e in import_products_excel.import_result_messages:
                detail_msg += "<li>%s</li>" % e
            detail_msg += "</ul></div>"

        # if the task was executed eager, set state to SUCCESS (required for testing)
        if self.request.is_eager:
            self.update_state(state=TaskState.SUCCESS,
                              meta={"status_message": detail_msg})

        if create_notification_on_server:
            NotificationMessage.objects.create(
                title="Import product list",
                type=NotificationMessage.MESSAGE_INFO,
                summary_message=summary_msg,
                detailed_message=detail_msg)

        # drop the file
        import_excel_file.delete()

        result = {"status_message": detail_msg}

    except InvalidImportFormatException as ex:
        msg = "import failed, invalid file format (%s)" % ex
        logger.error(msg, ex)
        result = {"error_message": msg}

    except Exception as ex:
        msg = "Unexpected exception occurred while importing product list (%s)" % ex
        logger.error(msg, ex)
        result = {"error_message": msg}

    return result