diff --git a/souschef/delivery/views.py b/souschef/delivery/views.py index b7adcf62..59a0c56e 100755 --- a/souschef/delivery/views.py +++ b/souschef/delivery/views.py @@ -1113,12 +1113,20 @@ def get(self, request, *args, **kwargs): component_lines = kcr_make_component_lines(kitchen_list, delivery_date) meal_lines = kcr_make_meal_lines(kitchen_list) + preperation_lines_with_incompatible_ingr = kcr_make_preparation_lines( + kitchen_list, "only_clients_with_incompatible_ingredients" + ) + preperation_lines_without_incompatible_ingr = kcr_make_preparation_lines( + kitchen_list, "only_clients_without_incompatible_ingredients" + ) if component_lines: # we have orders on that date num_pages = kcr_make_pages( # kitchen count as PDF delivery_date, component_lines, meal_lines, # summary + preperation_lines_with_incompatible_ingr, + preperation_lines_without_incompatible_ingr, ) # detail num_labels = kcr_make_labels( # meal labels as PDF delivery_date, @@ -1249,7 +1257,7 @@ def kcr_make_meal_lines(kitchen_list): [ (client_id, kitchen_item) for client_id, kitchen_item in kitchen_list.items() - if kitchen_item.incompatible_ingredients or kitchen_item.preparation + if kitchen_item.incompatible_ingredients ], key=lambda item: item[1].incompatible_ingredients, ) @@ -1388,17 +1396,62 @@ def format_client_name(firstname, lastname): return f"{lastname}, {firstname[:2]}." -def kcr_make_pages(kcr_date, component_lines, meal_lines): +def kcr_make_preparation_lines(kitchen_list, client_filter): + """Get food preparation method for clients not having clashing (incompatible) + ingredients.""" + if client_filter == "only_clients_with_incompatible_ingredients": + + def select_item(item): + return bool(item.incompatible_ingredients) + elif client_filter == "only_clients_without_incompatible_ingredients": + + def select_item(item): + return not item.incompatible_ingredients + else: + raise ValueError(f"Incompatible client_filter: {client_filter}") + + items = [item for item in kitchen_list.values() if select_item(item)] + + # Group KitchenItem per preparation method + items_per_preparation = collections.defaultdict(list) + for item in items: + for prep in item.preparation: + items_per_preparation[prep].append(item) + + # Return [(preparation_method, [formatted_client_name, ...]), ...] + return [ + ( + prep, + sorted( + format_client_name(item.firstname, item.lastname) + for item in items_per_preparation[prep] + ), + ) + for prep in sorted(items_per_preparation.keys()) + ] + + +def kcr_make_pages( + kcr_date, + component_lines, + meal_lines, + preperation_lines_with_incompatible_ingr, + preperation_lines_without_incompatible_ingr, +): """Generate the kitchen count report pages as a PDF file. Uses ReportLab see http://www.reportlab.com/documentation/faq/ Args: - kcr_date : The delivery date of the meals. - component_lines : A list of ComponentLine objects, the summary of + kcr_date: The delivery date of the meals. + component_lines: A list of ComponentLine objects, the summary of component quantities and sizes for the date's meal. - meal_lines : A list of MealLine objects, the details of the clients + meal_lines: A list of MealLine objects, the details of the clients for the date that have ingredients clashing with those in main dish. + preperation_lines_with_incompatible_ingr: + [(preparation_method, [formatted_client_name, ...]), ...] + preperation_lines_without_incompatible_ingr: + [(preparation_method, [formatted_client_name, ...]), ...] Returns: An integer : The number of pages generated. @@ -1459,6 +1512,42 @@ def myLaterPages(canvas, doc): drawHeader(canvas, doc) canvas.restoreState() + def get_food_preperation_table(preperation_lines, heading_suffix): + rows = [] + line = 0 + tab_style = RLTableStyle([("VALIGN", (0, 0), (-1, -1), "TOP")]) + rows.append( + [ + RLParagraph("Food Preparation", styles["NormalLeft"]), + RLParagraph("Quantity", styles["NormalRight"]), + "", + [ + RLParagraph("Clients", styles["NormalLeft"]), + RLParagraph(f"({heading_suffix})", styles["NormalLeftBold"]), + ], + ] + ) + tab_style.add("LINEABOVE", (0, line), (-1, line), 1, rl_colors.black) + tab_style.add("LINEBELOW", (0, line), (-1, line), 1, rl_colors.black) + tab_style.add("LINEBEFORE", (0, line), (0, line), 1, rl_colors.black) + tab_style.add("LINEAFTER", (-1, line), (-1, line), 1, rl_colors.black) + line += 1 + + for prepline in preperation_lines: + rows.append( + [ + RLParagraph(prepline[0], styles["LargeBoldLeft"]), + RLParagraph(str(len(prepline[1])), styles["NormalRightBold"]), + "", + RLParagraph( + ";   ".join(prepline[1]), styles["NormalLeft"] + ), + ] + ) + tab = RLTable(rows, colWidths=(150, 50, 10, 310), repeatRows=1) + tab.setStyle(tab_style) + return tab + def go(): """Generate the pages. @@ -1611,6 +1700,21 @@ def go(): story.append(RLSpacer(1, 1 * rl_inch)) # end Detail section + story.append(RLPageBreak()) + story.append( + get_food_preperation_table( + preperation_lines_with_incompatible_ingr, "with restrictions" + ) + ) + story.append(RLSpacer(1, 1 * rl_inch)) + + story.append( + get_food_preperation_table( + preperation_lines_without_incompatible_ingr, "without restrictions" + ) + ) + story.append(RLSpacer(1, 1 * rl_inch)) + # build full document doc.build(story, onFirstPage=myFirstPage, onLaterPages=myLaterPages) return doc.page