def send_emails(self): if not self.email_template: frappe.throw(frappe._("Email Template required to send emails")) subject, response = frappe.get_cached_value( "Email Template", self.email_template, ["subject", "response"] ) get_first_details = excepts(StopIteration, first, lambda _: {}) for contact_email, invoices in groupby( "contact_email", [x.as_dict() for x in self.invoices if x.contact_email] ).items(): context = merge( get_first_details(invoices), {"batch": self.batch, "invoices": invoices} ) _subject = frappe.render_template(subject, context) _message = frappe.render_template(response, context) frappe.sendmail( recipients=[contact_email], subject=_subject, message=_message, reference_doctype="Sales Invoice", reference_name=context.get("sales_invoice"), )
def _update_freight(bo, si): get_freight_row = compose( excepts(StopIteration, first, lambda _: None), lambda name: filter(lambda x: x.name == name, bo.freight), ) for sii in [x for x in si.items if x.gg_update_freight]: freight = get_freight_row(sii.gg_bo_detail) if freight: freight.based_on = frappe.get_cached_value("Item", sii.item_code, "gg_freight_based_on") if freight.based_on == "Packages": freight.no_of_packages = sii.qty elif freight.based_on == "Weight": freight.weight_actual = sii.qty freight.rate = sii.rate freight.amount = sii.amount
def _send_partner_assignment(doc): order = _get_so(doc) if not order: return fcm_token = frappe.get_cached_value("Sales Partner", doc.sales_partner, "le_fcm_token") if not fcm_token: return get_address = compose( json.dumps, list, filter(None), excepts( frappe.DoesNotExistError, lambda x: frappe.get_cached_value( "Address", x, ["address_line1", "address_line2"], ), lambda _: [], ), ) data = { "type": "job_assigment", "note_id": doc.name, "items": json.dumps([x.item_name for x in doc.items]), "scheduled_datetime": frappe.utils.get_datetime_str(doc.le_scheduled_datetime), "customer_name": doc.customer_name, "address": get_address(doc.shipping_address_name or doc.customer_address), } send_data(fcm_token, data)
def _get_root_groups(): def get_root(x): # assuming that parent - child relationship is never circular parent = get_parent(x) if parent: return get_root(parent) return x groups = frappe.get_all( "Item Group", fields=["name", "parent_item_group"], filters={"show_in_website": 1}, ) get_parent = compose( excepts(StopIteration, first, lambda _: None), lambda x: filter(lambda y: y.get("name") == x.get("parent_item_group"), groups), ) make_unique_roots = compose(list, unique, map(lambda x: x.get("name")), map(get_root)) return make_unique_roots(groups)
def _validate_freight_qty(doc): bo = frappe.get_cached_doc("Booking Order", doc.gg_booking_order) get_freight_row = compose( excepts(StopIteration, first, lambda _: None), lambda x: filter(lambda row: row.name == x, bo.freight), ) for item in doc.items: if item.gg_bo_detail: freight_row = get_freight_row(item.gg_bo_detail) if not freight_row: frappe.throw( frappe. _("Invalid Booking Order Freight Detail found in row #{} for {}" .format(item.idx, frappe.get_desk_link("Sales Invoice", doc.name)))) total_qty = (frappe.get_all( "Sales Invoice Item", filters={ "docstatus": 1, "gg_bo_detail": item.gg_bo_detail }, fields=["sum(qty)"], as_list=1, )[0][0] or 0) if total_qty + item.qty > _get_freight_qty(freight_row): frappe.throw( frappe. _("Total Qty in #{} for {} will exceed Freight Qty declared in {}" .format( item.idx, frappe.get_desk_link("Sales Invoice", doc.name), frappe.get_desk_link("Booking Order", doc.gg_booking_order), )))
def deliver(self, bo_detail, qty, unit, posting_datetime=None): deliverable = get_deliverable(bo_detail, self.destination_station) if qty > deliverable.get("qty"): frappe.throw( frappe._("Cannot deliver more than {} units".format(qty))) get_row = compose( excepts(StopIteration, first, lambda _: {}), filter(lambda x: x.get("name") == bo_detail), ) row = get_row(self.freight) if not row: frappe.throw(frappe._("Invalid item")) conversion_factor = get_loading_conversion_factor( qty, unit, row.get("no_of_packages"), row.get("weight_actual")) if not conversion_factor: frappe.throw(frappe._("Invalid conversion factor")) no_of_packages = row.get("no_of_packages") * conversion_factor weight_actual = row.get("weight_actual") * conversion_factor _posting_datetime = posting_datetime or frappe.utils.now() frappe.get_doc({ "doctype": "Booking Log", "posting_datetime": _posting_datetime, "booking_order": self.name, "station": self.destination_station, "activity": "Collected", "loading_unit": unit, "no_of_packages": -no_of_packages, "weight_actual": -weight_actual, "bo_detail": bo_detail, }).insert(ignore_permissions=True) self.set_as_completed()
import frappe import sys, traceback from toolz.curried import compose, excepts def handle_error(fn): def wrapper(*args, **kwargs): if "cmd" in kwargs.keys(): del kwargs["cmd"] try: return fn(*args, **kwargs) except Exception as e: frappe.logger("leiteng").error(e) traceback.print_exc(file=sys.stdout) return wrapper transform_route = compose( excepts(AttributeError, lambda x: x.replace("/", "__"), lambda _: None), lambda x: x.get("route"), )
def get_items(page="1", field_filters=None, attribute_filters=None, search=None): other_fieldnames = ["item_group", "thumbnail", "has_variants"] price_list = frappe.db.get_single_value("Shopping Cart Settings", "price_list") products_per_page = frappe.db.get_single_value("Products Settings", "products_per_page") get_item_groups = compose( list, unique, map(lambda x: x.get("name")), concat, map(lambda x: get_child_nodes("Item Group", x) if x and frappe.db.exists("Item Group", x, cache=True) else []), ) get_other_fields = compose( valmap(excepts(StopIteration, first, lambda _: {})), groupby("name"), lambda item_codes: frappe.db.sql( """ SELECT name, {other_fieldnames} FROM `tabItem` WHERE name IN %(item_codes)s """.format(other_fieldnames=", ".join(other_fieldnames)), values={"item_codes": item_codes}, as_dict=1, ), lambda items: [x.get("name") for x in items], ) get_page_count = compose( lambda x: frappe.utils.ceil(x[0][0] / products_per_page), lambda x: frappe.db.sql( """ SELECT COUNT(name) FROM `tabItem` WHERE show_in_website = 1 AND item_group IN %(item_groups)s """, values={"item_groups": x}, ), ) field_dict = (frappe.parse_json(field_filters) if isinstance( field_filters, str) else field_filters) or {} item_groups = (get_item_groups(field_dict.get("item_group")) if field_dict.get("item_group") else None) frappe.form_dict.start = (frappe.utils.cint(page) - 1) * products_per_page items = get_products_for_website( field_filters=merge( field_dict, {"item_group": item_groups} if item_groups else {}), attribute_filters=frappe.parse_json(attribute_filters), search=search, ) other_fields = get_other_fields(items) if items else {} item_prices = _get_item_prices(price_list, items) if items else {} get_rates = _rate_getter(price_list, item_prices) return { "page_count": get_page_count(item_groups) if item_groups else 0, "items": [ merge( x, { "route": transform_route(x), "description": frappe.utils.strip_html_tags(x.get("description") or ""), }, get_rates(x.get("name")), { k: other_fields.get(x.get("name"), {}).get(k) for k in other_fieldnames }, ) for x in items ], }
images = get_values(item_code, ) template_images = get_values(variant_of) if variant_of else {} def get_image(field): return images.get(field) or template_images.get(field) return { "thumbnail": get_image("thumbnail"), "image": get_image("image"), "website_image": get_image("website_image"), "slideshow": get_slideshows(get_image("slideshow")), } _get_item_prices = compose( valmap(excepts(StopIteration, first, lambda _: {})), groupby("item_code"), lambda price_list, items: frappe.db.sql( """ SELECT item_code, price_list_rate FROM `tabItem Price` WHERE price_list = %(price_list)s AND item_code IN %(item_codes)s """, values={ "price_list": price_list, "item_codes": [x.get("name") for x in items] }, as_dict=1, ) if price_list else {}, )
def get_mop_amount(mode_of_payment=None, payments=[]): return compose( lambda x: x.get("amount"), excepts(StopIteration, first, lambda x: {"amount": 0}), filter(lambda x: x.get("mode_of_payment") == mode_of_payment), )(payments)