Ejemplo n.º 1
0
def add_product_dict(args, cc_browser, products, worksheet):
    """Create the Product Dictionary worksheet."""

    # Prepare worksheet.
    worksheet.title = "Product Dictionary"

    # Add products.
    # Remove excluded SKUs.
    if args.exclude_skus:
        products = [
            x for x in products if str(x["SKU"]) not in args.exclude_skus
        ]

    # Add product rows, grouped by category.
    row = 1
    for _, product_group in itertools.groupby(
            products, key=cc_browser.product_key_by_category):
        # Add product rows.
        for product in product_group:
            if product["Discontinued Item"] == "Y":
                continue
            description = "{}: {}".format(
                product["Product Name"],
                cctools.html_to_plain_text(product["Teaser"]))
            worksheet.cell(row=row, column=1).value = product["SKU"]
            worksheet.cell(row=row, column=2).value = description
            worksheet.cell(row=row, column=3).value = product["HTSUS No"]
            row += 1

    # Set column widths.
    worksheet.column_dimensions["A"].width = 6
    worksheet.column_dimensions["B"].width = 95
    worksheet.column_dimensions["C"].width = 13
Ejemplo n.º 2
0
def add_product(args, worksheet, row, item_no, product, variants):
    """Add row for each variant."""
    size = product["Size"]
    product_name = product["Product Name"]
    sku = product["SKU"]
    teaser = cctools.html_to_plain_text(product["Teaser"])
    price = float(product["Price"])

    product_variants = get_product_variants(variants, sku)
    if len(product_variants) == 0:
        description = "{}: {}".format(product_name, teaser)
        add_variant(
            worksheet,
            row,
            item_no,
            size,
            sku,
            description,
            calc_wholesale_price(args, price),
            price
        )
        row += 1
        item_no += 1
    else:
        any_variant_exists = False
        for variant in product_variants:
            variant_sku = variant["Variant SKU"]
            if variant_sku == "ANY" or variant_sku == "VAR":
                any_variant_exists = True
            variant_sku = "{}-{}".format(sku, variant_sku)
            variant_add_price = float(variant["Variant Add Price"])
            variant_name = variant["Variant Name"]
            description = "{} ({}): {}".format(
                product_name,
                variant_name,
                teaser
            )
            add_variant(
                worksheet,
                row,
                item_no,
                size,
                variant_sku,
                description,
                calc_wholesale_price(args, price + variant_add_price),
                price + variant_add_price
            )
            row += 1
            item_no += 1
        if CHECK_FOR_LACK_OF_ANY and not any_variant_exists:
            logging.getLogger().warning(
                "No 'Any' or 'Variety' variant exists for {} {}".format(
                    sku,
                    product_name
                )
            )

    return row, item_no
Ejemplo n.º 3
0
def write_quantities(quant_filename, products):
    """Write empty quantities file."""

    with open(quant_filename, "w") as quant_file:
        quant_file.write("Quantity,SKU,Description(ignored)\n")
        for product in products:
            sku = product["SKU"]
            description = "{}: {}".format(
                product["Product Name"],
                cctools.html_to_plain_text(product["Teaser"])
            )
            quant_file.write(",".join(["0", sku, '"%s"' % description]) + "\n")
Ejemplo n.º 4
0
def add_product(args, worksheet, row, item_no, product, variants):
    """Add row for each variant."""
    size = product["Size"]
    product_name = product["Product Name"]
    sku = product["SKU"]
    teaser = cctools.html_to_plain_text(product["Teaser"])
    msrp = float(product["Price"])
    price = msrp * args.price_multiplier
    price =\
        math.floor(price / args.price_precision + 0.5) * args.price_precision

    if args.include_variants:
        product_variants = get_product_variants(variants, sku)
    else:
        product_variants = []

    if product_variants:
        any_variant_exists = False
        for variant in product_variants:
            variant_sku = variant["Variant SKU"]
            if variant_sku == "ANY" or variant_sku == "VAR":
                any_variant_exists = True
            variant_sku = "{}-{}".format(sku, variant_sku)
            variant_add_price = float(variant["Variant Add Price"])
            variant_name = variant["Variant Name"]
            description = "{} ({}): {}".format(product_name, variant_name,
                                               teaser)
            add_variant(
                worksheet, row, item_no, size, variant_sku, description,
                calc_price.calc_wholesale_price(price + variant_add_price,
                                                args.wholesale_fraction),
                msrp + variant_add_price)
            row += 1
            item_no += 1
        if CHECK_FOR_LACK_OF_ANY and not any_variant_exists:
            logging.getLogger().warning(
                "No 'Any' or 'Variety' variant exists for {} {}".format(
                    sku, product_name))
    else:
        description = "{}: {}".format(product_name, teaser)
        add_variant(
            worksheet, row, item_no, size, sku, description,
            calc_price.calc_wholesale_price(price, args.wholesale_fraction),
            msrp)
        row += 1
        item_no += 1

    return row, item_no
Ejemplo n.º 5
0
def add_product(worksheet, row, lineno, product, variants):
    """Add row for each variant."""
    product_name = product["Product Name"]
    sku = product["SKU"]
    teaser = cctools.html_to_plain_text(product["Teaser"])
    size = product["Size"]
    cost = float(product["Cost"])
    if "HTSUS No" in product:
        htsus_no = product["HTSUS No"]
    else:
        htsus_no = None
    product_variants = get_product_variants(variants, sku)
    if len(product_variants) == 0:
        description = "{}: {}".format(product_name, teaser)
        add_variant(worksheet, row, lineno, sku, description, size, cost,
                    htsus_no)
        row += 1
        lineno += 1
    else:
        any_variant_exists = False
        for variant in product_variants:
            variant_sku = variant["Variant SKU"]
            if variant_sku == "ANY" or variant_sku == "VAR":
                any_variant_exists = True
            variant_sku = "{}-{}".format(sku, variant_sku)
            variant_add_cost = float(variant["Variant Add Cost"])
            variant_name = variant["Variant Name"]
            description = "{} ({}): {}".format(product_name, variant_name,
                                               teaser)
            variant_group = variant["Variant Group"]
            if RE_SIZE_VARIANT.match(variant_group):
                size = variant_name
            add_variant(worksheet, row, lineno, variant_sku, description, size,
                        cost + variant_add_cost, htsus_no)
            row += 1
            lineno += 1
        if CHECK_FOR_LACK_OF_ANY and not any_variant_exists:
            logging.getLogger().warning(
                "No 'Any' or 'Variety' variant exists for {} {}".format(
                    sku, product_name))

    return row, lineno
Ejemplo n.º 6
0
def add_product(worksheet, row, lineno, product, variants):
    """Add row for each variant."""
    product_name = product["Product Name"]
    sku = product["SKU"]
    teaser = cctools.html_to_plain_text(product["Teaser"])
    size = product["Size"]
    cost = float(product["Cost"])
    if "HTSUS No" in product:
        htsus_no = product["HTSUS No"]
    else:
        htsus_no = None
    product_variants = get_product_variants(variants, sku)
    if len(product_variants) == 0:
        description = "{}: {}".format(product_name, teaser)
        add_variant(worksheet, row, lineno, sku, description, size, cost, htsus_no)
        row += 1
        lineno += 1
    else:
        any_variant_exists = False
        for variant in product_variants:
            variant_sku = variant["Variant SKU"]
            if variant_sku == "ANY" or variant_sku == "VAR":
                any_variant_exists = True
            variant_sku = "{}-{}".format(sku, variant_sku)
            variant_add_cost = float(variant["Variant Add Cost"])
            variant_name = variant["Variant Name"]
            description = "{} ({}): {}".format(product_name, variant_name, teaser)
            variant_group = variant["Variant Group"]
            if RE_SIZE_VARIANT.match(variant_group):
                size = variant_name
            add_variant(worksheet, row, lineno, variant_sku, description, size, cost + variant_add_cost, htsus_no)
            row += 1
            lineno += 1
        if CHECK_FOR_LACK_OF_ANY and not any_variant_exists:
            logging.getLogger().warning("No 'Any' or 'Variety' variant exists for {} {}".format(sku, product_name))

    return row, lineno
Ejemplo n.º 7
0
def add_product_dict(args, cc_browser, products, worksheet):
    """Create the Product Dictionary worksheet."""

    # Prepare worksheet.
    worksheet.title = "Product Dictionary"

    # Add products.
    # Remove excluded SKUs.
    if args.exclude_skus:
        products = [
            x for x in products if str(x["SKU"]) not in args.exclude_skus
        ]

    # Add product rows, grouped by category.
    row = 1
    for _, product_group in itertools.groupby(
        products,
        key=cc_browser.product_key_by_category
    ):
        # Add product rows.
        for product in product_group:
            if product["Discontinued Item"] == "Y":
                continue
            description = "{}: {}".format(
                product["Product Name"],
                cctools.html_to_plain_text(product["Teaser"])
            )
            worksheet.cell(row=row, column=1).value = product["SKU"]
            worksheet.cell(row=row, column=2).value = description
            worksheet.cell(row=row, column=3).value = product["HTSUS No"]
            row += 1

    # Set column widths.
    worksheet.column_dimensions["A"].width = 6
    worksheet.column_dimensions["B"].width = 95
    worksheet.column_dimensions["C"].width = 13
Ejemplo n.º 8
0
def generate_pdf(products, quantities, pdf_filename):
    """Generate the PDF file."""
    # Construct a document.
    doc = reportlab.platypus.BaseDocTemplate(
        pdf_filename,
        pagesize=reportlab.lib.pagesizes.letter,
        title="Art Mart Inventory Sheet Check In/Out",
        # showBoundary=True
    )

    # Construct a frame.
    page_width = doc.pagesize[0]
    page_height = doc.pagesize[1]
    frames = [
        reportlab.platypus.Frame(
            id="table_frame",
            x1=0.25 * INCH,
            y1=1.60 * INCH,
            width=page_width - 0.45 * INCH,
            height=page_height - 3.60 * INCH,
            leftPadding=0,
            bottomPadding=0,
            rightPadding=0,
            topPadding=0
        )
    ]

    # Construct a template and add it to the document.
    doc.addPageTemplates(
        reportlab.platypus.PageTemplate(
            id="mytemplate",
            frames=frames,
            onPage=on_page
        )
    )

    # Construct a story and add it to the document.
    col_widths = [
        0.40 * INCH,  # Existing Qty
        1.15 * INCH,  # Barcode
        0.40 * INCH,  # Qty Added
        0.60 * INCH,  # Price
        5.00 * INCH,  # Description
        0.40 * INCH,  # Total Qty
    ]
    col_header_style = reportlab.lib.styles.ParagraphStyle(
        name="col_header",
        fontName="Helvetica-Bold",
        fontSize=10
    )
    col_center_style = reportlab.lib.styles.ParagraphStyle(
        name="col_center",
        fontName="Helvetica-Bold",
        fontSize=10,
        alignment=reportlab.lib.enums.TA_CENTER
    )
    col_align_right_style = reportlab.lib.styles.ParagraphStyle(
        name="col_align_right",
        fontName="Helvetica-Bold",
        fontSize=10,
        alignment=reportlab.lib.enums.TA_RIGHT
    )
    # TableStyle cell formatting commands.
    styles = [
        # Whole table.
        ('FONTSIZE', (0, 0), (-1, -1), 10),
        ('TOPPADDING', (0, 1), (-1, -1), 0.26 * INCH),
        ('BOTTOMPADDING', (0, 1), (-1, -1), 0.10 * INCH),
        # Existing Qty
        ('LEFTPADDING', (0, 0), (0, -1), 0),
        # Barcode
        ('ALIGN', (1, 0), (1, 0), 'CENTER'),
        ('ALIGN', (1, 0), (1, -1), 'RIGHT'),
        ('FONT', (1, 0), (1, -1), 'Courier-Bold'),
        # Qty Added
        ('LEFTPADDING', (2, 0), (2, 0), 0),
        ('ALIGN', (2, 0), (2, 0), 'LEFT'),
        ('ALIGN', (2, 1), (2, -1), 'RIGHT'),
        ('FONT', (2, 0), (2, -1), 'Courier-Bold'),
        # Price
        ('ALIGN', (3, 0), (3, -1), 'RIGHT'),
        ('FONT', (3, 0), (3, -1), 'Courier-Bold'),
        # Description
        ('ALIGN', (4, 0), (4, -1), 'LEFT'),
        ('FONT', (4, 0), (4, -1), 'Helvetica'),
        # Total Qty
        ('LEFTPADDING', (5, 0), (5, -1), 0),
        ('ALIGN', (5, 0), (5, 0), 'LEFT'),
        # Other
        ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'),
        # ('GRID', (0, 0), (-1, -1), 1.0, BLACK)
    ]
    header_row = (
        reportlab.platypus.Paragraph("Existing<br/>Qty", col_header_style),
        reportlab.platypus.Paragraph("Barcode<br/>&nbsp;", col_center_style),
        reportlab.platypus.Paragraph("Qty<br/>Added", col_header_style),
        reportlab.platypus.Paragraph(
            "Price<br/>&nbsp;",
            col_align_right_style
        ),
        reportlab.platypus.Paragraph(
            "Description<br/>&nbsp;",
            col_header_style
        ),
        reportlab.platypus.Paragraph("Total<br/>Qty", col_header_style)
    )
    table_data = [header_row]
    for product in products:
        sku = product["SKU"]
        if sku in quantities:
            quantity = quantities[sku]
            # Round price to nearest dollar.
            price = product["Price"]
            price = "${.0f}".format(math.trunc(float(price) + 0.5))
            description = "{}: {}".format(
                product["Product Name"],
                cctools.html_to_plain_text(product["Teaser"])
            )
            description = description[:68]
            table_data.append(
                ("_____", sku, quantity, price, description, "_____")
            )
    table = reportlab.platypus.Table(
        data=table_data,
        colWidths=col_widths,
        style=styles,
        repeatRows=1
    )
    table.hAlign = "LEFT"
    story = [table]
    doc.build(story, canvasmaker=NumberedCanvas)
Ejemplo n.º 9
0
def generate_pdf(
    args,
    config,
    cc_browser,
    products
):
    """Generate a PDF given a list of products by category."""
    # Construct a document.
    doc_title = config.get("price_list", "title")
    doc = reportlab.platypus.BaseDocTemplate(
        args.pdf_file,
        pagesize=reportlab.lib.pagesizes.letter,
        title=doc_title,
        # showBoundary=True  # debug
    )

    # Construct a frame for each column.
    frames = create_col_frames(doc, args.ncols)

    # Construct a template and add it to the document.
    doc.my_title = doc_title
    doc.discount_percent = args.discount_percent
    doc.addPageTemplates(
        reportlab.platypus.PageTemplate(
            id="mytemplate",
            frames=frames,
            onPage=on_page
        )
    )

    # Construct a story and add it to the document.
    category_style = reportlab.lib.styles.ParagraphStyle(
        name="category",
        spaceBefore=0.15 * INCH,
        spaceAfter=0.05 * INCH,
        fontName="Helvetica-Bold",
        fontSize=12
    )
    greybar_color = reportlab.lib.colors.Whiter(
        reportlab.lib.colors.lightgrey,
        0.5
    )
    table_indent = 0.1 * INCH
    table_width = frames[0].width - table_indent
    price_width = 0.4 * INCH
    col_widths = [table_width - price_width, price_width]
    story = []

    # Sort products by category, product_name.
    if args.categories:
        cc_browser.set_category_sort_order(args.categories)
    products = sorted(products, key=cc_browser.product_key_by_cat_and_name)

    # Setup styles.
    body_fontsize = float(config.get("price_list", "body_fontsize"))
    row_padding =  float(config.get("price_list", "row_padding"))
    base_styles = [
        ("FONTSIZE", (0, 0), (-1, -1), body_fontsize),
        ("ALIGN", (0, 0), (0, -1), "LEFT"),
        ("ALIGN", (1, 0), (1, -1), "RIGHT"),
        ("FONT", (1, 0), (1, -1), "Courier-Bold"),
        ("LEFTPADDING", (0, 0), (-1, -1), 3),
        ("RIGHTPADDING", (0, 0), (-1, -1), 3),
        ("TOPPADDING", (0, 0), (-1, -1), row_padding),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3 + row_padding),
        # ("GRID", (0, 0), (-1, -1), 1.0, reportlab.lib.colors.black)
    ]

    # Group products by category.
    first = True
    for _, product_group in itertools.groupby(
        products,
        key=cc_browser.product_key_by_category
    ):
        # Make a new styles instance just for this table.
        styles = list(base_styles)
        if args.add_teaser:
            rows_per_product = 2
        else:
            rows_per_product = 1

        # Assemble table data for the product_group.
        table_data = list()
        row = 0
        for product in product_group:
            category = product["Category"]
            product_name = product["Product Name"]
            price = calc_price.calc_event_price(
                product["Price"],
                args.discount_percent,
                args.avg_tax_percent
            )
            # Format price as whole number string like "$1,234".
            price = "${:,.0f}".format(price)
            if args.add_sku:
                row_data = (
                    "{} ({})".format(product_name, product["SKU"]),
                    price
                )
            else:
                row_data = (product_name, price)
            table_data.append(row_data)
            row += 1
            if args.add_teaser:
                # Strip HTML formatting.
                product_teaser = cctools.html_to_plain_text(product["Teaser"])
                row_data = (product_teaser,)
                table_data.append(row_data)
                # Indent the teaser.
                styles.append(("LEFTPADDING", (0, row), (0, row), 18))
                row += 1
        if len(table_data) == 0:
            continue

        # Prevent page splitting in the middle of a product.
        if rows_per_product > 1:
            for row in range(0, len(table_data), rows_per_product):
                styles.append(
                    ("NOSPLIT", (0, row), (0, row + rows_per_product - 1))
                )

        # Grey background color to highlight alternate products.
        if args.greybar_interval > 1:
            interval = args.greybar_interval * rows_per_product
            for start_row in range(0, len(table_data), interval):
                for sub_row in range(0, rows_per_product):
                    row = start_row + sub_row
                    styles.append(
                        ("BACKGROUND", (0, row), (1, row), greybar_color)
                    )

        # Create the table.
        table = reportlab.platypus.Table(
            data=table_data,
            colWidths=col_widths,
            style=styles
        )

        # Create a group of the category name and the products.
        category_group = [
            reportlab.platypus.Paragraph(category, category_style),
            reportlab.platypus.Indenter(left=table_indent),
            table,
            reportlab.platypus.Indenter(left=-table_indent)
        ]
        # There is a bug in platypus where if a KeepTogether is at
        # the top of a page and the KeepTogether is longer than a
        # page, then a blank page will be emitted.  We can't always
        # know when this will happen, but we know for certain it will
        # happen for the first category group.
        if first:
            for flowable in category_group:
                story.append(flowable)
            first = False
        else:
            story.append(reportlab.platypus.KeepTogether(category_group))

    doc.build(story)
Ejemplo n.º 10
0
    def run_checks_core(self):
        """Run all checks, returning a list of findings."""

        self.clear_finding_list()

        findings = []

        # Create a connection to CoreCommerce.
        cc_browser = cctools.CCBrowser(
            self.config.get("website", "host"),
            self.config.get("website", "site"),
            self.config.get("website", "username"),
            self.config.get("website", "password"),
            clean=self.args.clean,
            cache_ttl=0 if self.args.refresh_cache else self.args.cache_ttl
        )

        # Any subsequent calls should ignore the cache.  If the user
        # clicks the Refresh button, it would be because they changed
        # something in CoreCommerce.
        self.args.refresh_cache = True

        # Check category list.
        categories = cc_browser.get_categories()
        self.eval_locals["items"] = categories
        for category in categories:
            findings.extend(
                self.check_item(
                    "category",
                    category,
                    category["Category Name"]
                )
            )

        # Check products list.
        cc_browser.guess_product_ids()
        products = sorted(
            cc_browser.get_products(),
            key=cc_browser.product_key_by_cat_and_name
        )
        self.eval_locals["items"] = products
        findings.extend(check_skus(self.config, products))
        for product in products:
            for key in ["Teaser"]:
                product[key] = cctools.html_to_plain_text(product[key])
            findings.extend(
                self.check_item(
                    "product",
                    product,
                    product_display_name(product)
                )
            )

        # Check variants list.
        variants = sorted(
            cc_browser.get_variants(),
            key=cc_browser.variant_key_by_cat_product
        )
        add_is_first_answer_flag(variants)
        self.eval_locals["items"] = variants
        for variant in variants:
            findings.extend(
                self.check_item(
                    "variant",
                    variant,
                    variant_display_name(variant)
                )
            )

        self.checks_completed()

        return findings
Ejemplo n.º 11
0
    def run_checks_core(self):
        """Run all checks, returning a list of findings."""

        self.clear_finding_list()

        findings = []

        # Create a connection to CoreCommerce.
        cc_browser = cctools.CCBrowser(
            self.config.get("website", "base_url"),
            self.config.get("website", "username"),
            self.config.get("website", "password"),
            clean=self.args.clean,
            cache_ttl=0 if self.args.refresh_cache else self.args.cache_ttl
        )

        # Any subsequent calls should ignore the cache.  If the user
        # clicks the Refresh button, it would be because they changed
        # something in CoreCommerce.
        self.args.refresh_cache = True

        # Check category list.
        categories = cc_browser.get_categories()
        self.eval_locals["items"] = categories
        for category in categories:
            findings.extend(
                self.check_item(
                    "category",
                    category,
                    category["Category Name"]
                )
            )

        # Check products list.
        cc_browser.guess_product_ids()
        products = sorted(
            cc_browser.get_products(),
            key=cc_browser.product_key_by_cat_and_name
        )
        self.eval_locals["items"] = products
        findings.extend(check_skus(self.config, products))
        for product in products:
            for key in ["Teaser"]:
                product[key] = cctools.html_to_plain_text(product[key])
            findings.extend(
                self.check_item(
                    "product",
                    product,
                    product_display_name(product)
                )
            )

        # Check variants list.
        variants = sorted(
            cc_browser.get_variants(),
            key=cc_browser.variant_key_by_cat_product
        )
        add_is_first_answer_flag(variants)
        self.eval_locals["items"] = variants
        for variant in variants:
            findings.extend(
                self.check_item(
                    "variant",
                    variant,
                    variant_display_name(variant)
                )
            )

        self.checks_completed()

        return findings
Ejemplo n.º 12
0
def generate_pdf(
    args,
    config,
    cc_browser,
    products
):
    """Generate a PDF given a list of products by category."""
    # Construct a document.
    doc_title = config.get("price_list", "title")
    doc = reportlab.platypus.BaseDocTemplate(
        args.pdf_file,
        pagesize=reportlab.lib.pagesizes.letter,
        title=doc_title,
        # showBoundary=True  # debug
    )

    # Construct a frame for each column.
    frames = create_col_frames(doc, args.ncols)

    # Construct a template and add it to the document.
    doc.my_title = doc_title
    doc.discount_percent = args.discount_percent
    doc.addPageTemplates(
        reportlab.platypus.PageTemplate(
            id="mytemplate",
            frames=frames,
            onPage=on_page
        )
    )

    # Construct a story and add it to the document.
    category_style = reportlab.lib.styles.ParagraphStyle(
        name="category",
        spaceBefore=0.15 * INCH,
        spaceAfter=0.05 * INCH,
        fontName="Helvetica-Bold",
        fontSize=12
    )
    greybar_color = reportlab.lib.colors.Whiter(
        reportlab.lib.colors.lightgrey,
        0.5
    )
    table_indent = 0.1 * INCH
    table_width = frames[0].width - table_indent
    price_width = 0.4 * INCH
    col_widths = [table_width - price_width, price_width]
    story = []

    # Sort products by category, product_name.
    if args.categories:
        cc_browser.set_category_sort_order(args.categories)
    products = sorted(products, key=cc_browser.product_key_by_cat_and_name)

    # Setup styles.
    body_fontsize = float(config.get("price_list", "body_fontsize"))
    row_padding =  float(config.get("price_list", "row_padding"))
    base_styles = [
        ("FONTSIZE", (0, 0), (-1, -1), body_fontsize),
        ("ALIGN", (0, 0), (0, -1), "LEFT"),
        ("ALIGN", (1, 0), (1, -1), "RIGHT"),
        ("FONT", (1, 0), (1, -1), "Courier-Bold"),
        ("LEFTPADDING", (0, 0), (-1, -1), 3),
        ("RIGHTPADDING", (0, 0), (-1, -1), 3),
        ("TOPPADDING", (0, 0), (-1, -1), row_padding),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3 + row_padding),
        # ("GRID", (0, 0), (-1, -1), 1.0, reportlab.lib.colors.black)
    ]

    # Group products by category.
    first = True
    for _, product_group in itertools.groupby(
        products,
        key=cc_browser.product_key_by_category
    ):
        # Make a new styles instance just for this table.
        styles = list(base_styles)
        if args.add_teaser:
            rows_per_product = 2
        else:
            rows_per_product = 1

        # Assemble table data for the product_group.
        table_data = list()
        row = 0
        for product in product_group:
            category = product["Category"]
            product_name = product["Product Name"]
            price = calc_price.calc_event_price(
                product["Price"],
                args.discount_percent,
                args.avg_tax_percent
            )
            # Format price as whole number string like "$1,234".
            price = "${:,.0f}".format(price)
            if args.add_sku:
                row_data = (
                    "{} ({})".format(product_name, product["SKU"]),
                    price
                )
            else:
                row_data = (product_name, price)
            table_data.append(row_data)
            row += 1
            if args.add_teaser:
                # Strip HTML formatting.
                product_teaser = cctools.html_to_plain_text(product["Teaser"])
                row_data = (product_teaser,)
                table_data.append(row_data)
                # Indent the teaser.
                styles.append(("LEFTPADDING", (0, row), (0, row), 18))
                row += 1
        if len(table_data) == 0:
            continue

        # Prevent page splitting in the middle of a product.
        if rows_per_product > 1:
            for row in range(0, len(table_data), rows_per_product):
                styles.append(
                    ("NOSPLIT", (0, row), (0, row + rows_per_product - 1))
                )

        # Grey background color to highlight alternate products.
        if args.greybar_interval > 1:
            interval = args.greybar_interval * rows_per_product
            for start_row in range(0, len(table_data), interval):
                for sub_row in range(0, rows_per_product):
                    row = start_row + sub_row
                    styles.append(
                        ("BACKGROUND", (0, row), (-1, row), greybar_color)
                    )

        # Create the table.
        table = reportlab.platypus.Table(
            data=table_data,
            colWidths=col_widths,
            style=styles
        )

        # Create a group of the category name and the products.
        category_group = [
            reportlab.platypus.Paragraph(category, category_style),
            reportlab.platypus.Indenter(left=table_indent),
            table,
            reportlab.platypus.Indenter(left=-table_indent)
        ]
        # There is a bug in platypus where if a KeepTogether is at
        # the top of a page and the KeepTogether is longer than a
        # page, then a blank page will be emitted.  We can't always
        # know when this will happen, but we know for certain it will
        # happen for the first category group.
        if first:
            for flowable in category_group:
                story.append(flowable)
            first = False
        else:
            story.append(reportlab.platypus.KeepTogether(category_group))

    doc.build(story)
Ejemplo n.º 13
0
def add_product(args, worksheet, row, item_no, product, variants):
    """Add row for each variant."""
    size = product["Size"]
    product_name = product["Product Name"]
    sku = product["SKU"]
    teaser = cctools.html_to_plain_text(product["Teaser"])
    msrp = float(product["Price"])
    price = msrp * args.price_multiplier
    price =\
        math.floor(price / args.price_precision + 0.5) * args.price_precision

    if args.include_variants:
        product_variants = get_product_variants(variants, sku)
    else:
        product_variants = []

    if product_variants:
        any_variant_exists = False
        for variant in product_variants:
            variant_sku = variant["Variant SKU"]
            if variant_sku == "ANY" or variant_sku == "VAR":
                any_variant_exists = True
            variant_sku = "{}-{}".format(sku, variant_sku)
            variant_add_price = float(variant["Variant Add Price"])
            variant_name = variant["Variant Name"]
            description = "{} ({}): {}".format(
                product_name,
                variant_name,
                teaser
            )
            add_variant(
                worksheet,
                row,
                item_no,
                size,
                variant_sku,
                description,
                calc_price.calc_wholesale_price(
                    price + variant_add_price,
                    args.wholesale_fraction
                ),
                msrp + variant_add_price
            )
            row += 1
            item_no += 1
        if CHECK_FOR_LACK_OF_ANY and not any_variant_exists:
            logging.getLogger().warning(
                "No 'Any' or 'Variety' variant exists for {} {}".format(
                    sku,
                    product_name
                )
            )
    else:
        description = "{}: {}".format(product_name, teaser)
        add_variant(
            worksheet,
            row,
            item_no,
            size,
            sku,
            description,
            calc_price.calc_wholesale_price(price, args.wholesale_fraction),
            msrp
        )
        row += 1
        item_no += 1

    return row, item_no