Пример #1
0
 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,
     )
Пример #2
0
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
Пример #3
0
 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))
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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,
    )
Пример #7
0
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
Пример #8
0
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),
    )
Пример #9
0
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
Пример #10
0
 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,
         },
     )
Пример #11
0
 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)
Пример #12
0
 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)
Пример #13
0
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
Пример #14
0
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."))
Пример #15
0
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
Пример #16
0
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
Пример #17
0
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
Пример #19
0
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,
    )
Пример #20
0
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),
    )
Пример #21
0
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
Пример #22
0
 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)
Пример #23
0
    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)