Ejemplo n.º 1
0
def get_item_group_defaults(item, company):
	item = frappe.get_cached_doc("Item", item)
	item_group = frappe.get_cached_doc("Item Group", item.item_group)

	for d in item_group.item_group_defaults or []:
		if d.company == company:
			row = copy.deepcopy(d.as_dict())
			row.pop("name")
			return row

	return frappe._dict()
Ejemplo n.º 2
0
def get_pos_profile(company, pos_profile=None, user=None):
	if pos_profile: return frappe.get_cached_doc('POS Profile', pos_profile)

	if not user:
		user = frappe.session['user']

	condition = "pfu.user = %(user)s AND pfu.default=1"
	if user and company:
		condition = "pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1"

	pos_profile = frappe.db.sql("""SELECT pf.*
		FROM
			`tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu
		ON
				pf.name = pfu.parent
		WHERE
			{cond} AND pf.disabled = 0
	""".format(cond = condition), {
		'user': user,
		'company': company
	}, as_dict=1)

	if not pos_profile and company:
		pos_profile = frappe.db.sql("""SELECT pf.*
			FROM
				`tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu
			ON
					pf.name = pfu.parent
			WHERE
				pf.company = %(company)s AND pf.disabled = 0
		""", {
			'company': company
		}, as_dict=1)

	return pos_profile and pos_profile[0] or None
Ejemplo n.º 3
0
def calculate_service_end_date(args, item=None):
	args = process_args(args)
	if not item:
		item = frappe.get_cached_doc("Item", args.item_code)

	doctype = args.get("parenttype") or args.get("doctype")
	if doctype == "Sales Invoice":
		enable_deferred = "enable_deferred_revenue"
		no_of_months = "no_of_months"
		account = "deferred_revenue_account"
	else:
		enable_deferred = "enable_deferred_expense"
		no_of_months = "no_of_months_exp"
		account = "deferred_expense_account"

	service_start_date = args.service_start_date if args.service_start_date else args.transaction_date
	service_end_date = add_months(service_start_date, item.get(no_of_months))
	deferred_detail = {
		"service_start_date": service_start_date,
		"service_end_date": service_end_date
	}
	deferred_detail[enable_deferred] = item.get(enable_deferred)
	deferred_detail[account] = get_default_deferred_account(args, item, fieldname=account)

	return deferred_detail
Ejemplo n.º 4
0
def get_item_groups(pos_profile):
	item_groups = []
	pos_profile = frappe.get_cached_doc('POS Profile', pos_profile)

	if pos_profile.get('item_groups'):
		# Get items based on the item groups defined in the POS profile
		for data in pos_profile.get('item_groups'):
			item_groups.extend(["'%s'" % frappe.db.escape(d.name) for d in get_child_nodes('Item Group', data.item_group)])

	return list(set(item_groups))
Ejemplo n.º 5
0
def get_item_defaults(item_code, company):
	item = frappe.get_cached_doc('Item', item_code)

	out = item.as_dict()

	for d in item.item_defaults:
		if d.company == company:
			row = copy.deepcopy(d.as_dict())
			row.pop("name")
			out.update(row)
	return out
Ejemplo n.º 6
0
	def make_material_request(self):
		'''Create Material Requests grouped by Sales Order and Material Request Type'''
		material_request_list = []
		material_request_map = {}

		for item in self.mr_items:
			item_doc = frappe.get_cached_doc('Item', item.item_code)

			# key for Sales Order:Material Request Type
			key = '{}:{}'.format(item.sales_order, item_doc.default_material_request_type)
			schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))

			if not key in material_request_map:
				# make a new MR for the combination
				material_request_map[key] = frappe.new_doc("Material Request")
				material_request = material_request_map[key]
				material_request.update({
					"transaction_date": nowdate(),
					"status": "Draft",
					"company": self.company,
					"requested_by": frappe.session.user,
					'material_request_type': item_doc.default_material_request_type
				})
				material_request_list.append(material_request)
			else:
				material_request = material_request_map[key]

			# add item
			material_request.append("items", {
				"item_code": item.item_code,
				"qty": item.quantity,
				"schedule_date": schedule_date,
				"warehouse": item.warehouse,
				"sales_order": item.sales_order,
				'production_plan': self.name,
				'material_request_plan_item': item.name,
				"project": frappe.db.get_value("Sales Order", item.sales_order, "project") \
					if item.sales_order else None
			})

		for material_request in material_request_list:
			# submit
			material_request.flags.ignore_permissions = 1
			material_request.run_method("set_missing_values")
			material_request.submit()

		frappe.flags.mute_messages = False

		if material_request_list:
			material_request_list = ["""<a href="#Form/Material Request/{0}">{1}</a>""".format(m.name, m.name) \
				for m in material_request_list]
			msgprint(_("{0} created").format(comma_and(material_request_list)))
		else :
			msgprint(_("No material request created"))
Ejemplo n.º 7
0
	def link_address(self):
		"""Link address based on owner"""
		if not self.links and not self.is_your_company_address:
			contact_name = frappe.db.get_value("Contact", {"email_id": self.owner})
			if contact_name:
				contact = frappe.get_cached_doc('Contact', contact_name)
				for link in contact.links:
					self.append('links', dict(link_doctype=link.link_doctype, link_name=link.link_name))
				return True

		return False
Ejemplo n.º 8
0
	def validate_item(self):
		"""
			Validate whether serial no is required for this item
		"""
		item = frappe.get_cached_doc("Item", self.item_code)
		if item.has_serial_no!=1:
			frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code))

		self.item_group = item.item_group
		self.description = item.description
		self.item_name = item.item_name
		self.brand = item.brand
		self.warranty_period = item.warranty_period
Ejemplo n.º 9
0
def set_item_default(item_code, company, fieldname, value):
	item = frappe.get_cached_doc('Item', item_code)

	for d in item.item_defaults:
		if d.company == company:
			if not d.get(fieldname):
				frappe.db.set_value(d.doctype, d.name, fieldname, value)
			return

	# no row found, add a new row for the company
	d = item.append('item_defaults', {fieldname: value, "company": company})
	d.db_insert()
	item.clear_cache()
Ejemplo n.º 10
0
	def fetch_cta(self):
		if frappe.db.get_single_value("Blog Settings", "show_cta_in_blog", cache=True):
			blog_settings = frappe.get_cached_doc("Blog Settings")

			return {
				"show_cta_in_blog": 1,
				"title": blog_settings.title,
				"subtitle": blog_settings.subtitle,
				"cta_label": blog_settings.cta_label,
				"cta_url": blog_settings.cta_url,
			}

		return {}
Ejemplo n.º 11
0
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):

    item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
    item_group = filters.get('item_group')
    taxes = item_doc.taxes or []

    while item_group:
        item_group_doc = frappe.get_cached_doc('Item Group', item_group)
        taxes += item_group_doc.taxes or []
        item_group = item_group_doc.parent_item_group

    if not taxes:
        return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
    else:
        args = {
            'item_code': filters.get('item_code'),
            'posting_date': filters.get('valid_from'),
            'tax_category': filters.get('tax_category')
        }

        taxes = _get_item_tax_template(args, taxes, for_validate=True)
        return [(d, ) for d in set(taxes)]
Ejemplo n.º 12
0
def set_item_default(item_code, company, fieldname, value):
	item = frappe.get_cached_doc('Item', item_code)

	for d in item.item_defaults:
		if d.company == company:
			if not d.get(fieldname):
				frappe.db.set_value(d.doctype, d.name, fieldname, value)
			return

	# no row found, add a new row for the company
	d = item.append('item_defaults', {fieldname: value, "company": company})
	d.db_insert()
	item.clear_cache()
Ejemplo n.º 13
0
def get_party_open_orders(party):
    sales_invoices = [
        frappe.get_cached_doc("Sales Invoice", x.get("name"))
        for x in frappe.db.sql(
            """
                SELECT name FROM `tabSales Invoice`
                WHERE docstatus = 1 AND outstanding_amount > 0 AND customer = %(customer)s
            """,
            values={
                "customer":
                frappe.get_cached_value("Booking Party", party, "customer")
            },
            as_dict=1,
        )
    ]

    booking_orders = [
        frappe.get_cached_doc("Booking Order", name)
        for name in set([x.gg_booking_order for x in sales_invoices if x])
    ]

    return {"booking_orders": booking_orders, "sales_invoices": sales_invoices}
Ejemplo n.º 14
0
def get_item_groups(pos_profile):
    item_groups = []
    pos_profile = frappe.get_cached_doc('POS Profile', pos_profile)

    if pos_profile.get('item_groups'):
        # Get items based on the item groups defined in the POS profile
        for data in pos_profile.get('item_groups'):
            item_groups.extend([
                "%s" % frappe.db.escape(d.name)
                for d in get_child_nodes('Item Group', data.item_group)
            ])

    return list(set(item_groups))
Ejemplo n.º 15
0
def validate_ip_address(user):
    """check if IP Address is valid"""
    user = frappe.get_cached_doc("User", user)
    ip_list = user.get_restricted_ip_list()
    if not ip_list:
        return

    system_settings = frappe.get_cached_doc("System Settings")
    # check if bypass restrict ip is enabled for all users
    bypass_restrict_ip_check = system_settings.bypass_restrict_ip_check_if_2fa_enabled

    # check if two factor auth is enabled
    if system_settings.enable_two_factor_auth and not bypass_restrict_ip_check:
        # check if bypass restrict ip is enabled for login user
        bypass_restrict_ip_check = user.bypass_restrict_ip_check_if_2fa_enabled

    for ip in ip_list:
        if frappe.local.request_ip.startswith(ip) or bypass_restrict_ip_check:
            return

    frappe.throw(_("Access not allowed from this IP Address"),
                 frappe.AuthenticationError)
Ejemplo n.º 16
0
def sync_customer_with_leaflink(customer_name):
    """
	Sync a customer with leaflink by hitting Sync with Customer Button.
	"""
    leaflink_settings = frappe.get_cached_doc("LeafLink Settings")
    header = {
        leaflink_settings.get("api_key"): leaflink_settings.get("api_value")
    }

    #validate if leaflink is enabled
    if not leaflink_settings.get("enable_leaflink"):
        frappe.throw("Please enable LeafLink in LeafLink Settings.")

    #check if customer exists on leaflink
    try:
        customers_on_leaflink = requests.get(
            leaflink_settings.get("customers_url"),
            headers=header,
            params={
                "name": customer_name
            }).json()
    except Exception as e:
        frappe.throw(
            _("An Exception: {e} occured while trying to sync customer on LeafLink. Please try again."
              .format(e)))

    #create customer record on leaflink if it does not exist
    if not customers_on_leaflink.get("count"):

        #create new customer data
        new_customer = {
            "name": customer_name,
            "owner": leaflink_settings.get("leaflink_id")
        }

        #post request to create customer in leaflink
        try:
            post_response = requests.post(
                leaflink_settings.get("customers_url"),
                headers=header,
                data=new_customer)
            if post_response.status_code == 201:
                frappe.msgprint(
                    _("Customer successfully created on LeafLink!"))
        except Exception as e:
            frappe.throw(
                _("An Exception: {e} occured while trying to sync customer on LeafLink. Please try again."
                  .format(e)))

    else:
        frappe.msgprint(_("Customer already exists on LeafLink!"))
Ejemplo n.º 17
0
	def check_workstation_time(self, row):
		workstation_doc = frappe.get_cached_doc("Workstation", self.workstation)
		if (not workstation_doc.working_hours or
			cint(frappe.db.get_single_value("Manufacturing Settings", "allow_overtime"))):
			if get_datetime(row.planned_end_time) < get_datetime(row.planned_start_time):
				row.planned_end_time = add_to_date(row.planned_start_time, minutes=row.time_in_mins)
				row.remaining_time_in_mins = 0.0
			else:
				row.remaining_time_in_mins -= time_diff_in_minutes(row.planned_end_time, row.planned_start_time)

			self.update_time_logs(row)
			return

		start_date = getdate(row.planned_start_time)
		start_time = get_time(row.planned_start_time)

		new_start_date = workstation_doc.validate_workstation_holiday(start_date)

		if new_start_date != start_date:
			row.planned_start_time = datetime.datetime.combine(new_start_date, start_time)
			start_date = new_start_date

		total_idx = len(workstation_doc.working_hours)

		for i, time_slot in enumerate(workstation_doc.working_hours):
			workstation_start_time = datetime.datetime.combine(start_date, get_time(time_slot.start_time))
			workstation_end_time = datetime.datetime.combine(start_date, get_time(time_slot.end_time))

			if (get_datetime(row.planned_start_time) >= workstation_start_time and
				get_datetime(row.planned_start_time) <= workstation_end_time):
				time_in_mins = time_diff_in_minutes(workstation_end_time, row.planned_start_time)

				# If remaining time fit in workstation time logs else split hours as per workstation time
				if time_in_mins > row.remaining_time_in_mins:
					row.planned_end_time = add_to_date(row.planned_start_time,
						minutes=row.remaining_time_in_mins)
					row.remaining_time_in_mins = 0
				else:
					row.planned_end_time = add_to_date(row.planned_start_time, minutes=time_in_mins)
					row.remaining_time_in_mins -= time_in_mins

				self.update_time_logs(row)

				if total_idx != (i+1) and row.remaining_time_in_mins > 0:
					row.planned_start_time = datetime.datetime.combine(start_date,
						get_time(workstation_doc.working_hours[i+1].start_time))

		if row.remaining_time_in_mins > 0:
			start_date = add_days(start_date, 1)
			row.planned_start_time = datetime.datetime.combine(start_date,
				get_time(workstation_doc.working_hours[0].start_time))
Ejemplo n.º 18
0
def get_product_list_for_group(product_group=None,
                               start=0,
                               limit=10,
                               search=None):
    if product_group:
        item_group = frappe.get_cached_doc('Item Group', product_group)
        if item_group.is_group:
            # return child item groups if the type is of "Is Group"
            return get_child_groups_for_list_in_html(item_group, start, limit,
                                                     search)

    child_groups = ", ".join(
        [frappe.db.escape(i[0]) for i in get_child_groups(product_group)])

    # base query
    query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
			I.description, I.web_long_description as website_description, I.is_stock_item,
			case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock, I.website_warehouse,
			I.has_batch_no
		from `tabItem` I
		left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse
		where I.show_in_website = 1
			and I.disabled = 0
			and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)
			and (I.variant_of = '' or I.variant_of is null)
			and (I.item_group in ({child_groups})
			or I.name in (select parent from `tabWebsite Item Group` where item_group in ({child_groups})))
			""".format(child_groups=child_groups)
    # search term condition
    if search:
        query += """ and (I.web_long_description like %(search)s
				or I.item_name like %(search)s
				or I.name like %(search)s)"""
        search = "%" + cstr(search) + "%"

    query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (
        start, limit)

    data = frappe.db.sql(query, {
        "product_group": product_group,
        "search": search,
        "today": nowdate()
    },
                         as_dict=1)
    data = adjust_qty_for_expired_items(data)

    if cint(frappe.db.get_single_value("Shopping Cart Settings", "enabled")):
        for item in data:
            set_product_info_for_website(item)

    return data
Ejemplo n.º 19
0
def make_raw_material_request(items, company, sales_order, project=None):
	if not frappe.has_permission("Sales Order", "write"):
		frappe.throw(_("Not permitted"), frappe.PermissionError)

	if isinstance(items, string_types):
		items = frappe._dict(json.loads(items))

	for item in items.get('items'):
		item["include_exploded_items"] = items.get('include_exploded_items')
		item["ignore_existing_ordered_qty"] = items.get('ignore_existing_ordered_qty')
		item["include_raw_materials_from_sales_order"] = items.get('include_raw_materials_from_sales_order')

	items.update({
		'company': company,
		'sales_order': sales_order
	})

	raw_materials = get_items_for_material_requests(items)
	if not raw_materials:
		frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
		return

	material_request = frappe.new_doc('Material Request')
	material_request.update(dict(
		doctype = 'Material Request',
		transaction_date = nowdate(),
		company = company,
		requested_by = frappe.session.user,
		material_request_type = 'Purchase'
	))
	for item in raw_materials:
		item_doc = frappe.get_cached_doc('Item', item.get('item_code'))

		schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))
		row = material_request.append('items', {
			'item_code': item.get('item_code'),
			'qty': item.get('quantity'),
			'schedule_date': schedule_date,
			'warehouse': item.get('warehouse'),
			'sales_order': sales_order,
			'project': project
		})

		if not (strip_html(item.get("description")) and strip_html(item_doc.description)):
			row.description = item_doc.item_name or item.get('item_code')

	material_request.insert()
	material_request.flags.ignore_permissions = 1
	material_request.run_method("set_missing_values")
	material_request.submit()
	return material_request
Ejemplo n.º 20
0
def calc_delivery_charges(doc):
    if not doc.pos_profile:
        return

    old_doc = None
    calculate_taxes_and_totals = False
    if not doc.is_new():
        old_doc = doc.get_doc_before_save()
        if not doc.posa_delivery_charges and not old_doc.posa_delivery_charges:
            return
    else:
        if not doc.posa_delivery_charges:
            return
    if not doc.posa_delivery_charges:
        doc.posa_delivery_charges_rate = 0

    charges_doc = None
    if doc.posa_delivery_charges:
        charges_doc = frappe.get_cached_doc("Delivery Charges",
                                            doc.posa_delivery_charges)
        doc.posa_delivery_charges_rate = charges_doc.default_rate
        charges_profile = next((i for i in charges_doc.profiles
                                if i.pos_profile == doc.pos_profile), None)
        if charges_profile:
            doc.posa_delivery_charges_rate = charges_profile.rate

    if old_doc and old_doc.posa_delivery_charges:
        old_charges = next(
            (i for i in doc.taxes if i.charge_type == "Actual"
             and i.description == old_doc.posa_delivery_charges),
            None,
        )
        if old_charges:
            doc.taxes.remove(old_charges)
            calculate_taxes_and_totals = True

    if doc.posa_delivery_charges:
        doc.append(
            "taxes",
            {
                "charge_type": "Actual",
                "description": doc.posa_delivery_charges,
                "tax_amount": doc.posa_delivery_charges_rate,
                "cost_center": charges_doc.cost_center,
                "account_head": charges_doc.shipping_account,
            },
        )
        calculate_taxes_and_totals = True

    if calculate_taxes_and_totals:
        doc.calculate_taxes_and_totals()
Ejemplo n.º 21
0
    def validate_item_tax_template(self):
        for item in self.doc.get("items"):
            if item.item_code and item.get("item_tax_template"):
                item_doc = frappe.get_cached_doc("Item", item.item_code)
                args = {
                    "net_rate": item.net_rate or item.rate,
                    "tax_category": self.doc.get("tax_category"),
                    "posting_date": self.doc.get("posting_date"),
                    "bill_date": self.doc.get("bill_date"),
                    "transaction_date": self.doc.get("transaction_date"),
                    "company": self.doc.get("company"),
                }

                item_group = item_doc.item_group
                item_group_taxes = []

                while item_group:
                    item_group_doc = frappe.get_cached_doc(
                        "Item Group", item_group)
                    item_group_taxes += item_group_doc.taxes or []
                    item_group = item_group_doc.parent_item_group

                item_taxes = item_doc.taxes or []

                if not item_group_taxes and (not item_taxes):
                    # No validation if no taxes in item or item group
                    continue

                taxes = _get_item_tax_template(args,
                                               item_taxes + item_group_taxes,
                                               for_validate=True)

                if taxes:
                    if item.item_tax_template not in taxes:
                        item.item_tax_template = taxes[0]
                        frappe.msgprint(
                            _("Row {0}: Item Tax template updated as per validity and rate applied"
                              ).format(item.idx, frappe.bold(item.item_code)))
Ejemplo n.º 22
0
    def set_document_detail_in_return_document(doctype):
        """Map each row of the original document in the return document."""
        mapped = []
        return_document_map = defaultdict(list)
        detail_field = "purchase_receipt_item" if doctype == "Purchase Receipt" else "dn_detail"

        child_doc = frappe.scrub("{0} Item".format(doctype))
        frappe.reload_doc("stock", "doctype", child_doc)

        return_document_map = make_return_document_map(doctype,
                                                       return_document_map)

        count = 0

        #iterate through original documents and its return documents
        for docname in return_document_map:
            doc_items = frappe.get_cached_doc(doctype, docname).get("items")
            for return_doc in return_document_map[docname]:
                return_doc_items = frappe.get_cached_doc(
                    doctype, return_doc).get("items")

                #iterate through return document items and original document items for mapping
                for return_item in return_doc_items:
                    for doc_item in doc_items:
                        if row_is_mappable(doc_item, return_item,
                                           detail_field) and doc_item.get(
                                               'name') not in mapped:
                            map_rows(doc_item, return_item, detail_field,
                                     doctype)
                            mapped.append(doc_item.get('name'))
                            break
                        else:
                            continue

            # commit after every 100 sql updates
            count += 1
            if count % 100 == 0:
                frappe.db.commit()
Ejemplo n.º 23
0
def repost_entries():
    riv_entries = get_repost_item_valuation_entries()

    for row in riv_entries:
        doc = frappe.get_cached_doc('Repost Item Valuation', row.name)
        repost(doc)

    riv_entries = get_repost_item_valuation_entries()
    if riv_entries:
        return

    for d in frappe.get_all('Company',
                            filters={'enable_perpetual_inventory': 1}):
        check_if_stock_and_account_balance_synced(today(), d.name)
Ejemplo n.º 24
0
def create_regular_web_item(item_code=None, item_args=None, web_args=None):
	"Create Regular Item and Website Item."
	item_code = item_code or "Test Mobile Phone"
	item = make_item(item_code, properties=item_args)

	if not frappe.db.exists("Website Item", {"item_code": item_code}):
		web_item = make_website_item(item, save=False)
		if web_args:
			web_item.update(web_args)
		web_item.save()
	else:
		web_item = frappe.get_cached_doc("Website Item", {"item_code": item_code})

	return web_item
Ejemplo n.º 25
0
	def check_stock_frozen_date(self):
		stock_settings = frappe.get_cached_doc('Stock Settings')

		if stock_settings.stock_frozen_upto:
			if (getdate(self.posting_date) <= getdate(stock_settings.stock_frozen_upto)
				and stock_settings.stock_auth_role not in frappe.get_roles()):
				frappe.throw(_("Stock transactions before {0} are frozen")
					.format(formatdate(stock_settings.stock_frozen_upto)), StockFreezeError)

		stock_frozen_upto_days = cint(stock_settings.stock_frozen_upto_days)
		if stock_frozen_upto_days:
			older_than_x_days_ago = (add_days(getdate(self.posting_date), stock_frozen_upto_days) <= date.today())
			if older_than_x_days_ago and stock_settings.stock_auth_role not in frappe.get_roles():
				frappe.throw(_("Not allowed to update stock transactions older than {0}").format(stock_frozen_upto_days), StockFreezeError)
Ejemplo n.º 26
0
def get_context(context):
    context.body_class = "product-page"

    settings = frappe.get_cached_doc("E Commerce Settings")
    context.categories_enabled = settings.enable_field_filters

    if context.categories_enabled:
        categories = [row.fieldname for row in settings.filter_fields]
        context.tabs = get_tabs(categories)

    if settings.slideshow:
        context.slideshow = get_slideshow(settings.slideshow)

    context.no_cache = 1
Ejemplo n.º 27
0
def get_stages_from_project_type(project_type):
    if not project_type:
        frappe.throw(_("Project Type not provided"))

    doc = frappe.get_cached_doc("Project Type", project_type)
    stages = [{
        "project_timeline": d.project_timeline,
        "project_stage": d.project_stage
    } for d in doc.stages]
    stages = sorted(stages,
                    key=lambda d: (not frappe.get_cached_value(
                        "Project Timeline", d.get('project_timeline'),
                        "single_stage"), d.get('project_timeline')))
    return stages
Ejemplo n.º 28
0
def get_doc_content(content_type):
    if content_type == "about":
        about = frappe.get_cached_doc("About Us Settings")
        return {"content": about.company_introduction}

    if content_type in ["privacy", "terms"]:
        settings = frappe.get_single("Ahong eCommerce Settings")
        if settings.get(content_type):
            content = frappe.get_cached_value(
                "Terms and Conditions", settings.get(content_type), "terms"
            )
            return {"content": content}

    return {"content": None}
Ejemplo n.º 29
0
def get_item_tax_info(company, tax_category, item_codes):
	out = {}
	if isinstance(item_codes, string_types):
		item_codes = json.loads(item_codes)

	for item_code in item_codes:
		if not item_code or item_code in out:
			continue
		out[item_code] = {}
		item = frappe.get_cached_doc("Item", item_code)
		get_item_tax_template({"tax_category": tax_category}, item, out[item_code])
		out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)

	return out
Ejemplo n.º 30
0
	def get_pages_to_extend(self):
		pages = frappe.get_all("Workspace", filters={
			"extends": self.page_name,
			'restrict_to_domain': ['in', frappe.get_active_domains()],
			'for_user': '',
			'module': ['in', self.allowed_modules]
		})

		pages = [frappe.get_cached_doc("Workspace", page['name']) for page in pages]

		for page in pages:
			self.extended_links = self.extended_links + page.get_link_groups()
			self.extended_charts = self.extended_charts + page.charts
			self.extended_shortcuts = self.extended_shortcuts + page.shortcuts
Ejemplo n.º 31
0
	def set_roles_and_modules_based_on_user_type(self):
		user_type_doc = frappe.get_cached_doc("User Type", self.user_type)
		if user_type_doc.role:
			self.roles = []

			# Check whether User has linked with the 'Apply User Permission On' doctype or not
			if user_linked_with_permission_on_doctype(user_type_doc, self.name):
				self.append("roles", {"role": user_type_doc.role})

				frappe.msgprint(
					_("Role has been set as per the user type {0}").format(self.user_type), alert=True
				)

		user_type_doc.update_modules_in_user(self)
Ejemplo n.º 32
0
def get_bin(item_code, warehouse):
	bin = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse})
	if not bin:
		bin_obj = frappe.get_doc({
			"doctype": "Bin",
			"item_code": item_code,
			"warehouse": warehouse,
		})
		bin_obj.flags.ignore_permissions = 1
		bin_obj.insert()
	else:
		bin_obj = frappe.get_cached_doc('Bin', bin)
	bin_obj.flags.ignore_permissions = True
	return bin_obj
Ejemplo n.º 33
0
def poll_and_process_new_messages():
    """
    Scheduled method that looks for any pending messages to be processed. Currently only 5 messages are picked up for
    processing to ensure too many messages are not picked up. Messages are sorted by time they were received at, to
    ensure processing in same order as receipt. However, this order is not guaranteed and handler implementations
    should not assume this order.
    :return: None
    """
    logger = get_module_logger()
    config = frappe.get_cached_doc("Spine Consumer Config", "Spine Consumer Config").as_dict()
    # Number of messages to pick up on one call.
    window_size = config.get("msg_window_size")
    if not window_size:
        window_size = 5
    # messages = frappe.get_all("Message Log", filters={"status": "Pending", "direction": "Received"},
    #                           fields=["*"], order_by="received_at", limit_page_length=window_size)
    messages = frappe.db.sql('''
        SELECT
            *
        from
            `tabMessage Log`
        where
            status = 'Pending'
            and direction = 'Received'
        order by
            received_at
        limit
            %(window_size)s
        for update
    ''', {
        'window_size': window_size,
    }, as_dict=True)
    if messages:
        logger.debug("Found {} unprocessed messages".format(len(messages)))
        updated_msgs = []

        for msg in messages:
            # Update status for all messages picked up for processing. This will ensure that later scheduled tasks will
            # not pick up same messages.
            updated_msgs.append(update_message_status(msg, "Processing"))
        # Commit updates
        frappe.db.commit()

        if updated_msgs and len(updated_msgs) > 0:
            for msg in updated_msgs:
                process_message_from_spine(msg)
        else:
            logger.info("SpineConsumer: No messages found for processing.")
    else:
        logger.info("SpineConsumer: No messages found for processing.")
Ejemplo n.º 34
0
    def save_file(self,
                  content=None,
                  decode=False,
                  ignore_existing_file_check=False):
        file_exists = False
        self.content = content
        if decode:
            if isinstance(content, text_type):
                self.content = content.encode("utf-8")

            if b"," in self.content:
                self.content = self.content.split(b",")[1]
            self.content = base64.b64decode(self.content)

        if not self.is_private:
            self.is_private = 0
        self.file_size = self.check_max_file_size()
        self.content_hash = get_content_hash(self.content)
        self.content_type = mimetypes.guess_type(self.file_name)[0]

        duplicate_file = None

        # check if a file exists with the same content hash and is also in the same folder (public or private)
        if not ignore_existing_file_check:
            duplicate_file = frappe.get_value("File", {
                "content_hash": self.content_hash,
                "is_private": self.is_private
            }, ["file_url", "name"],
                                              as_dict=True)

        if duplicate_file:
            file_doc = frappe.get_cached_doc('File', duplicate_file.name)
            if file_doc.exists_on_disk():
                self.file_url = duplicate_file.file_url
                file_exists = True

        if os.path.exists(
                encode(
                    get_files_path(self.file_name,
                                   is_private=self.is_private))):
            self.file_name = get_file_name(self.file_name,
                                           self.content_hash[-6:])

        if not file_exists:
            call_hook_method("before_write_file", file_size=self.file_size)
            write_file_method = get_hook_method('write_file')
            if write_file_method:
                return write_file_method(self)
            return self.save_file_on_filesystem()
Ejemplo n.º 35
0
def send_email_to_leads_or_contacts():
    email_campaigns = frappe.get_all(
        "Email Campaign",
        filters={
            "status": ("not in", ["Unsubscribed", "Completed", "Scheduled"])
        })
    for camp in email_campaigns:
        email_campaign = frappe.get_doc("Email Campaign", camp.name)
        campaign = frappe.get_cached_doc("Campaign",
                                         email_campaign.campaign_name)
        for entry in campaign.get("campaign_schedules"):
            scheduled_date = add_days(email_campaign.get("start_date"),
                                      entry.get("send_after_days"))
            if scheduled_date == getdate(today()):
                send_mail(entry, email_campaign)
Ejemplo n.º 36
0
def get_materials_from_supplier(purchase_order, po_details):
	if isinstance(po_details, str):
		po_details = json.loads(po_details)

	doc = frappe.get_cached_doc("Purchase Order", purchase_order)
	doc.initialized_fields()
	doc.purchase_orders = [doc.name]
	doc.get_available_materials()

	if not doc.available_materials:
		frappe.throw(
			_("Materials are already received against the purchase order {0}").format(purchase_order)
		)

	return make_return_stock_entry_for_subcontract(doc.available_materials, doc, po_details)
Ejemplo n.º 37
0
    def link_address(self):
        """Link address based on owner"""
        if not self.links and not self.is_your_company_address:
            contact_name = frappe.db.get_value("Contact",
                                               {"email_id": self.owner})
            if contact_name:
                contact = frappe.get_cached_doc('Contact', contact_name)
                for link in contact.links:
                    self.append(
                        'links',
                        dict(link_doctype=link.link_doctype,
                             link_name=link.link_name))
                return True

        return False
Ejemplo n.º 38
0
def send_email_to_leads_or_contacts():
    email_campaigns = frappe.get_all(
        "Email Campaign",
        filters={
            'status': ('not in', ['Unsubscribed', 'Completed', 'Scheduled'])
        })
    for camp in email_campaigns:
        email_campaign = frappe.get_doc("Email Campaign", camp.name)
        campaign = frappe.get_cached_doc("Campaign",
                                         email_campaign.campaign_name)
        for entry in campaign.get("campaign_schedules"):
            scheduled_date = add_days(email_campaign.get('start_date'),
                                      entry.get('send_after_days'))
            if scheduled_date == getdate(today()):
                send_mail(entry, email_campaign)
Ejemplo n.º 39
0
def get_territory_from_address(address):
	"""Tries to match city, state and country of address to existing territory"""
	if not address:
		return

	if isinstance(address, string_types):
		address = frappe.get_cached_doc("Address", address)

	territory = None
	for fieldname in ("city", "state", "country"):
		if address.get(fieldname):
			territory = frappe.db.get_value("Territory", address.get(fieldname))
			if territory:
				break

	return territory
Ejemplo n.º 40
0
def make_raw_material_request(items, company, sales_order, project=None):
	if not frappe.has_permission("Sales Order", "write"):
		frappe.throw(_("Not permitted"), frappe.PermissionError)

	if isinstance(items, string_types):
		items = frappe._dict(json.loads(items))

	for item in items.get('items'):
		item["include_exploded_items"] = items.get('include_exploded_items')
		item["ignore_existing_ordered_qty"] = items.get('ignore_existing_ordered_qty')
		item["include_raw_materials_from_sales_order"] = items.get('include_raw_materials_from_sales_order')

	raw_materials = get_items_for_material_requests(items, sales_order, company)
	if not raw_materials:
		frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
		return

	material_request = frappe.new_doc('Material Request')
	material_request.update(dict(
		doctype = 'Material Request',
		transaction_date = nowdate(),
		company = company,
		requested_by = frappe.session.user,
		material_request_type = 'Purchase'
	))
	for item in raw_materials:
		item_doc = frappe.get_cached_doc('Item', item.get('item_code'))
		schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))
		material_request.append('items', {
		'item_code': item.get('item_code'),
		'qty': item.get('quantity'),
		'schedule_date': schedule_date,
		'warehouse': item.get('warehouse'),
		'sales_order': sales_order,
		'project': project
		})
	material_request.insert()
	material_request.flags.ignore_permissions = 1
	material_request.run_method("set_missing_values")
	material_request.submit()
	return material_request
Ejemplo n.º 41
0
def get_product_list_for_group(product_group=None, start=0, limit=10, search=None):
	if product_group:
		item_group = frappe.get_cached_doc('Item Group', product_group)
		if item_group.is_group:
			# return child item groups if the type is of "Is Group"
			return get_child_groups_for_list_in_html(item_group, start, limit, search)

	child_groups = ", ".join(['"' + frappe.db.escape(i[0]) + '"' for i in get_child_groups(product_group)])

	# base query
	query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
			I.description, I.web_long_description as website_description, I.is_stock_item,
			case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock, I.website_warehouse,
			I.has_batch_no
		from `tabItem` I
		left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse
		where I.show_in_website = 1
			and I.disabled = 0
			and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)
			and (I.variant_of = '' or I.variant_of is null)
			and (I.item_group in ({child_groups})
			or I.name in (select parent from `tabWebsite Item Group` where item_group in ({child_groups})))
			""".format(child_groups=child_groups)
	# search term condition
	if search:
		query += """ and (I.web_long_description like %(search)s
				or I.item_name like %(search)s
				or I.name like %(search)s)"""
		search = "%" + cstr(search) + "%"

	query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (start, limit)

	data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
	data = adjust_qty_for_expired_items(data)

	for item in data:
		set_product_info_for_website(item)

	return [get_item_for_list_in_html(r) for r in data]
Ejemplo n.º 42
0
def get_pos_profile(company, pos_profile=None, user=None):
	if pos_profile:
		return frappe.get_cached_doc('POS Profile', pos_profile)

	if not user:
		user = frappe.session['user']

	pos_profile = frappe.db.sql("""SELECT pf.*
		FROM
			`tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu
		ON
				pf.name = pfu.parent
		WHERE
			(
				(pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1)
				OR (pfu.user = %(user)s AND pfu.default=1)
				OR (ifnull(pfu.user, '') = '' AND pf.company = %(company)s)
			) AND pf.disabled = 0
	""", {
		'user': user,
		'company': company
	}, as_dict=1)

	return pos_profile and pos_profile[0] or None
Ejemplo n.º 43
0
def get_item_details(args):
	"""
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": ""
			"set_warehouse": ""
		}
	"""
	args = process_args(args)
	item = frappe.get_cached_doc("Item", args.item_code)
	validate_item_details(args, item)

	out = get_basic_details(args, item)

	get_party_item_code(args, item, out)

	set_valuation_rate(out, args)

	update_party_blanket_order(args, out)

	get_price_list_rate(args, item, out)

	if args.customer and cint(args.is_pos):
		out.update(get_pos_profile_item_details(args.company, args))

	if out.get("warehouse"):
		out.update(get_bin_details(args.item_code, out.warehouse))

	# update args with out, if key or value not exists
	for key, value in iteritems(out):
		if args.get(key) is None:
			args[key] = value

	out.update(get_pricing_rule_for_item(args))

	update_stock(args, out)

	if args.transaction_date and item.lead_time_days:
		out.schedule_date = out.lead_time_date = add_days(args.transaction_date,
			item.lead_time_days)

	if args.get("is_subcontracted") == "Yes":
		out.bom = args.get('bom') or get_default_bom(args.item_code)

	get_gross_profit(out)
	if args.doctype == 'Material Request':
		out.rate = args.rate or out.price_list_rate
		out.amount = flt(args.qty * out.rate)

	return out