def fn(discount): brands = brands_by_category.get(discount.get("brand_category"), []) return map( lambda x: merge(pick(["brand"], x), pick(["discount_rate"], discount)), brands, )
def _get_branch_details(): branch = get_user_branch() if not branch: return None doc = frappe.get_doc("Branch", branch) return pick(["name", "branch_phone", "os_cr_no"], doc.as_dict()) if doc else None
def add_loyalty_points(customer): loyalty_points = get_loyalty_details( customer.get("name"), customer.get("loyalty_program"), expiry_date=query_date, ) return merge(customer, pick(["loyalty_points"], loyalty_points))
def _get_filters(filters): join_columns = compose(lambda x: " AND ".join(x), concatv) item_clauses = join_columns( ["i.disabled = 0"], ["i.item_group = %(item_group)s"] if filters.item_group else [], ["i.brand = %(brand)s"] if filters.brand else [], ["i.name = %(item_code)s"] if filters.item_code else [], ["INSTR(i.item_name, %(item_name)s) > 0"] if filters.item_name else [], ) sle_clauses = join_columns( ["sle.posting_date BETWEEN %(start_date)s AND %(end_date)s"]) def get_dates(): query_date = frappe.utils.getdate(filters.query_date) if filters.period == "Monthly": return { "start_date": frappe.utils.get_first_day(query_date), "end_date": frappe.utils.get_last_day(query_date), } if filters.period == "Yearly": return { "start_date": query_date.replace(month=1, day=1), "end_date": query_date.replace(month=12, day=31), } frappe.throw(_("Unknown period")) values = merge( pick(["item_group", "brand", "item_code", "item_name"], filters), get_dates()) return {"item_clauses": item_clauses, "sle_clauses": sle_clauses}, values
def _set_workflow_updates(result): get_comments = compose( partial( valmap, lambda comments: {x.get("comment"): x.get("creation") for x in comments}, ), partial(groupby, "docname"), partial(map, lambda x: pick(["docname", "creation", "comment"], x)), partial(filter, lambda x: x.get("comment_type") == "Workflow"), partial(map, lambda x: merge(x, json.loads(x.get("data", "{}")))), ) versions = frappe.db.sql( """ SELECT docname, creation, data FROM `tabVersion` WHERE ref_doctype = 'Sales Order' AND docname IN %(sales_orders)s """, values={"sales_orders": [x.get("sales_order") for x in result]}, as_dict=1, ) comments = get_comments(versions) def fn(row): docname = row.get("sales_order") return merge(row, {"Draft": row.get("creation")}, comments.get(docname, {})) return fn
def _get_filters(filters): opening_clause = concatv( ["posting_date < %(from_date)s"], ["customer = %(customer)s"] if filters.customer else [], ["loyalty_program = %(loyalty_program)s"] if filters.loyalty_program else [], ) period_clause = concatv( ["posting_date BETWEEN %(from_date)s AND %(to_date)s"], ["customer = %(customer)s"] if filters.customer else [], ["loyalty_program = %(loyalty_program)s"] if filters.loyalty_program else [], ) values = merge( pick(["customer", "loyalty_program"], filters), { "from_date": filters.date_range[0], "to_date": filters.date_range[1] }, ) return ( { "opening_clause": " AND ".join(opening_clause), "period_clause": " AND ".join(period_clause), }, values, )
def _get_filters(filters): def get_branches(): if any(role in ["Accounts Manager"] for role in frappe.get_roles()): return split_to_list(filters.branches) user_branch = get_user_branch() if (any(role in ["Branch User", "Branch Stock"] for role in frappe.get_roles()) and user_branch): return [user_branch] frappe.throw( _("Manager privilege or Branch User / Branch Stock role required")) branches = get_branches() clauses = concatv( [ "st.outgoing_datetime <= %(to_date)s", "IFNULL(st.incoming_datetime, CURRENT_DATE) >= %(from_date)s", ], ["st.docstatus = 1"] if not cint(filters.show_all) else [], [ "(st.source_branch IN %(branches)s OR st.target_branch IN %(branches)s)" ] if branches else [], ) values = merge( pick(["from_date", "to_date"], filters), {"branches": branches} if branches else {}, ) return " AND ".join(clauses), values
def get_customer_loyalty_details(customer, loyalty_card_no, expiry_date, company): if loyalty_card_no != frappe.db.get_value("Customer", customer, "os_loyalty_card_no"): frappe.throw(_("Loyalty Card does not belong to this Customer")) program = get_loyalty_program_details(customer, expiry_date=expiry_date, company=company) points = get_loyalty_details(customer, program.loyalty_program, expiry_date=expiry_date, company=company) return merge( pick(["loyalty_program", "conversion_factor"], program), pick(["loyalty_points"], points), )
def _get_filters(filters): branches = split_to_list(filters.branch) clauses = concatv( ["s.docstatus = 1", "s.posting_date = %(posting_date)s"], ["s.os_branch IN %(branches)s"] if branches else [], ) values = merge(pick(["posting_date"], filters), {"branches": branches} if branches else {}) return " AND ".join(clauses), values
def make_line(invoice): return merge( pick(["name"], invoice), { "amount": -invoice.get("outstanding_amount"), "expiry_date": frappe.utils.add_days(invoice.get("posting_date"), expiry_days) if expiry_days else None, }, )
def on_submit(self): if self.workflow_state == "In Transit": warehouses = self.get_warehouses(incoming=False) accounts = self.get_accounts() ref_doc = _make_stock_entry( merge( pick(["company"], self.as_dict()), warehouses, {"items": _map_items(warehouses, accounts)(self.items)}, _destruct_datetime(self.outgoing_datetime), )) self.set_ref_doc("outgoing_stock_entry", ref_doc)
def on_update_after_submit(self): if self.workflow_state == "Received": warehouses = self.get_warehouses(incoming=True) accounts = self.get_accounts() ref_doc = _make_stock_entry( merge( pick(["company"], self.as_dict()), warehouses, {"items": _map_items(warehouses, accounts)(self.items)}, _destruct_datetime(self.incoming_datetime), )) self.set_ref_doc("incoming_stock_entry", ref_doc)
def _get_filters(filters): join = compose(lambda x: " AND ".join(x), concatv) clauses = join( ["True"], ["so.os_branch = %(branch)s"] if filters.branch else [], ["so.workflow_state != 'Collected'"] if not filters.show_collected else [], ) values = merge( pick(["branch"], filters), { "from_date": filters.date_range[0], "to_date": filters.date_range[1] }, ) return clauses, values
def validate_loyalty(doc): def get_dict(obj): if isinstance(obj, frappe.model.document.Document): return obj.as_dict() if isinstance(obj, string_types): return json.loads(obj) if isinstance(obj, dict): return obj return {} code = frappe.db.get_single_value("Optical Store Settings", "loyalty_validation") locals = frappe._dict(pick(["loyalty_points"], get_dict(doc))) if code and not frappe.safe_eval(code, eval_locals=locals): frappe.throw( _("Loyalty validation failed." "Please correct loyalty fields or contact System Manager."))
def _get_filters(filters): clauses = concatv( [ "si.docstatus = 1", "si.posting_date BETWEEN %(from_date)s AND %(to_date)s", "si.customer = %(customer)s", ], ["si.os_branch = %(branch)s"] if filters.branch else [], ) values = merge( pick(["customer", "branch"], filters), { "from_date": filters.date_range[0], "to_date": filters.date_range[1], "item_wise": cint(filters.item_wise), }, ) return " AND ".join(clauses), values
def _get_filters(filters): branches = (compose( partial(filter, lambda x: x), partial(map, lambda x: x.strip()), lambda x: x.split(","), )(filters.branch) if filters.branch else None) clauses = concatv( [ "s.docstatus = 1", "s.posting_date BETWEEN %(from_date)s AND %(to_date)s" ], ["s.os_branch IN %(branches)s"] if branches else [], ) values = merge( pick(["from_date", "to_date"], filters), {"branches": branches} if branches else {}, ) return " AND ".join(clauses), values
def _get_filters(filters): item_groups = split_to_list(filters.item_groups) brands = split_to_list(filters.brands) item_codes = split_to_list(filters.item_codes) clauses = concatv( ["i.disabled = 0"], ["i.item_group IN %(item_groups)s"] if item_groups else [], ["i.brand IN %(brands)s"] if brands else [], ["i.item_code IN %(item_codes)s"] if item_codes else [], ["INSTR(i.item_name, %(item_name)s) > 0"] if filters.item_name else [], ) values = merge( pick(["item_name"], filters), {"item_groups": item_groups} if item_groups else {}, {"brands": brands} if brands else {}, {"item_codes": item_codes} if item_codes else {}, ) return " AND ".join(clauses), values
def _get_filters(filters): clauses = concatv( [ "sle.docstatus = 1", "sle.company = %(company)s", "sle.posting_date <= %(query_date)s", "IFNULL(sle.batch_no, '') != ''", ], ["sle.warehouse = %(warehouse)s"] if filters.get("warehouse") else [], ["i.item_group = %(item_group)s"] if filters.get("item_group") else [], ) values = pick( [ "company", "query_date", "warehouse", "item_group", "buying_price_list", "selling_price_list", ], filters, ) return " AND ".join(clauses), values
def _get_filters(filters): modes_of_payment = split_to_list(filters.modes_of_payment) branches = split_to_list(filters.branches) si_clauses = concatv( [ "si.docstatus = 1", "si.posting_date BETWEEN %(start_date)s AND %(end_date)s" ], ["si.is_return = 0"] if cint(filters.hide_returns) else [], ["si.os_branch IN %(branches)s"] if branches else [], ["sip.mode_of_payment IN %(modes_of_payment)s"] if modes_of_payment else [], ) pe_clauses = concatv( [ "pe.docstatus = 1", "pe.party_type = 'Customer'", "pe.posting_date BETWEEN %(start_date)s AND %(end_date)s", ], ["pe.payment_type = 'Receive'"] if cint(filters.hide_returns) else [], ["pe.os_branch IN %(branches)s"] if branches else [], ["pe.mode_of_payment IN %(modes_of_payment)s"] if modes_of_payment else [], ) values = merge( pick(["start_date", "end_date"], filters), {"branches": branches} if branches else {}, {"modes_of_payment": modes_of_payment} if modes_of_payment else {}, ) return ( { "si_clauses": " AND ".join(si_clauses), "pe_clauses": " AND ".join(pe_clauses), }, values, )
def get_items( start, page_length, price_list, item_group, search_value="", pos_profile=None, customer=None, ): debug = frappe.db.get_single_value("Optical Store Settings", "debug_query") search_data = (search_serial_or_batch_or_barcode_number(search_value) if search_value else {}) clauses, values = _get_conditions( merge( { "start": cint(start), "page_length": cint(page_length), "price_list": price_list, "item_group": item_group or get_root_of("Item Group"), "search_value": search_value, "pos_profile": pos_profile, "customer": customer, }, search_data, )) items = frappe.db.sql( """ SELECT i.name AS item_code, i.item_name AS item_name, i.image AS item_image, i.idx AS idx, i.is_stock_item AS is_stock_item, i.variant_of AS variant_of FROM `tabItem` AS i LEFT JOIN `tabItem Group` AS ig ON ig.name = i.item_group {stock_clause} WHERE {clauses} ORDER BY i.idx LIMIT %(start)s, %(page_length)s """.format(**clauses), values=values, as_dict=1, debug=debug, ) def list_items(items): make_list = compose(partial(filterf, lambda x: x), unique, concatv) return make_list(pluck("item_code", items), pluck("variant_of", items)) make_prices = compose(partial(valmap, partial(groupby, "item_code")), partial(groupby, "price_list")) # better to use a second query to fetch prices because combining with items query # takes considerably longer prices = (make_prices( frappe.db.sql( """ SELECT i.name AS item_code, ip.price_list AS price_list, ip.price_list_rate AS price_list_rate, ip.currency AS currency FROM `tabItem Price` AS ip LEFT JOIN `tabItem` AS i ON i.name = ip.item_code WHERE ip.selling = 1 AND ip.item_code IN %(items)s AND IFNULL(ip.uom, '') IN (i.stock_uom, '') AND IFNULL(ip.min_qty, 0) <= 1 AND IFNULL(ip.customer, '') IN (%(customer)s, '') AND CURDATE() BETWEEN IFNULL(ip.valid_from, '2000-01-01') AND IFNULL(ip.valid_upto, '2500-12-31') """, values={ "items": list_items(items), "customer": customer }, as_dict=1, debug=debug, )) if items else []) def add_price(prices): def make_price(item_code): return compose( excepts(StopIteration, first, lambda x: {}), partial(get, item_code, default=[]), lambda x: get(x, prices, {}), ) def fn(item): item_price = make_price(item.item_code) template_price = make_price(item.variant_of) sp = item_price(price_list) or template_price(price_list) ms1 = item_price("Minimum Selling") or template_price( "Minimum Selling") ms2 = item_price("Minimum Selling 2") or template_price( "Minimum Selling 2") return merge( item, { "price_list_rate": get("price_list_rate", sp, 0), "currency": get("currency", sp, 0), "os_minimum_selling_rate": get("price_list_rate", ms1, 0), "os_minimum_selling_2_rate": get("price_list_rate", ms2, 0), }, ) return fn make_item = compose( partial( pick, [ "item_code", "item_name", "idx", "is_stock_item", "price_list_rate", "currency", "os_minimum_selling_rate", "os_minimum_selling_2_rate", ], ), add_price(prices), ) return merge( {"items": mapf(make_item, items)}, pick(["barcode", "serial_no", "batch_no"], search_data), )
def deliver_qol(name, payments=[], batches=None, deliver=0): is_delivery = cint(deliver) si = frappe.get_doc("Sales Invoice", name) _validate_workflow() if is_delivery: _validate_qol(batches, si) def make_payment(payment): pe = _make_payment_entry( name, payment.get("mode_of_payment"), payment.get("amount"), payment.get("gift_card_no"), ) pe.insert(ignore_permissions=True) pe.submit() pe.name make_payments = compose(partial(mapf, make_payment), json.loads) pe_names = make_payments(payments) if payments else [] result = {"payment_entries": pe_names} if is_delivery: dn = make_delivery_note(name) dn.os_branch = si.os_branch warehouse = ( frappe.db.get_value("Branch", si.os_branch, "warehouse") if si.os_branch else None ) if batches: get_batches = compose(unique, partial(pluck, "item_code"), json.loads) batch_items = filterf( lambda x: x.item_code in get_batches(batches), dn.items ) def get_item(field, value): return compose( lambda x: x.as_dict() if x else {}, excepts(StopIteration, first, lambda x: None), partial(filter, lambda x: x.get(field) == value), )(batch_items) dn.items = filterf(lambda x: x not in batch_items, dn.items) for batch in json.loads(batches): si_detail = batch.get("si_detail") item = merge( ( get_item("si_detail", si_detail) or get_item("batch_no", batch.get("batch_no")) or get_item("item_code", batch.get("item_code")) ), pick(["item_code", "batch_no", "qty"], batch,), {"si_detail": si_detail} if si_detail else {}, ) dn.append("items", item) if warehouse: for item in dn.items: item.warehouse = warehouse dn.insert(ignore_permissions=True) dn.submit() result = merge(result, {"delivery_note": dn.name}) return result
def update_details(customer, data): cust_id = get_customer_id(data, customer) doc = frappe.get_doc("Customer", cust_id) doc.update(pick(CUSTOMER_DETAILS_FIELDS, data)) doc.flags.ignore_mandatory = True doc.save(ignore_permissions=True)
def set_report_details(self): args = merge( pick(["user", "pos_profile", "company"], self.as_dict()), { "start_time": self.start_time or now(), "end_time": self.end_time or now(), }, ) sales, returns = _get_invoices(args) sales_payments, returns_payments, collection_payments = _get_payments( args) taxes = _get_taxes(args) make_invoice = partial( pick, ["invoice", "total_qty", "grand_total", "paid_amount"]) make_payment = partial(pick, ["mode_of_payment", "amount"]) make_tax = partial(pick, ["rate", "tax_amount"]) mops = compose(unique, partial(pluck, "mode_of_payment")) def get_mop_amount(mode_of_payment, payments=[]): return compose( partial(get, "amount"), excepts(StopIteration, first, lambda x: {"amount": 0}), partial(filter, lambda x: x.get("mode_of_payment") == mode_of_payment), )(payments) get_cash = partial(get_mop_amount, "Cash") get_sales_amount = partial(get_mop_amount, payments=sales_payments) get_returns_amount = partial(get_mop_amount, payments=returns_payments) get_collection_amount = partial(get_mop_amount, payments=collection_payments) def make_payment(mode_of_payment): sales_amount = get_sales_amount(mode_of_payment) returns_amount = get_returns_amount(mode_of_payment) collection_amount = get_collection_amount(mode_of_payment) return { "mode_of_payment": mode_of_payment, "sales_amount": sales_amount, "returns_amount": returns_amount, "collection_amount": collection_amount, "total_amount": sales_amount + returns_amount + collection_amount, } sum_by_total = sum_by("total") sum_by_net = sum_by("net_total") sum_by_discount = compose(neg, sum_by("discount_amount")) sum_by_taxes = sum_by("tax_amount") sum_by_grand = sum_by("grand_total") self.cash_sales = get_cash(sales_payments) self.cash_returns = get_cash(returns_payments) self.cash_pe_received = get_cash(collection_payments) self.sales__total = sum_by_total(sales) - sum_by_total(returns) self.total__discount_amount = sum_by_discount(sales) + sum_by_discount( returns) self.returns__net_total = sum_by_net(returns) self.total__net_total = sum_by_net(sales + returns) self.total__total_taxes_and_charges = sum_by_taxes(taxes) self.total__grand_total = sum_by_grand(sales) + sum_by_grand(returns) self.sales = [] for invoice in sales: self.append("sales", make_invoice(invoice)) self.returns = [] for invoice in returns: self.append("returns", make_invoice(invoice)) self.payments = [] for payment in mops(sales_payments + returns_payments + collection_payments): self.append("payments", make_payment(payment)) self.taxes = [] for tax in taxes: self.append("taxes", make_tax(tax)) self.total_collection = sum_by("total_amount")(self.payments)