def reset_shipping(): customer = get_current_customer() awc_session = get_awc_session() awc = awc_session.get("cart") quotation = None if not awc: awc = clear_awc_session() if customer: cart_info = get_user_quotation(awc_session) quotation = cart_info.get('doc') if len(quotation.items) == 0: apply_cart_settings(quotation=quotation) quotation.flags.ignore_permissions=True quotation_dirty=False if quotation: quotation_dirty = sync_awc_and_quotation(awc_session, quotation, save_quotation=False) else: call_awc_sync_hook(awc_session, quotation) if "shipping_method" in awc_session: del awc_session["shipping_method"] if "shipping_address" in awc_session: del awc_session["shipping_address"] if "shipping_rates_list" in awc_session: awc_session["shipping_rates_list"] = [] save_and_commit_quotation(quotation, quotation_dirty, awc_session, commit=True)
def get_price(item_code, price_list=None, qty=1, find_price_list=False, customer=None): if not customer: customer = get_current_customer() if not price_list and find_price_list and is_logged_in(): quotation = _get_cart_quotation() price_list = quotation.get("selling_price_list") if price_list: cart_settings = get_shopping_cart_settings() template_item_code = frappe.db.get_value("Item", item_code, "variant_of") price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"], filters={"price_list": price_list, "item_code": item_code}) if not price and template_item_code: price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"], filters={"price_list": price_list, "item_code": template_item_code}) if price: rule_query = { "item_code": item_code, "qty": qty, "transaction_type": "selling", "price_list": price_list, "customer_group": customer.customer_group, "company": cart_settings.company, "conversion_rate": 1, "for_shopping_cart": True } pricing_rule = get_pricing_rule_for_item(frappe._dict(rule_query)) price_list_rate = price[0].price_list_rate if pricing_rule: if pricing_rule.pricing_rule_for == "Discount Percentage" and pricing_rule.discount_percentage: price[0].price_list_rate = flt(price[0].price_list_rate * (1.0 - (pricing_rule.discount_percentage / 100.0))) if pricing_rule.pricing_rule_for == "Price": price[0].price_list_rate = pricing_rule.price_list_rate return { "base_price_rate": price_list_rate, "currency": price[0].get("currency"), "rate": price[0].get("price_list_rate")} return { "base_price_rate": frappe.db.get_value("Item", item_code, "standard_rate"), "currency": "", #TODO: get default currency, don't remember from where atm "rate": frappe.db.get_value("Item", item_code, "standard_rate") }
def get_quick_cache(key, awc_session=None, customer=None, prefix=None): if not prefix: prefix = "awc-sku" if not awc_session: awc_session = get_awc_session() if not customer: from compat.customer import get_current_customer customer = get_current_customer() customer_lbl = "None" if customer: customer_lbl = customer.customer_group cache_prefix = prefix #.format(customer_lbl) cache_data = get_cache("{}-{}".format(customer_lbl, key), session=awc_session, prefix=cache_prefix) return cache_data, cache_prefix, awc_session
def reset_shipping(): customer = get_current_customer() awc_session = get_awc_session() awc = awc_session.get("cart") quotation = None if not awc: awc = clear_awc_session() if customer: cart_info = get_user_quotation(awc_session) quotation = cart_info.get('doc') if len(quotation.items) == 0: apply_cart_settings(quotation=quotation) quotation.flags.ignore_permissions=True if quotation: sync_awc_and_quotation(awc_session, quotation) if "shipping_method" in awc_session: del awc_session["shipping_method"] if "shipping_address" in awc_session: del awc_session["shipping_address"] if "shipping_rates_list" in awc_session: awc_session["shipping_rates_list"] = [] if quotation: update_cart_settings(quotation, awc_session) quotation.flags.ignore_permissions = True quotation.save() collect_totals(quotation, awc, awc_session) else: collect_totals(None, awc, awc_session) set_awc_session(awc_session) frappe.db.commit()
def create_transaction(gateway_service, billing_address, shipping_address, instructions=""): if billing_address and isinstance(billing_address, basestring): billing_address = json.loads(billing_address) if shipping_address and isinstance(shipping_address, basestring): shipping_address = json.loads(shipping_address) result = { "success": False, "error": "Unknown Internal Error" } # fetch customer customer = get_current_customer() # fetch awc awc_session = get_awc_session() awc = awc_session.get("cart") # fetch current quotation cart_info = get_user_quotation(awc_session) quotation = cart_info.get('doc') quotation_is_dirty = False # assign instructions to quotation if instructions: quotation.instructions = instructions quotation_is_dirty = False # make sure quotation email is contact person if we are a power user quotation_is_dirty = sync_awc_and_quotation(awc_session, quotation, quotation_is_dirty, save_quotation=False) if awc_session.get("selected_customer") and quotation.contact_person: email = frappe.get_value("Contact", quotation.contact_person, "email_id") else: email = quotation.contact_email save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) # create awc transaction to process payments first # sales order and friends will be generated from this data data = { "doctype": "AWC Transaction", "title": "Web Order", "description": "Online Web Order", "status": "Initiated", "payer_name": quotation.contact_person, "payer_email": email, "amount": quotation.grand_total, "currency": quotation.currency, "session": json.dumps(awc), "order_id": quotation.name, "gateway_service": gateway_service, "shipping_address": shipping_address.get("shipping_address"), "billing_address": billing_address.get("billing_address") } if shipping_address.get("ship_method"): # retrieve quoted chargesfee rates = awc_session.get("shipping_rates") #data["shipping_method"] = shipping_address.get("ship_method") #if rates: # data["shipping_fee"] = rates.get(data["shipping_method"], {}).get("fee") data.update({ "billing_%s" % key: value for key, value in billing_address.iteritems() }) data.update({ "shipping_%s" % key: value for key, value in shipping_address.iteritems() }) transaction = frappe.get_doc(data) transaction.flags.ignore_permissions = 1 transaction.save() # check AWCTransaction.on_payment_authorized implementation which is # where this transaction continues when payment processing kicks in # fetch only payment request info result["data"] = { key: transaction.get(key) for key in \ ('amount', 'currency', 'order_id', 'title', \ 'description', 'payer_email', 'payer_name')} result["data"]["reference_doctype"] = "AWC Transaction" result["data"]["reference_docname"] = transaction.name result["success"] = True del result["error"] return result
def cart(data=None, action=None): if data and isinstance(data, basestring): try: data = json.loads(data) except ex: log("REMOTE ADDR: {0}".format(frappe.request.get("remote_addr", "NO REMOTE ADDRESS?"))) log("URL: {0}".format(frappe.request.get("url", "NO URL DATA"))) log("Action: {0}".format(action)) log("Data: {0}".format(data)) log(traceback.format_exc()) data = None # make sure we can handle bulk actions if not isinstance(data, list): data = [data] customer = get_current_customer() quotation = None awc_session = get_awc_session() quotation_is_dirty = False if customer: cart_info = get_user_quotation(awc_session) quotation = cart_info.get('doc') if len(quotation.items) == 0: apply_cart_settings(quotation=quotation) awc = awc_session.get("cart") if not awc: awc = clear_awc_session() if quotation: quotation_is_dirty = sync_awc_and_quotation(awc_session, quotation) else: call_awc_sync_hook(awc_session, quotation) if not action: save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return { "data": awc, "success": True} elif action == "calculate_shipping": rate_name = data[0].get("name") address = data[0].get("address") if address: address_name = address.get("shipping_address") if not address_name: new_address = frappe.new_doc("Address") new_address.update({ "address_title": data[0].get("address").get("title"), "address_type": data[0].get("address").get("address_type", "Shipping"), "address_contact": data[0].get("address").get("address_contact", ""), "address_line1": data[0].get("address").get("address_1"), "address_line2": data[0].get("address").get("address_2"), "city": data[0].get("address").get("city"), "state": data[0].get("address").get("state"), "country": data[0].get("address").get("country"), "phone": data[0].get("address").get("phone"), "email_id": frappe.session.user, "pincode": data[0].get("address").get("pincode"), "links": [{"link_doctype" : "Customer", "link_name" : quotation.customer}] }) new_address.flags.ignore_permissions= True new_address.save() address_name = new_address.name address["shipping_address"] = address_name if quotation: quotation.shipping_address_name = address_name awc_session["last_shipping_address"] = address_name # check and update use_customer_fedex_account field in quotation if quotation: quotation.use_customer_fedex_account = 1 if data[0].get( "address", {}).get("use_customer_fedex_account") else 0 quotation.flags.ignore_permissions = True quotation.save() frappe.db.commit() result = calculate_shipping(rate_name, address, awc_session, quotation, save=True) return result elif action == "updateItem": # for now only qty field is updatable # key in awc fields and values are erpnext fields for quotation item valid_update_fields = {"qty": "qty"} remove_items = [] removed_ids = [] for item in data: awc_item = next((i for i in awc["items"] if i.get("id") == item.get("id")), None) if awc_item: quotation_item = None if quotation: quotation_item = next((q for q in quotation.get("items", []) if q.name == awc_item.get("id")), None) for awc_key, erp_key in valid_update_fields.iteritems(): if awc_key in item: awc_item[awc_key] = item.get(awc_key) if awc_key == "qty": awc_item["total"] = awc_item["unit"] * awc_item["qty"] if quotation_item: quotation_item.set(erp_key, item.get(awc_key)) #if erp_key == "qty": #quotation_item.amount = flt(quotation_item.rate) * quotation_item.qty if awc_item.get('options', {}).get('group'): # find all subgroup items and update qty accordingly for sub_item in [i for i in awc["items"] if i.get('options', {}).get('group') == awc_item.get('options', {}).get('group')]: sub_item["qty"] = awc_item["qty"] if quotation: sub_quotation_item = next((q for q in quotation.get("items", []) if q.name == sub_item.get("id")), None) if sub_quotation_item: sub_quotation_item.set("qty", sub_item.get("qty")) #sub_quotation_item.amount = flt(sub_quotation_item.rate) * sub_quotation_item.qty sub_item["total"] = sub_item["unit"] * sub_item["qty"] if awc_item.get("qty") == 0: remove_items.append(awc_item) # remove all 0 qty items if len(remove_items) > 0: success, removed_ids, awc_items = remove_from_cart(remove_items, awc["items"]) if success: awc["items"] = awc_items if quotation: # remove item and related grouped items from quote quotation_items = [ itm for itm in quotation.get("items", []) \ if itm.name not in removed_ids ] quotation.set("items", quotation_items) shipping_info = calculate_shipping(None, None, awc_session, quotation, save=0, force=True) if quotation: quotation_is_dirty=True save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": True, "removed": removed_ids, "shipping_rates": shipping_info.get("shipping_rates") }, awc_session, quotation) elif action == "addToCart": to_remove = [] for item in data: # need basic data validation here if not item.get("sku"): return { "success": False, "message": "Invalid Data" } if not item.get("qty"): return { "success": False, "message": "Invalid Data" } product = get_product_by_sku(item.get("sku"), quotation=quotation).get("data") if item.get("replaces"): to_remove.append(item.get("replaces")) del item["replaces"] if item.get("options", {}).get("custom", {}).get("rate", None) != None: item["total"] = flt(item["options"]["custom"]["rate"]) * item.get("qty") item["unit"] = flt(item["options"]["custom"]["rate"]) else: item["total"] = flt(product.get("price") * item.get("qty")) item["unit"] = flt(product.get("price")) if quotation: item_data = { "doctype": "Quotation Item", "item_code": item.get("sku"), "item_name": product.get("name"), "description": item.get("options", {}).get("description", product.get("name")), "qty": cint(item.get("qty")), "warehouse": product.get("warehouse") } update_quotation_item_awc_fields(item_data, item) quotation_item = quotation.append("items", item_data) # TODO: ( >_<) shitty way of setting rate due to rate reset # Please fix when not utterly pissed off if item.get("options", {}).get("custom", {}).get("rate", None) != None: quotation_item.set("ignore_pricing_rule", 1) set_quotation_item_rate(quotation_item, item["options"]["custom"]["rate"], product) item_data['total'] = item["options"]["custom"]["rate"] * cint(item.get("qty")) else: quotation_item.set("ignore_pricing_rule", 0) set_quotation_item_rate(quotation_item, product.get("price"), product) item_data['total'] = product.get("price") * cint(item.get("qty")) quotation_item.save() item["old_id"] = item["id"] item["id"] = quotation_item.name awc["items"].append(item) removed_ids = [] if len(to_remove) > 0: remove_success, removed_ids, awc_items = remove_from_cart([{ "id": x} for x in to_remove], awc["items"]) if remove_success: awc["items"] = awc_items if quotation: if len(removed_ids) > 0: # remove item and related grouped items from quote quotation_items = [ itm for itm in quotation.get("items", []) \ if itm.name not in removed_ids ] quotation.set("items", quotation_items) update_cart_settings(quotation, awc_session) quotation_is_dirty = True save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": True, "removed": removed_ids }, awc_session, quotation) elif action == "removeFromCart": success = False removed_ids = [] success, removed_ids, awc_items = remove_from_cart(data, awc["items"]) if success: awc["items"] = awc_items if quotation: # remove item and related grouped items from quote quotation_items = [ itm for itm in quotation.get("items", []) \ if itm.name not in removed_ids ] quotation.set("items", quotation_items) quotation_is_dirty = True save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": True, "removed": removed_ids }, awc_session, quotation) return session_response({ "success": False, "message": "Item not found." }, awc_session, quotation) elif action == "applyCoupon" and len(data) > 0: coupon = data[0] success = False msg = "Coupon not found" if quotation: # validate coupon msg = is_coupon_valid(coupon) is_valid = frappe.response.get("is_coupon_valid") if is_valid: discount, msg = calculate_coupon_discount(quotation.items, coupon)[0:2] if discount == 0: is_valid = False success = False msg = "Coupon is invalid for the current cart." else: quotation.coupon_code = coupon quotation_is_dirty = True success = True else: # must be logged in to use cupon success = False msg = "Please Login to Apply Coupon" if success: save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": True }, awc_session, quotation) save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": False, "message": _(msg) }, awc_session, quotation) elif action == "removeCoupon": if quotation: quotation.discount_amount = 0 quotation.coupon_code = None quotation_is_dirty = True save_and_commit_quotation(quotation, quotation_is_dirty, awc_session, commit=True) return session_response({ "success": True }, awc_session, quotation) else: return session_response({ "success": False, "message": "Unknown Command." }, awc_session, quotation)
def cart(data=None, action=None): if data and isinstance(data, basestring): data = json.loads(data) # make sure we can handle bulk actions if not isinstance(data, list): data = [data] customer = get_current_customer() quotation = None awc_session = get_awc_session() if customer: cart_info = get_user_quotation(awc_session) quotation = cart_info.get('doc') if len(quotation.items) == 0: apply_cart_settings(quotation=quotation) quotation.flags.ignore_permissions=True quotation.save() awc = awc_session.get("cart") if not awc: awc = clear_awc_session() if quotation: sync_awc_and_quotation(awc_session, quotation) #log(pretty_json(awc)) if not action: return { "data": awc, "success": True} elif action == "calculate_shipping": rate_name = data[0].get("name") address = data[0].get("address") if address: address_name = address.get("shipping_address") if not address_name: new_address = frappe.new_doc("Address") new_address.update({ "address_recipient": data[0].get("address").get("recipient"), "address_type": data[0].get("address").get("address_type", "Shipping"), "customer": quotation.customer, "address_line1": data[0].get("address").get("address_1"), "address_line2": data[0].get("address").get("address_2"), "address_line3": data[0].get("address").get("address_3"), "city": data[0].get("address").get("city"), "state": data[0].get("address").get("state"), "country": data[0].get("address").get("country"), "phone": data[0].get("address").get("phone"), "email_id": frappe.session.user, "pincode": data[0].get("address").get("pincode") }) new_address.flags.ignore_permissions= True new_address.save() address_name = new_address.name quotation.shipping_address_name = address_name quotation.save() return calculate_shipping(rate_name, address, awc_session, quotation) elif action == "updateItem": # for now only qty field is updatable # key in awc fields and values are erpnext fields for quotation item valid_update_fields = {"qty": "qty"} remove_items = [] removed_ids = [] for item in data: awc_item = next((i for i in awc["items"] if i.get("id") == item.get("id")), None) if awc_item: quotation_item = None if quotation: quotation_item = next((q for q in quotation.get("items", []) if q.name == awc_item.get("id")), None) for awc_key, erp_key in valid_update_fields.iteritems(): if awc_key in item: awc_item[awc_key] = item.get(awc_key) if awc_key == "qty": awc_item["total"] = awc_item["unit"] * awc_item["qty"] if quotation_item: quotation_item.set(erp_key, item.get(awc_key)) #if erp_key == "qty": #quotation_item.amount = flt(quotation_item.rate) * quotation_item.qty if awc_item.get('options', {}).get('group'): # find all subgroup items and update qty accordingly for sub_item in [i for i in awc["items"] if i.get('options', {}).get('group') == awc_item.get('options', {}).get('group')]: sub_item["qty"] = awc_item["qty"] if quotation: sub_quotation_item = next((q for q in quotation.get("items", []) if q.name == sub_item.get("id")), None) if sub_quotation_item: sub_quotation_item.set("qty", sub_item.get("qty")) #sub_quotation_item.amount = flt(sub_quotation_item.rate) * sub_quotation_item.qty sub_item["total"] = sub_item["unit"] * sub_item["qty"] if awc_item.get("qty") == 0: remove_items.append(awc_item) # remove all 0 qty items if len(remove_items) > 0: success, removed_ids, awc_items = remove_from_cart(remove_items, awc["items"]) if success: awc["items"] = awc_items if quotation: # remove item and related grouped items from quote quotation_items = [ itm for itm in quotation.get("items", []) \ if itm.name not in removed_ids ] quotation.set("items", quotation_items) shipping_info = calculate_shipping(None, None, awc_session, quotation, save=0) if quotation: update_cart_settings(quotation, awc_session) quotation.flags.ignore_permissions = True quotation.save() frappe.db.commit() collect_totals(quotation, awc, awc_session) else: collect_totals(None, awc, awc_session) set_awc_session(awc_session) return { "success": True, "data": awc["items"], "removed": removed_ids, "totals": awc.get("totals"), "shipping_rates": shipping_info.get("shipping_rates") } elif action == "addToCart": for item in data: # need basic data validation here if not item.get("sku"): return { "success": False, "message": "Invalid Data" } if not item.get("qty"): return { "success": False, "message": "Invalid Data" } product = get_product_by_sku(item.get("sku")).get("data") if item.get("options", {}).get("custom", {}).get("rate", None) != None: item["total"] = flt(item["options"]["custom"]["rate"]) * item.get("qty") item["unit"] = flt(item["options"]["custom"]["rate"]) else: item["total"] = flt(product.get("price") * item.get("qty")) item["unit"] = flt(product.get("price")) if quotation: item_data = { "doctype": "Quotation Item", "item_code": item.get("sku"), "item_name": product.get("name"), "description": item.get("options", {}).get("description", product.get("name")), "qty": cint(item.get("qty")), "warehouse": product.get("warehouse") } update_quotation_item_awc_fields(item_data, item) quotation_item = quotation.append("items", item_data) # TODO: ( >_<) shitty way of setting rate due to rate reset # Please fix when not utterly pissed off if item.get("options", {}).get("custom", {}).get("rate", None) != None: quotation_item.set("ignore_pricing_rule", 1) set_quotation_item_rate(quotation_item, item["options"]["custom"]["rate"], product) item_data['total'] = item["options"]["custom"]["rate"] * cint(item.get("qty")) else: quotation_item.set("ignore_pricing_rule", 0) set_quotation_item_rate(quotation_item, product.get("price"), product) item_data['total'] = product.get("price") * cint(item.get("qty")) #quotation_item.discount_percentage = 100 - flt(item["options"]["custom"]["rate"] * 100) / flt(product.get("price")) #quotation_item.rate = flt(item["options"]["custom"]["rate"]) #quotation_item.price_list_rate = flt(product.get("price")) #quotation_item.amount = flt(item["options"]["custom"]["rate"]) #quotation_item.base_price_list_rate = flt(product.get("price")) #quotation_item.base_rate = flt(product.get("price")) quotation_item.save() item["old_id"] = item["id"] item["id"] = quotation_item.name awc["items"].append(item) if quotation: update_cart_settings(quotation, awc_session) quotation.flags.ignore_permissions = True quotation.save() #log("Quotation after add to cart: \n{0}", pretty_json(quotation.as_dict())) frappe.db.commit() collect_totals(quotation, awc, awc_session) #log("Quotation after collecting totals: \n{0}", pretty_json(quotation.as_dict())) else: collect_totals(None, awc, awc_session) set_awc_session(awc_session) #log("Awc session after add to cart: \n{0}", pretty_json(awc_session)) return { "success": True, "data": data, "totals": awc.get("totals") } elif action == "removeFromCart": success = False removed_ids = [] success, removed_ids, awc_items = remove_from_cart(data, awc["items"]) if success: awc["items"] = awc_items if quotation: # remove item and related grouped items from quote quotation_items = [ itm for itm in quotation.get("items", []) \ if itm.name not in removed_ids ] quotation.set("items", quotation_items) update_cart_settings(quotation, awc_session) quotation.flags.ignore_permissions = True quotation.save() frappe.db.commit() collect_totals(quotation, awc, awc_session) else: collect_totals(None, awc, awc_session) set_awc_session(awc_session) return { "success": True, "totals": awc.get("totals"), "data": awc["items"], "removed": removed_ids } return { "success": False, "message": "Item not found."} else: return { "success": False, "message": "Unknown Command." }