Exemple #1
0
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)
Exemple #2
0
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")
		}
Exemple #3
0
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
Exemple #4
0
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()
Exemple #5
0
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
Exemple #6
0
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)
Exemple #7
0
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." }