def check_nextdoc_docstatus(self): # Checks Delivery Note submit_dn = frappe.db.sql_list( """select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""", self.name) if submit_dn: frappe.throw( _("Delivery Notes {0} must be cancelled before cancelling this Sales Order" ).format(comma_and(submit_dn))) # Checks Sales Invoice submit_rv = frappe.db.sql_list( """select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""", self.name) if submit_rv: frappe.throw( _("Sales Invoice {0} must be cancelled before cancelling this Sales Order" ).format(comma_and(submit_rv))) # Checks Job Order added on 09-09-2017 #submit_jo = frappe.db.sql_list("""select t1.name # from `tabJob Order` t1,`tabJob Order Item` t2 # where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""", # self.name) #if submit_jo: # frappe.throw(_("Job Order {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_rv))) #check maintenance schedule submit_ms = frappe.db.sql_list( """select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.sales_order = %s and t1.docstatus = 1""", self.name) if submit_ms: frappe.throw( _("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order" ).format(comma_and(submit_ms))) # check maintenance visit submit_mv = frappe.db.sql_list( """select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""", self.name) if submit_mv: frappe.throw( _("Maintenance Visit {0} must be cancelled before cancelling this Sales Order" ).format(comma_and(submit_mv))) # check production order pro_order = frappe.db.sql_list( """select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.name) if pro_order: frappe.throw( _("Production Order {0} must be cancelled before cancelling this Sales Order" ).format(comma_and(pro_order)))
def make_program_enrollment(self): if not self.follow_up: program_enrollment = frappe.new_doc("Program Enrollment") program_enrollment.update({ "student": self.student, "student_name": self.student_name, "academic_year": self.academic_year, "academic_term": self.academic_term, "program": self.program, "percent": self.percent, "company": self.company, "program_application": self.name, "price": self.program_price, "application": "Program" }) for d in self.sta_courses: program_enrollment.append("courses", {"course": d.course}) program_enrollment.save() program_enrollment_msg = frappe.get_doc("Program Enrollment", {"program_application": self.name}) link = ["""<a href=desk#Form/Program%20Enrollment/{0}>{0}</a>""".format(program_enrollment_msg.name)] frappe.msgprint(_("Program Enrollment Created - {0} As a Draft").format(comma_and(link))) else: for d in self.follow_up: if not d.sales_person: frappe.throw("Please Enter Sales Person In Follow UP") else: user = frappe.get_doc("User", {"name": frappe.session.user}) if not user.sales_person and frappe.session.user != "Administrator" : frappe.throw(_("User {0} Missing Field Sales Person").format(user.name)) else: self.mpe = 1 if self.mpe: program_enrollment = frappe.new_doc("Program Enrollment") program_enrollment.student = self.student program_enrollment.student_name = self.student_name program_enrollment.academic_year = self.academic_year program_enrollment.academic_term = self.academic_term program_enrollment.follow_up = self.follow_up program_enrollment.program = self.program program_enrollment.percent = self.percent program_enrollment.company = self.company program_enrollment.program_application = self.name program_enrollment.price = self.program_price program_enrollment.application = "Program" for d in self.sta_courses: program_enrollment.append("courses", {"course": d.course}) program_enrollment.save() program_enrollment_msg = frappe.get_doc("Program Enrollment", {"program_application": self.name}) link = ["""<a href=desk#Form/Program%20Enrollment/{0}>{0}</a>""".format( program_enrollment_msg.name)] frappe.msgprint(_("Program Enrollment Created - {0} As Draft").format(comma_and(link)))
def check_nextdoc_docstatus(self): # Checks Delivery Note submit_dn = frappe.db.sql_list(""" select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""", self.name) if submit_dn: frappe.throw(_("Delivery Notes {0} must be cancelled before cancelling this Sales Order") .format(comma_and(submit_dn))) # Checks Sales Invoice submit_rv = frappe.db.sql_list("""select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""", self.name) if submit_rv: frappe.throw(_("Sales Invoice {0} must be cancelled before cancelling this Sales Order") .format(comma_and(submit_rv))) #check maintenance schedule submit_ms = frappe.db.sql_list(""" select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.sales_order = %s and t1.docstatus = 1""", self.name) if submit_ms: frappe.throw(_("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order") .format(comma_and(submit_ms))) # check maintenance visit submit_mv = frappe.db.sql_list(""" select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""",self.name) if submit_mv: frappe.throw(_("Maintenance Visit {0} must be cancelled before cancelling this Sales Order") .format(comma_and(submit_mv))) # check work order pro_order = frappe.db.sql_list(""" select name from `tabWork Order` where sales_order = %s and docstatus = 1""", self.name) if pro_order: frappe.throw(_("Work Order {0} must be cancelled before cancelling this Sales Order") .format(comma_and(pro_order)))
def allocate_leave(self): self.validate_values() leave_allocated_for = [] employees = self.get_employees() if not employees: frappe.throw(_("No employee found")) for d in self.get_employees(): try: la = frappe.new_doc('Leave Allocation') la.set("__islocal", 1) la.employee = cstr(d[0]) la.employee_name = frappe.db.get_value('Employee', cstr(d[0]), 'employee_name') la.leave_type = self.leave_type la.from_date = self.from_date la.to_date = self.to_date la.carry_forward = cint(self.carry_forward) la.new_leaves_allocated = flt(self.no_of_days) la.docstatus = 1 la.save() leave_allocated_for.append(d[0]) except: pass if leave_allocated_for: msgprint( _("Leaves Allocated Successfully for {0}").format( comma_and(leave_allocated_for)))
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"))
def raise_production_orders(self): """It will raise production order (Draft) for all distinct FG items""" self.validate_data() from erpnext.utilities.transaction_base import validate_uom_is_integer validate_uom_is_integer(self, "stock_uom", "planned_qty") items = self.get_production_items() pro_list = [] frappe.flags.mute_messages = True for key in items: production_order = self.create_production_order(items[key]) if production_order: pro_list.append(production_order) frappe.flags.mute_messages = False if pro_list: pro_list = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \ (p, p) for p in pro_list] msgprint(_("{0} created").format(comma_and(pro_list))) else: msgprint(_("No Production Orders created"))
def allocate_shift(self): self.validate_values() def add_shift(employee): shift_allocated_for = [] try: sh = frappe.new_doc('Work Shift') sh.employee = cstr(employee) sh.employee_name = frappe.db.get_value('Employee', cstr(employee), 'employee_name') sh.holiday_list = self.holiday_list #'Work Shift Details' #sh.from_date = self.from_date #sh.to_date = self.to_date sh.save() shift_allocated_for.append(employee) except: pass if self.all_employee: employees = self.get_employees() if not employees: frappe.throw(_("No employee found")) for d in self.get_employees(): add_shift(d[0]) elif self.employee: add_shift(self.employee) if shift_allocated_for: msgprint( _("Shift Allocated Successfully for {0}").format( comma_and(shift_allocated_for)))
def validate_exchange_rates_exist(self): """check if exchange rates exist for all Price List currencies (to company's currency)""" company_currency = frappe.db.get_value("Company", self.company, "default_currency") if not company_currency: msgprint(_("Please specify currency in Company") + ": " + self.company, raise_exception=ShoppingCartSetupError) price_list_currency_map = frappe.db.get_values("Price List", [self.price_list], "currency") # check if all price lists have a currency for price_list, currency in price_list_currency_map.items(): if not currency: frappe.throw(_("Currency is required for Price List {0}").format(price_list)) expected_to_exist = [currency + "-" + company_currency for currency in price_list_currency_map.values() if currency != company_currency] if expected_to_exist: exists = frappe.db.sql_list("""select name from `tabCurrency Exchange` where name in (%s)""" % (", ".join(["%s"]*len(expected_to_exist)),), tuple(expected_to_exist)) missing = list(set(expected_to_exist).difference(exists)) if missing: msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)), raise_exception=ShoppingCartSetupError)
def on_update(self): frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock) if cint(self.auto_accounting_for_stock): if cint( frappe.db.get_value("Stock Settings", None, "allow_negative_stock")): frappe.throw( _("Negative stock is not allowed in case of Perpetual Inventory, please disable it from Stock Settings" )) # set default perpetual account in company for company in frappe.db.sql("select name from tabCompany"): frappe.get_doc("Company", company[0]).save() # Create account head for warehouses warehouse_list = frappe.db.sql( "select name, company from tabWarehouse", as_dict=1) warehouse_with_no_company = [ d.name for d in warehouse_list if not d.company ] if warehouse_with_no_company: frappe.throw( _("Company is missing in warehouses {0}").format( comma_and(warehouse_with_no_company))) for wh in warehouse_list: wh_doc = frappe.get_doc("Warehouse", wh.name) wh_doc.save()
def validate_exchange_rates_exist(self): """check if exchange rates exist for all Price List currencies (to company's currency)""" company_currency = frappe.db.get_value("Company", self.company, "default_currency") if not company_currency: msgprint(_("Please specify currency in Company") + ": " + self.company, raise_exception=ShoppingCartSetupError) price_list_currency_map = frappe.db.get_values("Price List", [d.selling_price_list for d in self.get("price_lists")], "currency") # check if all price lists have a currency for price_list, currency in price_list_currency_map.items(): if not currency: frappe.throw(_("Currency is required for Price List {0}").format(price_list)) expected_to_exist = [currency + "-" + company_currency for currency in price_list_currency_map.values() if currency != company_currency] if expected_to_exist: exists = frappe.db.sql_list("""select name from `tabCurrency Exchange` where name in (%s)""" % (", ".join(["%s"]*len(expected_to_exist)),), tuple(expected_to_exist)) missing = list(set(expected_to_exist).difference(exists)) if missing: msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)), raise_exception=ShoppingCartSetupError)
def on_update(self): frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock) if cint(self.auto_accounting_for_stock): # set default perpetual account in company for company in frappe.db.sql("select name from tabCompany"): company = frappe.get_doc("Company", company[0]) company.flags.ignore_permissions = True company.save() # Create account head for warehouses warehouse_list = frappe.db.sql( """select name, company from tabWarehouse where disabled=0""", as_dict=1) warehouse_with_no_company = [ d.name for d in warehouse_list if not d.company ] if warehouse_with_no_company: frappe.throw( _("Company is missing in warehouses {0}").format( comma_and(warehouse_with_no_company))) for wh in warehouse_list: wh_doc = frappe.get_doc("Warehouse", wh.name) wh_doc.flags.ignore_permissions = True wh_doc.save()
def make_sales_order(self): if self.has_placement_test and not frappe.db.exists("Sales Order", {"program_application": self.name}): si = frappe.new_doc("Sales Order") si.update({ "customer": self.student_name, "transaction_date": frappe.utils.nowdate(), "company": self.company, "program_application": self.name, "currency": self.currency }) si.append("items", { "item_code": self.placement_test, "qty": 1, "rate": self.placement_test_amount, "uom": "nos", "conversion_factor": 1, "item_name": self.placement_test, "description": self.placement_test, "delivery_date": frappe.utils.nowdate(), }) si.append("payment_schedule", { "due_date": frappe.utils.nowdate(), "payment_amount": self.placement_test_amount, "description": self.placement_test, }) si.save() si.submit() sales_order = frappe.get_last_doc("Sales Order") link = ["""<a href=desk#Form/Sales%20Order/{0}>{0}</a>""".format(sales_order.name)] frappe.msgprint(_("Sales Order Created - {0} For Placement Test").format(comma_and(link)))
def raise_production_orders(self): """It will raise production order (Draft) for all distinct FG items""" self.validate_data() from erpnext.utilities.transaction_base import validate_uom_is_integer validate_uom_is_integer(self, "stock_uom", "planned_qty") items = self.get_production_items() pro_list = [] frappe.flags.mute_messages = True for key in items: production_order = self.create_production_order(items[key]) if production_order: pro_list.append(production_order) frappe.flags.mute_messages = False if pro_list: pro_list = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \ (p, p) for p in pro_list] msgprint(_("{0} created").format(comma_and(pro_list))) else : msgprint(_("No Production Orders created"))
def validate_search_index_fields(self): if not self.search_index_fields: return fields = self.search_index_fields.replace(' ', '') fields = unique(fields.strip(',').split( ',')) # Remove extra ',' and remove duplicates # All fields should be indexable allowed_indexable_fields = get_indexable_web_fields() if not (set(fields).issubset(allowed_indexable_fields)): invalid_fields = list( set(fields).difference(allowed_indexable_fields)) num_invalid_fields = len(invalid_fields) invalid_fields = comma_and(invalid_fields) if num_invalid_fields > 1: frappe.throw( _("{0} are not valid options for Search Index Field."). format(frappe.bold(invalid_fields))) else: frappe.throw( _("{0} is not a valid option for Search Index Field."). format(frappe.bold(invalid_fields))) self.search_index_fields = ','.join(fields)
def validate_recurring_additional_salary_overlap(self): if self.is_recurring: additional_salaries = frappe.db.sql(""" SELECT name FROM `tabAdditional Salary` WHERE employee=%s AND name <> %s AND docstatus=1 AND is_recurring=1 AND salary_component = %s AND to_date >= %s AND from_date <= %s""", (self.employee, self.name, self.salary_component, self.from_date, self.to_date), as_dict = 1) additional_salaries = [salary.name for salary in additional_salaries] if additional_salaries and len(additional_salaries): frappe.throw(_("Additional Salary: {0} already exist for Salary Component: {1} for period {2} and {3}").format( bold(comma_and(additional_salaries)), bold(self.salary_component), bold(formatdate(self.from_date)), bold(formatdate(self.to_date) )))
def check_email_id_is_unique(self): if self.email_id: names = frappe.db.sql_list("""select name from `tabJob Applicant` where email_id=%s and name!=%s""", (self.email_id, self.name)) if names: frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(names)), frappe.DuplicateEntryError)
def make_fee_records(self): from erpnext.schools.api import get_fee_components fee_list = [] for d in self.fees: fee_components = get_fee_components(d.fee_structure) if fee_components: fees = frappe.new_doc("Fees") fees.update({ "student": self.student, "academic_year": self.academic_year, "academic_term": d.academic_term, "fee_structure": d.fee_structure, "program": self.program, "due_date": d.due_date, "student_name": self.student_name, "program_enrollment": self.name, "components": fee_components }) fees.save() fees.submit() fee_list.append(fees.name) if fee_list: fee_list = ["""<a href="#Form/Fees/%s" target="_blank">%s</a>""" % \ (fee, fee) for fee in fee_list] msgprint( _("Fee Records Created - {0}").format(comma_and(fee_list)))
def check_email_id_is_unique(self): if self.email_id: names = frappe.db.sql_list("""select name from `tabJob Applicant` where email_id=%s and name!=%s and job_title=%s""", (self.email_id, self.name, self.job_title)) if names: frappe.throw(_("Email Address must be unique, already exists for {0}").format(comma_and(names)), frappe.DuplicateEntryError)
def get_row_data(self, task_details): assigned_user = [] if task_details.assignee: assigned_user = [ value for key, value in task_details.assignee.items() if key == "name" ] parent_id = '' parent_name = '' if task_details.parent: parent = frappe._dict(task_details.parent) parent_id = parent.gid parent_name = parent.name return { "name": task_details.name, "global_id": task_details.gid, "notes": task_details.notes or '', "assignee": comma_and(assigned_user) if len(assigned_user) else '', "status": "Completed" if task_details.completed else "In Progress", "completed_on": task_details.created_at, "parent_id": parent_id, "parent_name": parent_name, "reference": task_details.permalink_url }
def allocate_leave(self): self.validate_values() leave_allocated_for = [] employees = self.get_employees() if not employees: frappe.throw(_("No employee found")) for d in self.get_employees(): try: la = frappe.new_doc('Leave Allocation') la.set("__islocal", 1) la.employee = cstr(d[0]) la.employee_name = frappe.db.get_value('Employee',cstr(d[0]),'employee_name') la.leave_type = self.leave_type la.from_date = self.from_date la.to_date = self.to_date la.carry_forward = cint(self.carry_forward) la.new_leaves_allocated = flt(self.no_of_days) la.docstatus = 1 la.save() leave_allocated_for.append(d[0]) except: pass if leave_allocated_for: msgprint(_("Leaves Allocated Successfully for {0}").format(comma_and(leave_allocated_for)))
def make_fee_records(self): from erpnext.schools.api import get_fee_components fee_list = [] for d in self.fees: fee_components = get_fee_components(d.fee_structure) if fee_components: fees = frappe.new_doc("Fees") fees.update({ "student": self.student, "academic_year": self.academic_year, "academic_term": d.academic_term, "fee_structure": d.fee_structure, "program": self.program, "due_date": d.due_date, "student_name": self.student_name, "program_enrollment": self.name, "components": fee_components }) fees.save() fees.submit() fee_list.append(fees.name) if fee_list: fee_list = ["""<a href="#Form/Fees/%s" target="_blank">%s</a>""" % \ (fee, fee) for fee in fee_list] msgprint(_("Fee Records Created - {0}").format(comma_and(fee_list)))
def create_material_request(self): items_to_be_requested = self.get_requested_items() material_request_list = [] if items_to_be_requested: for item in items_to_be_requested: item_wrapper = frappe.get_doc("Item", item) material_request = frappe.new_doc("Material Request") material_request.update({ "transaction_date": nowdate(), "status": "Draft", "company": self.company, "requested_by": frappe.session.user, "material_request_type": "Purchase" }) for sales_order, requested_qty in items_to_be_requested[ item].items(): material_request.append( "items", { "doctype": "Material Request Item", "__islocal": 1, "item_code": item, "item_name": item_wrapper.item_name, "description": item_wrapper.description, "uom": item_wrapper.stock_uom, "item_group": item_wrapper.item_group, "brand": item_wrapper.brand, "qty": requested_qty, "schedule_date": add_days(nowdate(), cint(item_wrapper.lead_time_days)), "warehouse": self.purchase_request_for_warehouse, "sales_order": sales_order if sales_order != "No Sales Order" else None }) material_request.flags.ignore_permissions = 1 material_request.submit() material_request_list.append(material_request.name) if material_request_list: message = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \ (p, p) for p in material_request_list] msgprint( _("Material Requests {0} created").format( comma_and(message))) else: msgprint(_("Nothing to request"))
def show_list_created_message(self, doctype, doc_list=None): if not doc_list: return frappe.flags.mute_messages = False if doc_list: doc_list = [get_link_to_form(doctype, p) for p in doc_list] msgprint(_("{0} created").format(comma_and(doc_list)))
def check_email_id_is_unique(self): if self.email_id: # validate email is unique email_list = frappe.db.sql("""select name from tabLead where email_id=%s""", self.email_id) if len(email_list) > 1: items = [e[0] for e in email_list if e[0]!=self.name] frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(items)))
def check_email_id_is_unique(self): if self.email_id: # validate email is unique duplicate_leads = frappe.db.sql_list("""select name from tabLead where email_id=%s and name!=%s""", (self.email_id, self.name)) if duplicate_leads: frappe.throw(_("Email Address must be unique, already exists for {0}") .format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
def check_email_id_is_unique(self): if self.email_id: # validate email is unique duplicate_leads = frappe.get_all("Lead", filters={"email_id": self.email_id, "name": ["!=", self.name]}) duplicate_leads = [lead.name for lead in duplicate_leads] if duplicate_leads: frappe.throw(_("Email Address must be unique, already exists for {0}") .format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
def check_next_docs(self): invoices = frappe.db.sql(""" SELECT name FROM `tabIndent Invoice` WHERE docstatus = 1 AND indent = '{}' """.format(self.name)) if invoices: frappe.throw("Invoices {} is/are attached to this indent. Cancel those first.".format( comma_and(invoices) ))
def check_date_is_unique(self): if self.posting_date: names = frappe.db.sql_list( """select name from `tabCovid19 Entry` where posting_date=%s and name!=%s""", (self.posting_date, self.name)) if names: frappe.throw( _("Posting Date must be unique, already exists for {0}"). format(comma_and(names)), frappe.DuplicateEntryError)
def validate_delivery_day(self): delivery_days = frappe.db.get_value("Customer", self.customer, "delivery_days") if not delivery_days: return customer_delivery_days = json.loads(delivery_days) if customer_delivery_days: delivery_day = calendar.day_name[getdate(self.delivery_date).weekday()] if delivery_day not in customer_delivery_days: frappe.msgprint(_("This order is set to be delivered on a '{0}', but {1} only accepts deliveries on {2}").format( frappe.bold(delivery_day), frappe.bold(self.customer), comma_and(customer_delivery_days)))
def cancel_cheque_payment_entry(self, action_status): self.update_status(action_status) if self.payment_entry: frappe.get_doc("Payment Entry", self.payment_entry).cancel() self.append( "status_history", { "status": action_status, "transaction_date": nowdate(), "bank": self.deposit_account }) self.bank_changed = 1 self.submit() message = """<a href="#Form/Payment Entry/%s" target="_blank">%s</a>""" % ( self.payment_entry, self.payment_entry) msgprint(_("Payment Entry {0} Cancelled").format(comma_and(message))) message = _("Payment Entry {0} Cancelled").format(comma_and(message)) return message
def validate(self): if self.designation: names = frappe.db.sql_list( """select name from `tabJob Description` where designation=%s and name!=%s """, (self.designation, self.name)) if names: frappe.throw( _("Designation must be unique, already exists for {0}"). format(comma_and(names)), frappe.DuplicateEntryError)
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"))
def check_progress_calc_method(self): bsc_target_master = frappe.get_doc("BSC Target", self.bsc_target) if bsc_target_master.based_last_month and self.based_last_month: conditions = " where based_last_month=1 and docstatus < 2 and bsc_target = '%s'" % self.bsc_target conditions += " and name <> '%s'" % self.name names = frappe.db.sql_list( """select name from `tabBSC Initiative` %s""" % conditions) if names: frappe.throw( _("Progress Based on Last Month must to be unique, already exists for {0}" ).format(comma_and(names)), frappe.DuplicateEntryError)
def make_journal_entry(self, account1, account2, amount, action_status, posting_date=None, party_type=None, party=None, cost_center=None, save=True, submit=False): cost_center_project = cost_center if self.project: cost_center_project = frappe.db.get_value("Project", self.project, "cost_center") jv = frappe.new_doc("Journal Entry") jv.posting_date = posting_date or nowdate() jv.company = self.company jv.cheque_no = self.cheque_no jv.cheque_date = self.cheque_date jv.user_remark = self.remarks or "Cheque Transaction" jv.multi_currency = 0 jv.set("accounts", [ { "account": account1, "party_type": party_type if (action_status == "Cheque Cancelled") else None, "party": party if action_status == "Cheque Cancelled" else None, "cost_center": cost_center_project, "project": self.project, "debit_in_account_currency": amount if amount > 0 else 0, "credit_in_account_currency": abs(amount) if amount < 0 else 0 }, { "account": account2, "party_type": party_type if action_status == "Cheque Issued" else None, "party": party if action_status == "Cheque Issued" else None, "cost_center": cost_center_project, "project": self.project, "credit_in_account_currency": amount if amount > 0 else 0, "debit_in_account_currency": abs(amount) if amount < 0 else 0 } ]) if save or submit: jv.insert(ignore_permissions=True) if submit: jv.submit() self.append("status_history", { "status": action_status, "transaction_date": nowdate(), "transaction_posting_date": posting_date or nowdate(), "debit_account": account1, "credit_account": account2, "journal_entry": jv.name }) self.update_status(action_status) self.submit() message = """<a href="#Form/Journal Entry/%s" target="_blank">%s</a>""" % (jv.name, jv.name) msgprint(_("Journal Entry {0} created").format(comma_and(message))) #message = _("Journal Entry {0} created").format(comma_and(message)) return message
def make_stock_entries(self, purpose=None, all=False): if purpose: conditions = "" ste_list = [] for item in self.get('items'): bom = frappe.db.get_value("BOM", filters={ "item": item.item_code, "project": self.project }) or frappe.db.get_value( "BOM", filters={ "item": item.item_code, "is_default": 1 }) if bom: if purpose == "Manufacture": stock_entries = frappe.db.sql( """select name from `tabStock Entry` where delivery_note_no=%s and docstatus=0 and purpose=%s and bom_no = %s""", (self.name, purpose, bom), as_dict=1) if not stock_entries: ste_name = self.make_stock_entry_from_do( bom, purpose, item.against_sales_order, item.qty) if ste_name: ste_list.append(ste_name) else: stock_entries = frappe.db.sql( """select name from `tabStock Entry` where delivery_note_no=%s and docstatus=0 and purpose=%s and bom_no = %s""", (self.name, purpose, bom), as_dict=1) if not stock_entries: ste_name = self.make_stock_entry_from_do( bom, purpose, item.against_sales_order, item.qty) if ste_name: ste_list.append(ste_name) if ste_list: ste_list = ["""<a href="#Form/Stock Entry/%s" target="_blank">%s</a>""" % \ (p, p) for p in ste_list] msgprint( _("{0} created for {1}").format(comma_and(ste_list), purpose)) else: msgprint(_("No Stock Entries Created for {0}").format(purpose))
def update_status(data, status): if isinstance(data, string_types): data = json.loads(data) forbidden_doc_list = [] ineligible_doc_list = [] allow_user = True user = frappe.session.user is_enabled = frappe.db.get_value('CD GSTR 2B Settings', None, 'enable_account_freezing') acc_settings = frappe.db.get_values('Accounts Settings', None, ['acc_frozen_upto', 'frozen_accounts_modifier']) if not user in get_users_with_role(acc_settings[0][1]) and user != 'Administrator' and is_enabled: allow_user = False for row in data: if row and row['gstr_2b']: doc = frappe.get_doc('CD GSTR 2B Entry', row['gstr_2b']) if doc.cf_status == 'Accepted' and not allow_user and is_enabled: if getdate(doc.cf_document_date) <= getdate(acc_settings[0][0]): forbidden_doc_list.append(comma_and("""<a href="#Form/CD GSTR 2B Entry/{0}">{1}</a>""".format(row['gstr_2b'], row['gstr_2b']))) else: forbidden_doc_list.append(comma_and("""<a href="#Form/CD GSTR 2B Entry/{0}">{1}</a>""".format(row['gstr_2b'], row['gstr_2b']))) continue if doc.cf_status == 'Pending' and not allow_user and is_enabled: if getdate(doc.cf_document_date) <= getdate(acc_settings[0][0]): forbidden_doc_list.append(comma_and("""<a href="#Form/CD GSTR 2B Entry/{0}">{1}</a>""".format(row['gstr_2b'], row['gstr_2b']))) continue if status == 'Accepted' and doc.cf_purchase_invoice and \ round(abs(doc.cf_tax_amount - get_tax_details(doc.cf_purchase_invoice)['total_tax_amount']), 2) > 10: ineligible_doc_list.append(comma_and("""<a href="#Form/CD GSTR 2B Entry/{0}">{1}</a>""".format(row['gstr_2b'], row['gstr_2b']))) continue doc.cf_status = status doc.save(ignore_permissions = True) doc.reload() frappe.db.commit() if forbidden_doc_list: forbidden_docs = ','.join(forbidden_doc_list) frappe.throw(_(f"You are not authorized to update entries {forbidden_docs}")) if ineligible_doc_list: ineligible_docs = ','.join(ineligible_doc_list) frappe.throw(_(f"Tax difference exceeded Rs.10. Unable to accept these documents {ineligible_docs}."))
def validate_exchange_rates_exist(self): """check if exchange rates exist for all Price List currencies (to company's currency)""" company_currency = frappe.get_cached_value('Company', self.company, "default_currency") if not company_currency: msgprint(_("Please specify currency in Company") + ": " + self.company, raise_exception=ShoppingCartSetupError) price_list_currency_map = frappe.db.get_values("Price List", [self.price_list], "currency") price_list_currency_map = dict(price_list_currency_map) # check if all price lists have a currency for price_list, currency in price_list_currency_map.items(): if not currency: frappe.throw( _("Currency is required for Price List {0}").format( price_list)) expected_to_exist = [ currency + "-" + company_currency for currency in price_list_currency_map.values() if currency != company_currency ] # manqala 20/09/2016: set up selection parameters for query from tabCurrency Exchange from_currency = [ currency for currency in price_list_currency_map.values() if currency != company_currency ] to_currency = company_currency # manqala end if expected_to_exist: # manqala 20/09/2016: modify query so that it uses date in the selection from Currency Exchange. # exchange rates defined with date less than the date on which this document is being saved will be selected exists = frappe.db.sql_list( """select CONCAT(from_currency,'-',to_currency) from `tabCurrency Exchange` where from_currency in (%s) and to_currency = "%s" and date <= curdate()""" % (", ".join(["%s"] * len(from_currency)), to_currency), tuple(from_currency)) # manqala end missing = list(set(expected_to_exist).difference(exists)) if missing: msgprint(_("Missing Currency Exchange Rates for {0}").format( comma_and(missing)), raise_exception=ShoppingCartSetupError)
def validate_overlap_for_operation_timings(self): """Check if there is no overlap in setting Workstation Operating Hours""" for d in self.get("working_hours"): existing = frappe.db.sql_list("""select idx from `tabWorkstation Working Hour` where parent = %s and name != %s and ( (start_time between %s and %s) or (end_time between %s and %s) or (%s between start_time and end_time)) """, (self.name, d.name, d.start_time, d.end_time, d.start_time, d.end_time, d.start_time)) if existing: frappe.throw(_("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), OverlapError)
def validate_overlapping_territories(self, parentfield, fieldname): # for displaying message doctype = self.meta.get_field(parentfield).options # specify atleast one entry in the table self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) territory_name_map = self.get_territory_name_map(parentfield, fieldname) for territory, names in territory_name_map.items(): if len(names) > 1: frappe.throw(_("{0} {1} has a common territory {2}").format(_(doctype), comma_and(names), territory), ShoppingCartSetupError) return territory_name_map
def validate_overlap(self): existing = frappe.db.sql_list("""select name from `tabTime Log` where employee=%s and ( (from_time < %s and from_time > %s) or (to_time < %s and to_time < %s) or (%s between from_time and to_time)) and name !=%s and to_time > %s and docstatus < 2""", (self.employee, self.from_time, self.to_time, self.from_time, self.to_time, self.from_time, self.name or "No Name", self.from_time)) if existing: frappe.throw(_("This Time Log conflicts with {0}").format(comma_and(existing)), OverlapError)
def raise_production_order(self): """It will raise production order (Draft) for all distinct FG items""" self.validate_data() from erpnext.utilities.transaction_base import validate_uom_is_integer validate_uom_is_integer(self, "stock_uom", "planned_qty") items = self.get_distinct_items_and_boms()[1] pro = self.create_production_order(items) if pro: pro = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \ (p, p) for p in pro] msgprint(_("{0} created").format(comma_and(pro))) else : msgprint(_("No Production Orders created"))
def validate_overlap(self): existing = frappe.db.sql_list("""select name from `tabTime Log` where owner=%s and ( (from_time between %s and %s) or (to_time between %s and %s) or (%s between from_time and to_time)) and name!=%s and ifnull(task, "")=%s and docstatus < 2""", (self.owner, self.from_time, self.to_time, self.from_time, self.to_time, self.from_time, self.name or "No Name", cstr(self.task))) if existing: frappe.throw(_("This Time Log conflicts with {0}").format(comma_and(existing)), OverlapError)
def validate_overlapping_territories(self, parentfield, fieldname): # for displaying message doctype = self.meta.get_field(parentfield).options # specify atleast one entry in the table self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) territory_name_map = self.get_territory_name_map(parentfield, fieldname) for territory, names in territory_name_map.items(): if len(names) > 1: msgprint(_("Error for") + " " + _(doctype) + ": " + comma_and(names) + " " + _("have a common territory") + ": " + territory, raise_exception=ShoppingCartSetupError) return territory_name_map
def insert_purchase_request(self): items_to_be_requested = self.get_requested_items() purchase_request_list = [] if items_to_be_requested: for item in items_to_be_requested: item_wrapper = frappe.get_doc("Item", item) pr_doc = frappe.new_doc("Material Request") pr_doc.update( { "transaction_date": nowdate(), "status": "Draft", "company": self.company, "requested_by": frappe.session.user, "material_request_type": "Purchase", } ) for sales_order, requested_qty in items_to_be_requested[item].items(): pr_doc.append( "items", { "doctype": "Material Request Item", "__islocal": 1, "item_code": item, "item_name": item_wrapper.item_name, "description": item_wrapper.description, "uom": item_wrapper.stock_uom, "item_group": item_wrapper.item_group, "brand": item_wrapper.brand, "qty": requested_qty, "schedule_date": add_days(nowdate(), cint(item_wrapper.lead_time_days)), "warehouse": self.purchase_request_for_warehouse, "sales_order_no": sales_order if sales_order != "No Sales Order" else None, }, ) pr_doc.flags.ignore_permissions = 1 pr_doc.submit() purchase_request_list.append(pr_doc.name) if purchase_request_list: pur_req = [ """<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % (p, p) for p in purchase_request_list ] msgprint(_("Material Requests {0} created").format(comma_and(pur_req))) else: msgprint(_("Nothing to request"))
def on_update(self): frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock) if cint(self.auto_accounting_for_stock): # set default perpetual account in company for company in frappe.db.sql("select name from tabCompany"): frappe.get_doc("Company", company[0]).save() # Create account head for warehouses warehouse_list = frappe.db.sql("select name, company from tabWarehouse", as_dict=1) warehouse_with_no_company = [d.name for d in warehouse_list if not d.company] if warehouse_with_no_company: frappe.throw(_("Company is missing in warehouses {0}").format(comma_and(warehouse_with_no_company))) for wh in warehouse_list: wh_doc = frappe.get_doc("Warehouse", wh.name) wh_doc.save()
def validate_bill_no(self, method): if self.bill_no: # validate bill no is unique bill_list = frappe.db.sql( """select name from `tabPurchase Invoice` where bill_no=%s and docstatus =1 and is_recurring='0'""", self.bill_no, ) if len(bill_list) > 0: items = [e[0] for e in bill_list if e[0] != self.name] frappe.throw( _( "Supplier Invoice Number must be unique. Current Supplier Invoice Number already exists for {0}" ).format(comma_and(items)) ) if self.bill_date: if getdate(self.bill_date) > getdate(self.posting_date): frappe.throw(_("Supplier Invoice Date cannot be after Purchase Invoice Date"))
def make_work_order(self): wo_list = [] self.validate_data() items_data = self.get_production_items() for key, item in items_data.items(): work_order = self.create_work_order(item) if work_order: wo_list.append(work_order) frappe.flags.mute_messages = False if wo_list: wo_list = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \ (p, p) for p in wo_list] msgprint(_("{0} created").format(comma_and(wo_list))) else : msgprint(_("No Work Orders created"))
def validate_exchange_rates_exist(self): """check if exchange rates exist for all Price List currencies (to company's currency)""" company_currency = frappe.db.get_value("Company", self.company, "default_currency") if not company_currency: msgprint(_("Please specify currency in Company") + ": " + self.company, raise_exception=ShoppingCartSetupError) price_list_currency_map = frappe.db.get_values("Price List", [self.price_list], "currency") # check if all price lists have a currency for price_list, currency in price_list_currency_map.items(): if not currency: frappe.throw(_("Currency is required for Price List {0}").format(price_list)) expected_to_exist = [currency + "-" + company_currency for currency in price_list_currency_map.values() if currency != company_currency] # manqala 20/09/2016: set up selection parameters for query from tabCurrency Exchange from_currency = [currency for currency in price_list_currency_map.values() if currency != company_currency] to_currency = company_currency # manqala end if expected_to_exist: # manqala 20/09/2016: modify query so that it uses date in the selection from Currency Exchange. # exchange rates defined with date less than the date on which this document is being saved will be selected exists = frappe.db.sql_list("""select CONCAT(from_currency,'-',to_currency) from `tabCurrency Exchange` where from_currency in (%s) and to_currency = "%s" and date <= curdate()""" % (", ".join(["%s"]*len(from_currency)), to_currency), tuple(from_currency)) # manqala end missing = list(set(expected_to_exist).difference(exists)) if missing: msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)), raise_exception=ShoppingCartSetupError)