示例#1
0
def process_workflow_actions(doc, state):
	workflow = get_workflow_name(doc.get('doctype'))
	if not workflow: return

	if state == "on_trash":
		clear_workflow_actions(doc.get('doctype'), doc.get('name'))
		return

	if is_workflow_action_already_created(doc): return

	clear_old_workflow_actions(doc)
	update_completed_workflow_actions(doc)
	clear_doctype_notifications('Workflow Action')

	next_possible_transitions = get_next_possible_transitions(workflow, get_doc_workflow_state(doc), doc)

	if not next_possible_transitions: return

	user_data_map = get_users_next_action_data(next_possible_transitions, doc)

	if not user_data_map: return

	create_workflow_actions_for_users(user_data_map.keys(), doc)

	if send_email_alert(workflow):
		enqueue(send_workflow_action_email, queue='short', users_data=list(user_data_map.values()), doc=doc)
示例#2
0
def process_workflow_actions(doc, state):
	workflow = get_workflow_name(doc.get('doctype'))
	if not workflow: return

	if state == "on_trash":
		clear_workflow_actions(doc.get('doctype'), doc.get('name'))
		return

	if is_workflow_action_already_created(doc): return

	clear_old_workflow_actions(doc)
	update_completed_workflow_actions(doc)
	clear_doctype_notifications('Workflow Action')

	next_possible_transitions = get_next_possible_transitions(workflow, get_doc_workflow_state(doc))

	if not next_possible_transitions: return

	user_data_map = get_users_next_action_data(next_possible_transitions, doc)

	if not user_data_map: return

	create_workflow_actions_for_users(user_data_map.keys(), doc)

	if send_email_alert(workflow):
		enqueue(send_workflow_action_email, queue='short', users_data=list(user_data_map.values()), doc=doc)
def recall_purchase_receipt(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    if not workflow:
        return
    else:
        this_doc_workflow_state = get_doc_workflow_state(doc)
        if this_doc_workflow_state == "Reversed":
            quality_inspections = frappe.db.get_all(
                'Quality Inspection',
                filters={'reference_name': doc.get("name")},
                fields=['name'],
                as_list=False)

            q_documents =[frappe.get_doc("Quality Inspection", x.get("name"))\
             for x in quality_inspections if quality_inspections]

            submitted_qis = [x for x in q_documents if x.get("docstatus") == 1]
            if len(submitted_qis) > 0:
                frappe.throw(
                    "It seems that some inspection documents are already submitted.\
					To recall specific items please recall them from Quality Inspection doctype"
                )
                return
            else:
                list(
                    map(lambda x: x.delete(ignore_permissions=True),
                        q_documents))
                doc.db_set('workflow_state',
                           "Draft",
                           notify=True,
                           commit=True,
                           update_modified=True)
    return
def process_workflow_log(doc, state):
    if state == "before_save":
        workflow = get_workflow_name(doc.get('doctype'))
        if not workflow:
            this_doc_workflow_state = "Draft"
        else:
            if is_workflow_action_already_created(doc): return
            this_doc_workflow_state = get_doc_workflow_state(doc)
            if not this_doc_workflow_state:
                this_doc_workflow_state = "Draft"
        the_decision = "Actioned To: " + this_doc_workflow_state

    elif state == "before_submit":
        the_decision = "Document Approved!"

        #LET THE USER GIVE A MEMO FOR APPROVING DOCUMENT.
        comment_on_action(doc, state)
    elif state == "on_cancel":
        the_decision = "Document Cancelled/Revoked!"

        #LET THE USER GIVE A MEMO FOR CANCELLING DOCUMENT.
        comment_on_action(doc, state)
    #frappe.msgprint("Logging: " + state)
    log_actions(doc, the_decision)

    #================Generation of Quality Inspection========================
    #frappe.throw("doctype: " + doc.get('doctype') + ", state: " + state + ", workflow: " + get_doc_workflow_state(doc))
    if doc.get(
            'doctype'
    ) == "Purchase Receipt" and state == "before_save" and get_doc_workflow_state(
            doc) == "Pending Inspection":
        #function to insert into Quality Inspection
        #frappe.msgprint("Logging: " + get_doc_workflow_state(doc))
        create_quality_inspection(doc)
def update_invoice_state(doc, state):
    if doc.docstatus == 1:
        return
    workflow = get_workflow_name(doc.get('doctype'))
    if workflow:
        new_workflow_state = get_doc_workflow_state(doc)
        old_workflow_state = frappe.db.get_value(doc.get('doctype'),
                                                 doc.get('name'),
                                                 'workflow_state')
        if old_workflow_state == new_workflow_state:
            return
        else:
            #WORKFLOW STATE CHANGED. SO UPDATE INVOICE STATE AS WELL.
            invoice_docs = [
                frappe.get_doc("Purchase Invoice", x.get("invoice_number"))
                for x in doc.get("invoices")
            ]
            for d in invoice_docs:
                frappe.db.set_value(d.get("doctype"), d.get("name"),
                                    "workflow_state", new_workflow_state)
                d.notify_update()
            #invoice_to_update = frappe.get_doc(doc.get("reference_doctype"), doc.get("reference_name"))
            #invoice_to_update.flags.ignore_permissions = True
            #invoice_to_update.set("workflow_state", new_workflow_state)
            #invoice_to_update.save()
    return
def process_workflow_custom_actions(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    current_state = doc.status
    docname = doc.name
    full_user_name = frappe.db.get_value("User", frappe.session.user,
                                         "full_name")
    #frappe.msgprint("Current state "+str(current_state))
    #if current_state== "Cancelled" or current_state =="Terminated" or current_state =="Rejected":
    #frappe.publish_realtime(event='eval_js', message='alert("{0}")', user=frappe.session.user)
    # msgprint with server and client side action
    frappe.msgprint(
        msg='You ' + current_state + " document " + docname +
        " please click the appropriate reason. If you need to add a comment please scroll to the bottom of this document and tag specific users",
        title='Document ' + docname + ' ' + current_state,
        #raise_exception=FileNotFoundError
        primary_action={
            'label': _('Alert stakeholders for action'),
            'server_action': 'dotted.path.to.method',
            'args': {
                "comment_type": "Comment",
                "comment_email": full_user_name,
                "reference_doctype": "Material Request",
                "reference_name": docname,
                content: ""
            }
        })
示例#7
0
	def load_workflows(self):
		# get active workflow
		workflow_name = get_workflow_name(self.name)

		if workflow_name and frappe.db.exists("Workflow", workflow_name):
			workflow = frappe.get_doc("Workflow", workflow_name)
			frappe.response.docs.append(workflow)

			for d in workflow.get("workflow_document_states"):
				frappe.response.docs.append(frappe.get_doc("Workflow State", d.state))
示例#8
0
	def load_workflows(self):
		# get active workflow
		workflow_name = get_workflow_name(self.name)
		workflow_docs = []

		if workflow_name and frappe.db.exists("Workflow", workflow_name):
			workflow = frappe.get_doc("Workflow", workflow_name)
			workflow_docs.append(workflow)

			for d in workflow.get("states"):
				workflow_docs.append(frappe.get_doc("Workflow State", d.state))

		self.set("__workflow_docs", workflow_docs, as_value=True)
示例#9
0
def get_email_template(doc):
	"""Returns next_action_email_template
	for workflow state (if available) based on doc current workflow state
	"""
	workflow_name = get_workflow_name(doc.get('doctype'))
	doc_state = get_doc_workflow_state(doc)
	template_name = frappe.db.get_value('Workflow Document State', {
		'parent': workflow_name,
		'state': doc_state
	}, 'next_action_email_template')

	if not template_name: return
	return frappe.get_doc('Email Template', template_name)
def validate_invoices_in_po_v2(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    if workflow:
        new_workflow_state = get_doc_workflow_state(doc)
        old_workflow_state = frappe.db.get_value(doc.get('doctype'),
                                                 doc.get('name'),
                                                 'workflow_state')
        if old_workflow_state == new_workflow_state:
            return
        elif new_workflow_state in ["Pending Payment Voucher", "Credit Note"]:
            doc.set("to_be_sent_to_pv", True)
            frappe.msgprint("Document checking successful")
    return
示例#11
0
	def load_workflows(self):
		# get active workflow
		workflow_name = get_workflow_name(self.name)
		workflow_docs = []

		if workflow_name and frappe.db.exists("Workflow", workflow_name):
			workflow = frappe.get_doc("Workflow", workflow_name)
			workflow_docs.append(workflow)

			for d in workflow.get("states"):
				workflow_docs.append(frappe.get_doc("Workflow State", d.state))

		self.set("__workflow_docs", workflow_docs, as_value=True)
示例#12
0
def get_email_template(doc):
	"""Returns next_action_email_template
	for workflow state (if available) based on doc current workflow state
	"""
	workflow_name = get_workflow_name(doc.get('doctype'))
	doc_state = get_doc_workflow_state(doc)
	template_name = frappe.db.get_value('Workflow Document State', {
		'parent': workflow_name,
		'state': doc_state
	}, 'next_action_email_template')

	if not template_name: return
	return frappe.get_doc('Email Template', template_name)
def set_purchase_request_as_checked(doc):
    workflow = get_workflow_name(doc.get('doctype'))
    if workflow:
        new_workflow_state = get_doc_workflow_state(doc)
        old_workflow_state = frappe.db.get_value(doc.get('doctype'),
                                                 doc.get('name'),
                                                 'workflow_state')
        doc.set("checked", False)
        if old_workflow_state == new_workflow_state:
            return
        elif new_workflow_state not in ["Voteholder Checking"]:
            doc.set("checked", True)
            frappe.msgprint("Document checking successful")
    return
示例#14
0
def add_workflows(doclist):
    from frappe.model.workflow import get_workflow_name
    doctype = doclist[0].name

    # get active workflow
    workflow_name = get_workflow_name(doctype)

    if workflow_name and frappe.db.exists("Workflow", workflow_name):
        doclist += frappe.get_doclist("Workflow", workflow_name)

        # add workflow states (for icons and style)
        for state in map(lambda d: d.state,
                         doclist.get({"doctype": "Workflow Document State"})):
            doclist += frappe.get_doclist("Workflow State", state)
def execute():
	for doctype in ['Expense Claim', 'Leave Application']:

		active_workflow = get_workflow_name(doctype)
		if not active_workflow: continue

		workflow_states = frappe.get_all('Workflow Document State',
			filters=[['parent', '=', active_workflow]],
			fields=['*'])

		for state in workflow_states:
			if state.update_field: continue
			status_field = 'approval_status' if doctype=="Expense Claim" else 'status'
			frappe.set_value('Workflow Document State', state.name, 'update_field', status_field)
			frappe.set_value('Workflow Document State', state.name, 'update_value', state.state)
示例#16
0
def get_email_template(doc):
    """Returns next_action_email_template
	for workflow state (if available) based on doc current workflow state
	"""
    workflow_name = get_workflow_name(doc.get("doctype"))
    doc_state = get_doc_workflow_state(doc)
    template_name = frappe.db.get_value(
        "Workflow Document State",
        {
            "parent": workflow_name,
            "state": doc_state
        },
        "next_action_email_template",
    )

    if not template_name:
        return
    return frappe.get_doc("Email Template", template_name)
示例#17
0
def execute():
    for doctype in ['Expense Claim', 'Leave Application']:

        active_workflow = get_workflow_name(doctype)
        if not active_workflow: continue

        workflow_states = frappe.get_all(
            'Workflow Document State',
            filters=[['parent', '=', active_workflow]],
            fields=['*'])

        for state in workflow_states:
            if state.update_field: continue
            status_field = 'approval_status' if doctype == "Expense Claim" else 'status'
            frappe.set_value('Workflow Document State', state.name,
                             'update_field', status_field)
            frappe.set_value('Workflow Document State', state.name,
                             'update_value', state.state)
def execute():
    for doctype in ["Expense Claim", "Leave Application"]:

        active_workflow = get_workflow_name(doctype)
        if not active_workflow:
            continue

        workflow_states = frappe.get_all(
            "Workflow Document State",
            filters=[["parent", "=", active_workflow]],
            fields=["*"])

        for state in workflow_states:
            if state.update_field:
                continue
            status_field = "approval_status" if doctype == "Expense Claim" else "status"
            frappe.set_value("Workflow Document State", state.name,
                             "update_field", status_field)
            frappe.set_value("Workflow Document State", state.name,
                             "update_value", state.state)
示例#19
0
    def validate_workflow_conditions(doc):
        workflow = get_workflow_name(doc.doctype)
        if not workflow:
            return

        workflow_doc = frappe.get_doc("Workflow", workflow)
        current_state = doc.get(workflow_doc.workflow_state_field)
        roles = frappe.get_roles()

        transitions = []
        for transition in workflow_doc.transitions:
            if transition.next_state == current_state and transition.allowed in roles:
                if not is_transition_condition_satisfied(transition, doc):
                    continue
                transitions.append(transition.as_dict())

        if not transitions:
            frappe.throw(
                _("You are not allowed to update as per the conditions set in {} Workflow."
                  ).format(get_link_to_form("Workflow", workflow)),
                title=_("Insufficient Permissions"),
            )
def recall_quality_inspection_item(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    if not workflow:
        return
    else:
        this_doc_workflow_state = get_doc_workflow_state(doc)
        #frappe.msgprint(f"State: {this_doc_workflow_state}")
        if this_doc_workflow_state == "Reversed":
            pr_name = doc.get("reference_name")
            item_code = doc.get("item_code")
            purchase_receipt = frappe.get_doc("Purchase Receipt", pr_name)
            if purchase_receipt:
                item_row_id = frappe.db.sql(
                    f"""SELECT name FROM `tabPurchase Receipt Item`\
					WHERE parent ='{pr_name}' AND item_code ='{item_code}' """)[0][0]
                row_doc = frappe.get_doc("Purchase Receipt Item", item_row_id)
                #frappe.msgprint(f"rowID: {item_row_id} and row_doc")
                row_doc.flags.ignore_permissions = True
                row_doc.delete()

                #WE RE-UPDATE THE PERCENTAGE OF GOODS INSPECTED.
                update_percentage_inspected(doc, "Submitted")

                #RE-UPDATE THE PURCHASE RECEIPT. WE MAY NEED TO RELOOK WHETHER THE TOTALS ARE UPDATED APPROPRIATELY.
                purchase_receipt.flags.ignore_permissions = True
                purchase_receipt.run_method("set_missing_values")
                purchase_receipt.save()
                purchase_receipt.reload()
                purchase_receipt.notify_update()

                frappe.msgprint(
                    f"The item has been reversed and the related GRN: {pr_name} has been updated appropriately."
                )
                #doc.flags.ignore_permissions = True
                #doc.delete() #DELETE THIS INSPECTION DOCUMENT
                #frappe.set_route("List", "Quality Inspection",{"reference_name": pr_name})
        elif this_doc_workflow_state == "Cancelled":
            pass
def validate_invoices_in_po(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    if workflow:
        new_workflow_state = get_doc_workflow_state(doc)
        old_workflow_state = frappe.db.get_value(doc.get('doctype'),
                                                 doc.get('name'),
                                                 'workflow_state')
        if old_workflow_state == new_workflow_state:
            return
        elif new_workflow_state in ["Pending Payment Voucher", "Credit Note"]:

            purchase_receipt = doc.get("items")[0].purchase_receipt

            purchase_order = doc.get("items")[0].purchase_order

            if not purchase_receipt or not purchase_order:
                frappe.throw(
                    "Sorry. This invoice was not validly received with a system generated PO or GRN"
                )
            else:
                total_po_amount = frappe.db.get_value(
                    "Purchase Order", purchase_order, 'total') or 0.0
                '''invoices_list = frappe.db.get_all('Purchase Invoice Item', filters={
													'purchase_order': purchase_order

													},
													fields=['parent'],
													group_by='parent',
													as_list = False)'''

                sql_to_run = f"""SELECT DISTINCT parent FROM `tabPurchase Invoice Item`\
					WHERE purchase_order = '{purchase_order}'\
						 AND parent IN (SELECT name FROM `tabPurchase Invoice`\
							 WHERE workflow_state in ('Pending Payment Voucher', 'Credit Note'))"""
                invoices_list = frappe.db.sql(sql_to_run, as_dict=True)
                invoices_arr = [invoice.parent for invoice in invoices_list]

                #frappe.throw("Purchase Order: {0}".format(invoices_arr))

                total_accepted_amount = frappe.db.get_list(
                    'Purchase Invoice',
                    filters={
                        'name': ["IN", invoices_arr],
                        'is_return': False
                    },
                    #fields="`tabPurchase Invoice`.name, sum(`tabPurchase Invoice`.total) as total") or [0.0]
                    fields="sum(`tabPurchase Invoice`.total) as total") or [{
                        "total":
                        0.0
                    }]
                total_returns = frappe.db.get_list(
                    'Purchase Invoice',
                    filters={
                        'name': ['IN', invoices_arr],
                        'is_return': True
                    },
                    #fields='`tabPurchase Invoice`.name, sum(`tabPurchase Invoice`.total)*-1 as total') or [0.0]
                    fields='sum(`tabPurchase Invoice`.total)*-1 as total') or [
                        {
                            "total": 0.0
                        }
                    ]
                po = total_po_amount or 0.0
                ta = total_accepted_amount[0].total or 0.0
                tr = total_returns[0].total or 0.0

                #frappe.throw("Purchase Order: {0} Accepted Amount: {1} Returns: {2} for {3}".\
                #	format(total_po_amount,total_accepted_amount[0].total, total_returns, invoices_arr))
                this_invoice_total = doc.get(
                    "total") if doc.get("total") > 0 else doc.get("total") * -1
                if (po == (ta + tr + this_invoice_total)):
                    invoices_arr.append(doc.get("name"))
                    documents = [
                        frappe.get_doc("Purchase Invoice", x)
                        for x in invoices_arr
                    ]
                    documents_to_be_paid = [
                        x for x in documents if x.get("is_return") == False
                    ]
                    list(
                        map(lambda x: raise_payment_request(x, "Submitted"),
                            documents_to_be_paid))
                    #Raise all documents
                    #CLOSE the PO
                    from mtrh_dev.mtrh_dev.purchase_receipt_utils import close_purchase_order
                    po_doc = frappe.get_doc("Purchase Order", purchase_order)
                    close_purchase_order(po_doc)
    return
示例#22
0
文件: meta.py 项目: robulik/frappe
	def get_workflow(self):
		return get_workflow_name(self.name)
示例#23
0
def get_doc_workflow_state(doc):
	workflow_name = get_workflow_name(doc.get('doctype'))
	workflow_state_field = get_workflow_state_field(workflow_name)
	return doc.get(workflow_state_field)
示例#24
0
 def get_workflow(self):
     return get_workflow_name(self.name)
示例#25
0
	def workflow_manager(self):
		from frappe.model.workflow import get_workflow_name
		if not getattr(self, "__islocal", None) and frappe.db.exists(self.doctype, self.name):
			self.previous_doc = frappe.db.get_value(self.doctype, self.name, "*", as_dict=True)
		else:
			self.previous_doc = None
		self._current_action = self._action
		if get_workflow_name(self.doctype) is not None:
			if not self.is_new():
#				frappe.msgprint("1")
				transactions = frappe.db.sql("""
				SELECT state,next_state, thecondition ,idx ,`action` , allowed FROM `tabWorkflow Transition` WHERE `parent` = '{workflow_name}' and `action` = 'Approve'  order by `idx` asc
				""".format(workflow_name = get_workflow_name(self.doctype)))
				frappe.clear_cache(doctype=self.doctype)

				transactions = list(transactions)
				print "****************************\n"
				print "History"
				print self.get('workflow_history')
				print "****************************\n"

				print "****************************\n"
				print "Transactions"
				print transactions
				print "****************************\n"

				same_states = []

				transactions_index = 0
				for i in range(0,len(transactions)):

					if self.workflow_state == transactions[i][0]:
						same_states.append(i)
					transactions_index +=1

				print "****************************\n"
				print "Same States"
				print same_states , self.workflow_state
				print "****************************\n"

				if self._action == "submit" or self._action == "update_after_submit":
					current_transaction = transactions[len(transactions)-1]
				elif self._action == "cancel":
					child = self.append('workflow_history', {})
					child.user = frappe.session.user
					child.action = self._action
					if self.previous_doc and 'workflow_state' in self.previous_doc:
						child.previous_state = self.previous_doc['workflow_state']
					child.new_state = self.workflow_state
					return
				elif len(same_states) == 0:
					#Check if last status
					frappe.throw(_("Its not Allowed"))
				else:
#					frappe.msgprint("2")
					current_transaction = None
#					for i in range(0,len(same_states)):
					if len(same_states):
						i = 0
#						frappe.msgprint("3")
						length = len(self.get('workflow_history'))-1 if len(self.get('workflow_history')) > 0 else 0
						print self.get('workflow_history')
						prev_transaction = transactions[ same_states[i] - 1]
						print length
						last_elem = self.get('workflow_history')[length] #if length >= 0 else None
						print last_elem
						print "****************************\n"
						print "Last Transaction and last history"
						print prev_transaction[0] , last_elem.name
						print "****************************\n"

						#Action
						if last_elem is None or last_elem.new_state is None:
							current_transaction = transactions[0]
						#Update
						elif str(prev_transaction[0]) == str(last_elem.new_state):
							current_transaction = prev_transaction
						#Update
						elif last_elem.new_state == self.workflow_state:
							current_transaction = transactions[same_states[i]]
							self._current_action = "update"

				if current_transaction is None:
					frappe.throw("There's no workflow state, Refresh the page")

				condition = str(current_transaction[2]).split(":")
				if len(condition) == 1:
					check_func = condition[0]
					if not self.run_method(check_func):
						frappe.throw(_("You are not permitted."))

				if current_transaction[5] not in frappe.get_roles(frappe.session.user):
					frappe.throw(_("You are not Allowed ."))

#				print current_transaction[2]
				if current_transaction[2] is not None and self._current_action != "update":
					if len(condition) == 2:
						try:
							fcall = self.run_method(condition[0])
							if fcall:
								self.run_method("before_submit")
								self.db_set("workflow_state", condition[1])
								self.db_set("docstatus", "1") # submitted
								self.run_method("on_submit")
						except AttributeError as e:
							frappe.throw("Check workflow transaction condition :"+ str(e))
			else:
				pass

#			frappe.msgprint("before add to history")
			child = self.append('workflow_history', {})
			child.user = frappe.session.user
			child.action = self._current_action
			if self.previous_doc and 'workflow_state' in self.previous_doc:
				child.previous_state = self.previous_doc['workflow_state']
			child.new_state = self.workflow_state

			from frappe.utils import get_link_to_form , get_url , get_fullname

			#frappe.get_doc("Workflow Transition" , "" , "allowed")
			owner_employee = frappe.get_doc('Employee',{'name' : self.employee } )
			#if self.workflow_state =  or
			owner_user = frappe.db.get_value("User", owner_employee.user_id, "email")


			frappe.sendmail(
				recipients=(owner_user),
				sender= frappe.db.get_value("User", frappe.session.user, "email"),
				subject = "New Message from " + get_fullname(frappe.session.user),
				message = frappe.get_template("templates/emails/new_message.html").render({
					"from": get_fullname(frappe.session.user),
					"message": "Hello This is me",
					"link": get_link_to_form(self.doctype , self.name)
			}))
示例#26
0
def get_doc_workflow_state(doc):
	workflow_name = get_workflow_name(doc.get('doctype'))
	workflow_state_field = get_workflow_state_field(workflow_name)
	return doc.get(workflow_state_field)