예제 #1
0
def set_item_prices(items, posting_date, posting_time):
    get_rate = compose(
        excepts(IndexError, partial(get, 1), lambda __: None),
        excepts(StopIteration, first, lambda __: []),
        excepts(TypeError, json.loads, lambda __: []),
        lambda x: x.stock_queue,
        lambda x: get_previous_sle({
            "item_code": x,
            "posting_date": posting_date,
            "posting_time": posting_time
        }),
    )
    selling_price_list = frappe.db.get_single_value("Selling Settings",
                                                    "selling_price_list")

    def get_price(item_code):
        get_first = compose(partial(get, "name"),
                            excepts(StopIteration, first, lambda __: {}))
        prices = frappe.db.sql(
            """
                SELECT name FROM `tabItem Price`
                WHERE
                    item_code = %(item_code)s AND
                    price_list = %(price_list)s AND
                    IFNULL(uom, '') = ''
            """,
            values={
                "item_code": item_code,
                "price_list": selling_price_list
            },
            as_dict=1,
        )
        if len(prices) > 1:
            frappe.throw(
                frappe._(
                    "Cannot set {} Item Price because multiple prices exists").
                format(selling_price_list))
        item_price = get_first(prices)
        return frappe.get_doc("Item Price", item_price) if item_price else None

    def has_margin_price(item_code):
        return frappe.db.get_value("Item", item_code, "vn_has_margin_price")

    for item in items:
        if has_margin_price(item.item_code):
            rate = get_rate(item.item_code)
            if rate:
                item_price = get_price(item.item_code)
                if item_price and item_price.price_list_rate != rate:
                    item_price.price_list_rate = rate
                    item_price.save()
예제 #2
0
def _set_sales_orders(rows):
    get_orders = compose(
        partial(groupby, "invoice"),
        partial(unique, key=lambda x: x.get("invoice")),
        lambda x: frappe.db.sql(
            """
            SELECT
                sii.parent AS invoice,
                sii.sales_order AS sales_order,
                so.workflow_state AS order_status
            FROM `tabSales Invoice Item` AS sii
            LEFT JOIN `tabSales Order` AS so ON so.name = sii.sales_order
            WHERE sii.parent IN %(invoices)s
        """,
            values={"invoices": x},
            as_dict=1,
        ),
        list,
        unique,
        partial(pluck, "invoice"),
    )

    orders = get_orders(rows)
    set_sales_order = compose(
        excepts(StopIteration, first, lambda _: {}),
        lambda x: orders.get(x, []),
        lambda x: x.get("invoice"),
    )

    def fn(row):
        return merge(row, set_sales_order(row))

    return fn
예제 #3
0
 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)
예제 #4
0
def get_standard_prices(item_code):
    buying_price_list = frappe.db.get_single_value("Buying Settings",
                                                   "buying_price_list")
    selling_price_list = frappe.db.get_single_value("Selling Settings",
                                                    "selling_price_list")
    stock_uom = frappe.db.get_value("Item", item_code, "stock_uom")

    get_price = compose(
        lambda x: x.get("price_list_rate"),
        excepts(StopIteration, first, lambda _0: {}),
        lambda x: frappe.db.sql(
            """
                SELECT price_list_rate FROM `tabItem Price`
                WHERE
                    item_code = %(item_code)s AND
                    price_list = %(price_list)s AND
                    IFNULL(uom, '') IN ('', %(stock_uom)s) AND
                    IFNULL(customer, '') = ''
            """,
            values={
                "item_code": item_code,
                "price_list": x,
                "stock_uom": stock_uom
            },
            as_dict=1,
        ),
    )

    return {
        "selling_price": get_price(selling_price_list),
        "buying_price": get_price(buying_price_list),
    }
def _get_payments(args):
    payments = frappe.db.sql(
        """
            SELECT
                sip.mode_of_payment AS mode_of_payment,
                sip.type AS type,
                SUM(sip.base_amount) AS amount,
                sip.mop_currency AS mop_currency,
                SUM(sip.mop_amount) AS mop_amount
            FROM `tabSales Invoice Payment` AS sip
            LEFT JOIN `tabSales Invoice` AS si ON
                sip.parent = si.name
            WHERE sip.parenttype = 'Sales Invoice' AND {clauses}
            GROUP BY sip.mode_of_payment
        """.format(clauses=_get_clauses()),
        values=args,
        as_dict=1,
    )
    default_mop = compose(
        excepts(StopIteration, first, lambda __: None),
        partial(pluck, "mode_of_payment"),
        frappe.get_all,
    )(
        "Sales Invoice Payment",
        fields=["mode_of_payment"],
        filters={
            "parenttype": "POS Profile",
            "parent": args.get("pos_profile"),
            "default": 1,
        },
    )
    return _correct_mop_amounts(payments, default_mop)
예제 #6
0
def _validate_cashback(doc):
    cashback_mop = "Cashback"
    if cashback_mop not in [
            x.mode_of_payment for x in doc.payments if x.amount != 0
    ]:
        return
    if not doc.os_cashback_receipt:
        frappe.throw(
            _("Cashback Receipt required if using Mode of Payment {}".format(
                frappe.bold(cashback_mop))))
    get_cb_redeemed_amt = compose(
        excepts(StopIteration, first, lambda _: 0),
        lambda _=None:
        [x.amount for x in doc.payments if x.mode_of_payment == cashback_mop],
    )

    redeemed_amt = get_cb_redeemed_amt()
    balance_amt, expiry_date = frappe.db.get_value(
        "Cashback Receipt", doc.os_cashback_receipt,
        ["balance_amount", "expiry_date"])
    if redeemed_amt > balance_amt:
        frappe.throw(
            _("Redeemed cashback amount cannot be greater than available balance "
              "{}.".format(
                  frappe.bold(
                      frappe.utils.fmt_money(balance_amt,
                                             currency=doc.currency)))))

    if getdate(doc.posting_date) > expiry_date:
        frappe.throw(_("Cashback Receipt has expired."))
예제 #7
0
파일: item.py 프로젝트: azhkhn/pos_bahrain
def get_pos_data():
    from erpnext.accounts.doctype.sales_invoice.pos import get_pos_data

    get_price = compose(
        partial(get, "price_list_rate", default=0),
        excepts(StopIteration, first, lambda __: {}),
    )

    get_price_list_data = compose(partial(valmap, get_price), _get_default_item_prices)

    def add_discounts(items):
        item_codes = compose(list, partial(pluck, "name"))(items)
        max_discounts_by_item = compose(partial(key_by, "name"), frappe.db.sql)(
            """
                SELECT name, max_discount FROM `tabItem`
                WHERE item_code IN %(item_codes)s
            """,
            values={"item_codes": item_codes},
            as_dict=1,
        )
        return [merge(x, max_discounts_by_item.get(x.get("name")), {}) for x in items]

    data = get_pos_data()

    return merge(
        data,
        {"price_list_data": get_price_list_data(data.get("doc").selling_price_list)},
        {"items": add_discounts(data.get("items"))},
    )
예제 #8
0
파일: __init__.py 프로젝트: magreiner/MMLP
def excepting_pipe(data, *funcs):
    for func in funcs:
        data = excepts(Exception, func, lambda _: _)(data)
        if isinstance(data, Exception):
            # Modify the error object to preserve the function name where it occurred
            # A generic error class would be better
            if hasattr(func, '__code__'):
                if hasattr(func, 'args'):
                    print(
                        f'Exception occurred in excepting pipe function {repr(func.__code__), func.args}: {data}'
                    )
                    data.args = (
                        f'{repr(func.__code__), func.args}: {data.args[0]}', )
                else:
                    print(
                        f'Exception occurred in excepting pipe function {repr(func.__code__)}: {data}'
                    )
                    data.args = (f'{repr(func.__code__)}: {data.args[0]}', )
            else:
                if hasattr(func, 'args'):
                    print(
                        f'Exception occurred in excepting pipe function {repr(func.__name__), func.args}: {data}'
                    )
                    data.args = (
                        f'{repr(func.__name__), func.args}: {data.args[0]}', )
                else:
                    print(
                        f'Exception occurred in excepting pipe function {repr(func.__name__)}: {data}'
                    )
                    data.args = (f'{repr(func.__name__)}: {data.args[0]}', )
            return data
    return data
예제 #9
0
def get_cashback_program(branch, posting_date):
    program_names = [
        x.get("name") for x in frappe.db.sql(
            """
                SELECT cp.name AS name FROM `tabCashback Program` AS cp
                LEFT JOIN `tabCashback Program Branch` AS cpb ON
                    cpb.parent = cp.name
                WHERE
                    cp.disabled = 0 AND
                    cpb.branch = %(branch)s AND
                    %(posting_date)s BETWEEN
                        cp.from_date AND IFNULL(cp.to_date, '9999-12-31')
            """,
            values={
                "branch": branch,
                "posting_date": posting_date
            },
            as_dict=1,
        )
    ]
    if len(program_names) > 1:
        frappe.throw(
            frappe._(
                "Something is wrong. More than one Cashback Program found."))

    get_program = compose(
        lambda x: frappe.get_doc("Cashback Program", x) if x else None,
        excepts(StopIteration, first, lambda x: None),
    )

    return get_program(program_names)
예제 #10
0
def translate_exception(func: Callable, exc1: Exception, exc2: Exception):
    """A functional try/except block: if `func` fails with `exc1`, raise `exc2`.

    >>> from gamla import functional_generic
    >>> functional_generic.pipe(iter([]), translate_exception(next, StopIteration, ValueError))
    ValueError
    Note: `func` is assumed to be unary."""
    return toolz.excepts(exc1, func, make_raise(exc2))
def _county_fips_name(fips):
    return pipe(
        Granularity.COUNTY, geo_data, curried.get("features"),
        curry(filter, lambda region: region["id"] == fips),
        excepts(
            StopIteration,
            lambda x: pipe(x, first, curried.get_in(["properties", "NAME"])),
            lambda _: None))
예제 #12
0
def _get_trainer(member, subscriptions):
    training_sub = compose(
        excepts(StopIteration, first, lambda __: None),
        partial(filter, lambda x: x.get("is_training") == 1),
    )(subscriptions)
    if not training_sub:
        return None
    return get_last(member, subscription_item=training_sub.get("item"))
예제 #13
0
 def get_form_collected(mop):
     existing = compose(
         excepts(StopIteration, first, lambda x: None),
         partial(filter, lambda x: x.mode_of_payment == mop),
     )(existing_payments)
     if not existing or existing.collected_amount == existing.expected_amount:
         return {}
     return {"collected_amount": existing.collected_amount}
예제 #14
0
def track_exceptions(f, caught, default=None):
    """
    Decorate ``f`` with a function that traps exceptions and appends them to
    ``caught``, returning ``default`` in their place.
    """
    def _catch(_):
        caught.append(sys.exc_info())
        return default
    return excepts(Exception, f, _catch)
예제 #15
0
def get_ref_so_date(sales_invoice):
    get_transaction_dates = compose(
        excepts(ValueError, min, lambda x: None),
        partial(
            map, lambda x: frappe.db.get_value("Sales Order", x, "transaction_date")
        ),
        _get_sales_orders,
    )
    return get_transaction_dates(sales_invoice)
예제 #16
0
def set_or_create_batch(doc, method):
    def set_existing_batch(item):
        if item.os_expiry_date and not item.batch_no:
            has_batch_no, has_expiry_date = frappe.db.get_value(
                "Item", item.item_code, ["has_batch_no", "has_expiry_date"])
            if has_batch_no and has_expiry_date:
                batch_no = frappe.db.exists(
                    "Batch",
                    {
                        "item": item.item_code,
                        "expiry_date": item.os_expiry_date
                    },
                )
                item.batch_no = batch_no

    get_batch_in_previous_items = compose(
        lambda x: x.get("batch_no"),
        excepts(StopIteration, first, lambda _: {}),
        lambda x: filter(
            lambda item: item.idx < x.idx and item.item_code == x.item_code and
            item.pb_expiry_date == x.pb_expiry_date,
            doc.items,
        ),
    )

    def create_new_batch(item):
        warehouse = "t_warehouse" if doc.doctype == "Stock Entry" else "warehouse"
        if item.get(warehouse) and item.os_expiry_date and not item.batch_no:
            has_batch_no, create_new_batch, has_expiry_date = frappe.db.get_value(
                "Item",
                item.item_code,
                ["has_batch_no", "create_new_batch", "has_expiry_date"],
            )
            if has_batch_no and create_new_batch and has_expiry_date:
                batch_in_items = get_batch_in_previous_items(item)
                if batch_in_items:
                    item.batch_no = batch_in_items
                    return
                batch = frappe.get_doc({
                    "doctype": "Batch",
                    "item": item.item_code,
                    "expiry_date": item.os_expiry_date,
                    "supplier": doc.supplier,
                    # "reference_doctype": doc.doctype,
                    # "reference_name": doc.name,
                }).insert()
                item.batch_no = batch.name

    if doc._action == "save":
        map_resolved(set_existing_batch, doc.items)

        # TODO: when `before_validate` gets merged into master create_new_batch should
        # run when doc._action == 'submit'.
        # also update `hooks.py` to use `before_validate` instead of the current
        # `before_save` method
        map_resolved(create_new_batch, doc.items)
def _set_consumption(sles, periods):
    def groupby_filter(sl):
        def fn(p):
            return p.get("start_date") <= sl.get("posting_date") <= p.get(
                "end_date")

        return fn

    groupby_fn = compose(
        partial(get, "key", default=None),
        excepts(StopIteration, first, lambda __: {}),
        partial(flip, filter, periods),
        groupby_filter,
    )

    sles_grouped = groupby(groupby_fn, sles)

    summer = compose(operator.neg, sum, partial(pluck, "actual_qty"))

    def seg_filter(x):
        return lambda sl: sl.get("item_code") == x

    segregator_fns = map(
        lambda x: merge(
            x,
            {
                "seger":
                compose(
                    summer,
                    partial(flip, filter, get(x.get("key"), sles_grouped, [])),
                    seg_filter,
                )
            },
        ),
        periods,
    )

    def seg_reducer(item_code):
        def fn(a, p):
            key = get("key", p, None)
            seger = get("seger", p, lambda __: None)
            return merge(a, {key: seger(item_code)})

        return fn

    total_fn = compose(summer, partial(flip, filter, sles), seg_filter)

    def fn(item):
        item_code = item.get("item_code")
        return merge(
            item,
            reduce(seg_reducer(item_code), segregator_fns, {}),
            {"total_consumption": total_fn(item_code)},
        )

    return fn
예제 #18
0
 def before_submit(self):
     if not self.period_to:
         self.period_to = get_datetime()
     self.set_report_details()
     get_default_collected = compose(
         lambda x: x.collected_amount if x else 0,
         excepts(StopIteration, first, lambda x: None),
         partial(filter, lambda x: cint(x.is_default) == 1),
     )
     self.closing_amount = self.opening_amount + get_default_collected(self.payments)
예제 #19
0
def get_item_rate(item_code, uom, price_list="Standard Selling"):
    get_price = compose(
        lambda x: x[1] if x else None,
        excepts(StopIteration, first, lambda __: None),
        get_item_price,
    )

    return get_price(
        {"price_list": price_list, "uom": uom, "transaction_date": today()}, item_code,
    )
예제 #20
0
def _count_activations(customers, intervals):
    def groupby_filter(c):
        def fn(p):
            return (p.get("start_date") <= c.get("loyalty_activation_date") <=
                    p.get("end_date"))

        return fn

    groupby_fn = compose(
        partial(get, "key", default=None),
        excepts(StopIteration, first, lambda __: {}),
        partial(flip, filter, intervals),
        groupby_filter,
    )

    customers_grouped = groupby(groupby_fn, customers)

    def seg_filter(x):
        return lambda c: c.get("branch") == x

    segregator_fns = map(
        lambda x: merge(
            x,
            {
                "seger":
                compose(
                    len,
                    partial(flip, filter,
                            get(x.get("key"), customers_grouped, [])),
                    seg_filter,
                )
            },
        ),
        intervals,
    )

    def seg_reducer(branch):
        def fn(a, p):
            key = get("key", p, None)
            seger = get("seger", p, lambda __: None)
            return merge(a, {key: seger(branch)})

        return fn

    total_fn = compose(len, partial(flip, filter, customers), seg_filter)

    def fn(x):
        branch = x.get("branch")
        return merge(
            x,
            reduce(seg_reducer(branch), segregator_fns, {}),
            {"total": total_fn(branch)},
        )

    return fn
예제 #21
0
def _get_payments(args):
    sales_payments = frappe.db.sql(
        """
            SELECT
                sip.mode_of_payment AS mode_of_payment,
                sip.type AS type,
                SUM(sip.base_amount) AS amount,
                sip.mop_currency AS mop_currency,
                SUM(sip.mop_amount) AS mop_amount
            FROM `tabSales Invoice Payment` AS sip
            LEFT JOIN `tabSales Invoice` AS si ON
                sip.parent = si.name
            WHERE sip.parenttype = 'Sales Invoice' AND {clauses}
            GROUP BY sip.mode_of_payment
        """.format(
            clauses=_get_clauses(args)
        ),
        values=args,
        as_dict=1,
    )
    default_mop = compose(
        excepts(StopIteration, first, lambda __: None),
        partial(pluck, "mode_of_payment"),
        frappe.get_all,
    )(
        "Sales Invoice Payment",
        fields=["mode_of_payment"],
        filters={
            "parenttype": "POS Profile",
            "parent": args.get("pos_profile"),
            "default": 1,
        },
    )
    collection_payments = frappe.db.sql(
        """
            SELECT
                mode_of_payment,
                SUM(paid_amount) AS amount
            FROM `tabPayment Entry`
            WHERE docstatus = 1
            AND company = %(company)s
            AND owner = %(user)s
            AND TIMESTAMP(posting_date, pb_posting_time) BETWEEN %(period_from)s AND %(period_to)s
            GROUP BY mode_of_payment
        """,
        values=args,
        as_dict=1,
    )

    return (
        _correct_mop_amounts(sales_payments, default_mop),
        _correct_mop_amounts(collection_payments, default_mop),
    )
예제 #22
0
    def remove_snapshot(
            self, snap: ModelSnapshot) -> Union[Exception, ModelSnapshot]:
        if not self._snapshots.get(snap.id, None):
            raise Exception("remove_snapshot",
                            f"Snapshot {snap.id} is not known")

        # remove container image
        # Todo: Fix issue with depending child images
        i = excepts(Exception, lambda image: self._d.images.get(image),
                    lambda _: -1)(snap.new_container_image_name)
        excepts(Exception,
                lambda image: self._d.images.remove(image.id, force=True),
                lambda _: -1)(i)

        # Remove the method file from filesystem
        rmtree(str(snap.storage_path))

        # Remove object from collection
        self._snapshots.pop(snap.id)

        return snap
예제 #23
0
    def advance_wf(name):
        doc = frappe.get_doc("Sales Order", name)

        workflow_state = compose(
            lambda x: x.get("state"),
            excepts(StopIteration, first, lambda: {}),
            partial(filter, lambda x: x.get("action") == "Complete"),
            frappe.model.workflow.get_transitions,
        )(doc, workflow)

        if (doc and doc.delivery_status == "Fully Delivered"
                and doc.get(workflow.workflow_state_field) == workflow_state):
            apply_workflow(doc, "Complete")
예제 #24
0
def get_number_from_contact(contact):
    get_number = compose(
        lambda x: x.get("phone"),
        excepts(StopIteration, first, lambda __: {}),
        frappe.db.sql,
    )
    return get_number(
        """
            SELECT phone FROM `tabContact Phone`
            WHERE parent = %(parent)s AND is_primary_mobile_no = 1
        """,
        values={"parent": contact},
        as_dict=1,
    )
예제 #25
0
    def pull_container_context(self, context: Union[ModelSnapshot, Result]) -> Union[ModelSnapshot, Result]:
        context = update_instance_status_rest(instance=context, new_status=f'Pull Model-Container from Registry')

        log_container_pull = "Started: {}\n".format(get_timestamp())

        # Catch the exception if the image is not found (image will be build later)
        # log_container_pull += excepts(NotFound,

        # For debugging ignore errors from the registry and continue
        # TODO: Apply error handling
        log_container_pull += excepts(Exception,
                                      lambda image: self._d_low.pull(image),
                                      lambda _: 'image not present')(context.container_image_name)

        return dataclasses.replace(context, container_pull_logs=log_container_pull)
예제 #26
0
def _get_data(file_url):
    get_header = excepts(StopIteration, first, lambda _: [])
    get_rows = compose(list, partial(drop, 1))
    if not file_url:
        return [], []

    file = frappe.get_doc("File", {"file_url": file_url})
    filename, file_extension = file.get_extension()
    if file_extension == ".xlsx":
        data = read_xlsx_file_from_attached_file(file_url=file_url)
        return get_header(data), get_rows(data)
    if file_extension == ".csv":
        data = read_csv_content(file.get_content())
        return get_header(data), get_rows(data)
    frappe.throw(frappe._("Unsupported File Format"))
예제 #27
0
def get_pos_data():
    from erpnext.accounts.doctype.sales_invoice.pos import get_pos_data

    get_price = compose(
        partial(get, "price_list_rate", default=0),
        excepts(StopIteration, first, lambda __: {}),
    )

    get_price_list_data = compose(partial(valmap, get_price), _get_default_item_prices)

    data = get_pos_data()

    return merge(
        data,
        {"price_list_data": get_price_list_data(data.get("doc").selling_price_list)},
    )
예제 #28
0
def on_update(doc, method):
    if doc.customer_primary_contact and not doc.mobile_no:
        get_number = compose(
            partial(get, "phone", default=None),
            excepts(StopIteration, first, lambda __: {}),
            frappe.db.sql,
        )
        mobile_no = get_number(
            """
                SELECT phone FROM `tabContact Phone`
                WHERE parent = %(parent)s AND is_primary_mobile_no = 1
                LIMIT 1
            """,
            values={"parent": doc.customer_primary_contact},
            as_dict=1,
        )
        frappe.db.set_value("Customer", doc.name, "mobile_no", mobile_no)
        doc.reload()
예제 #29
0
def get_amounts(doc):
    get_price_list_amount = compose(
        sum,
        partial(
            map,
            excepts(
                ZeroDivisionError,
                lambda x: x.amount / abs(x.amount) * max(
                    flt(x.price_list_rate) * abs(flt(x.qty)), abs(flt(x.amount)
                                                                  )),
                lambda __: 0,
            ),
        ),
    )
    total = get_price_list_amount(doc.items)
    # `doc.discount_amount` is negative
    discount_amount = doc.discount_amount + (doc.total - total)
    return {"total": total, "discount_amount": discount_amount}
예제 #30
0
def _set_cashback_balances(doc, cancel=False):
    get_cb_redeemed_amt = compose(
        excepts(StopIteration, first, lambda _: 0),
        lambda _=None: [
            x.amount for x in doc.payments if x.mode_of_payment == "Cashback"
        ],
    )

    redeemed_amt = get_cb_redeemed_amt()
    if redeemed_amt > 0:
        cashback_receipt = frappe.get_doc("Cashback Receipt", doc.os_cashback_receipt)
        if cancel:
            cashback_receipt.redemptions = [
                x for x in cashback_receipt.redemptions if x.reference != doc.name
            ]
        else:
            cashback_receipt.append(
                "redemptions", {"reference": doc.name, "amount": redeemed_amt}
            )
        cashback_receipt.save(ignore_permissions=True)