def raise_exceptions(self): deficiency = min(e["diff"] for e in self.exceptions) if ( self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"], ) in frappe.local.flags.currently_saving: msg = _("{0} units of {1} needed in {2} to complete this transaction.").format( abs(deficiency), frappe.get_desk_link("Item", self.item_code), frappe.get_desk_link("Warehouse", self.warehouse), ) else: msg = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format( abs(deficiency), frappe.get_desk_link("Item", self.item_code), frappe.get_desk_link("Warehouse", self.warehouse), self.exceptions[0]["posting_date"], self.exceptions[0]["posting_time"], frappe.get_desk_link(self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"]), ) if self.verbose: frappe.throw(msg, NegativeStockError, title="Insufficent Stock") else: raise NegativeStockError, msg
def validate(doc,method): ship_pincode = frappe.db.get_value("Address", doc.shipping_address_name ,"pincode") bill_pincode = frappe.db.get_value("Address", doc.customer_address ,"pincode") ship_gstin = frappe.db.get_value("Address", doc.shipping_address_name ,"gstin") bill_gstin = frappe.db.get_value("Address", doc.customer_address ,"gstin") bill_state = frappe.db.get_value("Address", doc.customer_address, "state_rigpl") ship_country = frappe.db.get_value("Address", doc.shipping_address_name, "country") template_doc = frappe.get_doc("Sales Taxes and Charges Template", doc.taxes_and_charges) if ship_pincode is None: frappe.throw(("Shipping Pincode is Mandatory or NA, please correct it in Shipping Address {0}").\ format(frappe.get_desk_link('Address', doc.shipping_address_name))) if bill_pincode is None: frappe.throw(("Billing Pincode is Mandatory or NA, please correct it in Billing Address {0}").\ format(frappe.get_desk_link('Address', doc.shipping_address_name))) doc.shipping_address_gstin = ship_gstin doc.billing_address_gstin = bill_gstin for items in doc.items: custom_tariff = frappe.db.get_value("Item", items.item_code, "customs_tariff_number") if custom_tariff: if len(custom_tariff) == 8: items.gst_hsn_code = custom_tariff else: frappe.throw(("Item Code {0} in line# {1} has a Custom Tariff {2} which not \ 8 digit, please get the Custom Tariff corrected").\ format(items.item_code, items.idx, custom_tariff)) else: frappe.throw(("Item Code {0} in line# {1} does not have linked Customs \ Tariff in Item Master").format(items.item_code, items.idx)) #Check if Shipping State is Same as Template State then check if the tax template is LOCAL #Else if the States are different then the template should NOT BE LOCAL if bill_state == template_doc.state and template_doc.is_export == 0: if template_doc.is_local_sales != 1: frappe.throw(("Selected Tax {0} is NOT LOCAL Tax but Billing Address is \ in Same State {1}, hence either change Billing Address or Change the \ Selected Tax").format(doc.taxes_and_charges, bill_state)) elif ship_country == 'India' and bill_state != template_doc.state: if template_doc.is_local_sales == 1: frappe.throw(("Selected Tax {0} is LOCAL Tax but Billing Address is \ in Different State {1}, hence either change Billing Address or Change the \ Selected Tax").format(doc.taxes_and_charges, bill_state)) elif ship_country != 'India': #Case of EXPORTS if template_doc.is_export != 1: frappe.throw(("Selected Tax {0} is for Indian Sales but Billing Address is \ in Different Country {1}, hence either change Billing Address or Change the \ Selected Tax").format(doc.taxes_and_charges, ship_country)) #lastly check the child taxes table are in sync with the template check_taxes_integrity(doc, method, template_doc)
def create_new_carrier_track(doc, method): # If SI is from Cancelled Doc then update the Existing Carrier Track is_tracked = is_tracked_transporter(doc, method) if is_tracked == 1: if doc.amended_from: existing_track = check_existing_track(doc.doctype, doc.amended_from) if existing_track: exist_track = frappe.get_doc("Carrier Tracking", existing_track[0][0]) if exist_track.docstatus == 0: doc.lr_no = exist_track.awb_number exist_track.receiver_name = doc.customer exist_track.document_name = doc.name doc.transporters = exist_track.carrier_name exist_track.flags.ignore_permissions = True exist_track.save() frappe.msgprint(("Updated {0}").format(frappe.get_desk_link('Carrier Tracking', exist_track.name))) elif exist_track.docstatus == 1: route = doc.name.lower() + exist_track.name.lower() frappe.db.set_value("Carrier Tracking", exist_track.name, "published", 1) frappe.db.set_value("Carrier Tracking", exist_track.name, "document_name", doc.name) frappe.db.set_value("Carrier Tracking", exist_track.name, "reference_document_name", "") frappe.db.set_value("Carrier Tracking", exist_track.name, "route", route) else: new_ctrack = frappe.copy_doc(exist_track) new_ctrack.amended_from = exist_track.name new_ctrack.document_name = doc.name new_ctrack.insert(ignore_permissions=True) frappe.msgprint(("Added New {0}").format(frappe.get_desk_link \ ('Carrier Tracking', new_ctrack.name))) else: create_new_ship_track(doc) elif check_existing_track(doc.doctype, doc.name) is None: # Dont create a new Tracker if already exists create_new_ship_track(doc)
def get_available_item_locations(item_code, from_warehouses, required_qty, company, ignore_validation=False): locations = [] has_serial_no = frappe.get_cached_value("Item", item_code, "has_serial_no") has_batch_no = frappe.get_cached_value("Item", item_code, "has_batch_no") if has_batch_no and has_serial_no: locations = get_available_item_locations_for_serial_and_batched_item( item_code, from_warehouses, required_qty, company) elif has_serial_no: locations = get_available_item_locations_for_serialized_item( item_code, from_warehouses, required_qty, company) elif has_batch_no: locations = get_available_item_locations_for_batched_item( item_code, from_warehouses, required_qty, company) else: locations = get_available_item_locations_for_other_item( item_code, from_warehouses, required_qty, company) total_qty_available = sum(location.get("qty") for location in locations) remaining_qty = required_qty - total_qty_available if remaining_qty > 0 and not ignore_validation: frappe.msgprint( _("{0} units of Item {1} is not available.").format( remaining_qty, frappe.get_desk_link("Item", item_code)), title=_("Insufficient Stock"), ) return locations
def create_new_communication(created_by, next_action_by, row): comm = frappe.new_doc("Communication") comm.owner = created_by comm.user = next_action_by comm.communication_date = row.communication_date comm.duration = row.duration #add custom field for next_action_date in Communication #add custom field for communication_subtype in Communication if row.no_action_required != 1: comm.follow_up = 1 comm.next_action_date = row.next_action_date #This would add a TODO to USER fields' account on that day comm.communication_subtype = "Sales Related" comm.communication_medium = row.type_of_communication #Change the above Select field by customize form view in Communication comm.communication_type = "Communication" comm.content = row.details if row.document == "Customer": comm.reference_doctype = "Contact" comm.reference_name = row.contact comm.timeline_doctype = row.document comm.timeline_name = row.document_name comm.subject = "Sales Call: " + row.type_of_communication + " To:" + \ row.document + ":" + row.document_name + " Contact:" + row.contact elif row.document == "Lead": comm.reference_doctype = row.document comm.reference_name = row.document_name comm.subject = "Sales Call: " + row.type_of_communication + " To:" + \ row.document + ":" + row.document_name + " Org:" + \ row.lead_organisation_name + " Contact:" + row.lead_contact_name else: frappe.throw("Error Contact [email protected]") comm.insert() frappe.db.set_value('Daily Call Details', row.name, 'communication', comm.name) row.communication = comm.name frappe.msgprint("Created New Communication {}".format(frappe.get_desk_link('Communication', comm.name)))
def validate_carrier_tracking(doc,method): tracked_transporter = is_tracked_transporter(doc,method) if tracked_transporter == 1: frappe.msgprint(("{0} is Tracked Automatically all Shipment Data for LR No {1} \ would be automatically updated in Carrier Tracking Document").format( frappe.get_desk_link('Transporters', doc.transporters), doc.lr_no)) return tracked_transporter
def create_new_brc_tracking(doc,method): brc_doc = frappe.new_doc("BRC MEIS Tracking") brc_doc.flags.ignore_permissions = True brc_doc.export_or_import = 'Export' brc_doc.reference_doctype = doc.doctype brc_doc.reference_name = doc.name brc_doc.insert() frappe.msgprint(("Created New {0}").format(frappe.get_desk_link('BRC MEIS Tracking', brc_doc.name)))
def validate_duplicate_log(self): doc = frappe.db.exists('Employee Checkin', { 'employee': self.employee, 'time': self.time, 'name': ['!=', self.name]}) if doc: doc_link = frappe.get_desk_link('Employee Checkin', doc) frappe.throw(_('This employee already has a log with the same timestamp.{0}') .format("<Br>" + doc_link))
def _delete_cashback(doc): cashback_receipt_name = frappe.db.exists("Cashback Receipt", {"origin": doc.name}) if not cashback_receipt_name: return cashback_receipt = frappe.get_doc("Cashback Receipt", cashback_receipt_name) if len(cashback_receipt.redemptions) > 0: frappe.throw( _("{} cannot be cancelled because {} is redeemed.").format( frappe.get_desk_link("Sales Invoice", doc.name), "cancelled" if doc.docstatus == 2 else "returned", frappe.get_desk_link("Cashback Receipt", cashback_receipt_name), )) frappe.delete_doc("Cashback Receipt", cashback_receipt.name, ignore_permissions=True)
def _get_filters(doctype, filters): is_include = filters.vat_type not in ["Standard Rated", "Zero Rated"] vat_exempt_accounts = [ x[0] for x in frappe.get_all( "POS Bahrain Settings Tax Category", filters={"category": filters.vat_type} if is_include else {}, fields=["account"], as_list=1, ) ] if not vat_exempt_accounts: msg = "Please setup {}: <em>VAT Tax Categories</em>".format( frappe.get_desk_link("POS Bahrain Settings", "") ) if filters.get("hide_error_message"): raise VatCategoryNotFound(msg) else: frappe.throw(msg, exc=VatCategoryNotFound) inv_clauses = [ "d.docstatus = 1", "d.posting_date BETWEEN %(from_date)s AND %(to_date)s", "IFNULL(dt.account_head, '') != ''", "dt.account_head {} %(tax_accounts)s".format("IN" if is_include else "NOT IN"), ] glp_clauses = concatv( inv_clauses, ["d.payment_type IN %(payment_types)s", "a.account_type = 'Tax'"] ) values = merge( pick(["vat_type"], filters), { "from_date": filters.date_range[0], "to_date": filters.date_range[1], "tax_accounts": vat_exempt_accounts, "payment_types": ["Incoming"] if doctype == "Sales Invoice" else ["Outgoing", "Internal Transfer"], }, ) return ( { "doctype": doctype, "item_doctype": "{} Item".format(doctype), "tax_doctype": "{} Taxes and Charges".format( "Sales" if doctype == "Sales Invoice" else "Purchase" ), "party_name": "{}_name".format( "customer" if doctype == "Sales Invoice" else "supplier" ), "invoice_clauses": " AND ".join(inv_clauses), "glp_clauses": " AND ".join(glp_clauses), }, values, )
def validate_negative_qty_in_future_sle(args, allow_negative_stock=None): allow_negative_stock = allow_negative_stock \ or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) if args.actual_qty < 0 and not allow_negative_stock: sle = get_future_sle_with_negative_qty(args) if sle: message = _( "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." ).format( abs(sle[0]["qty_after_transaction"]), frappe.get_desk_link('Item', args.item_code), frappe.get_desk_link('Warehouse', args.warehouse), sle[0]["posting_date"], sle[0]["posting_time"], frappe.get_desk_link(sle[0]["voucher_type"], sle[0]["voucher_no"])) frappe.throw(message, NegativeStockError, title='Insufficient Stock')
def validate(doc, method): if doc.reference_type == 'Communication': if doc.reference_name: comm_doc = frappe.get_doc('Communication', doc.reference_name) else: frappe.throw('Reference Name is Mandatory for {} Reference Type'.format(doc.reference_name)) if comm_doc.follow_up == 1 and doc.status == 'Closed': frappe.msgprint("If you don't wish to receive ToDo for this Communication \ then Click on Communication and uncheck the Follow Up Check Box \ or Change the next action date to be reminded again about this communication \ {}".format(frappe.get_desk_link("Communication", doc.reference_name)))
def create_new_ship_track(si_doc): track = frappe.new_doc("Carrier Tracking") track.carrier_name = si_doc.transporters track.awb_number = si_doc.lr_no track.receiver_document = "Customer" track.receiver_name = si_doc.customer track.document = "Sales Invoice" track.document_name = si_doc.name track.flags.ignore_permissions = True track.insert() frappe.msgprint(("Created New {0}").format(frappe.get_desk_link('Carrier Tracking', track.name)))
def raise_exceptions(self): deficiency = min(e["diff"] for e in self.exceptions) if ((self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"]) in frappe.local.flags.currently_saving): msg = _("{0} units of {1} needed in {2} to complete this transaction.").format( abs(deficiency), frappe.get_desk_link('Item', self.item_code), frappe.get_desk_link('Warehouse', self.warehouse)) else: msg = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format( abs(deficiency), frappe.get_desk_link('Item', self.item_code), frappe.get_desk_link('Warehouse', self.warehouse), self.exceptions[0]["posting_date"], self.exceptions[0]["posting_time"], frappe.get_desk_link(self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"])) if self.verbose: frappe.throw(msg, NegativeStockError, title='Insufficent Stock') else: raise NegativeStockError(msg)
def _validate_collected_booking_orders(self): for bo_name in set(x.booking_order for x in self.on_loads + self.off_loads): status = frappe.get_cached_value("Booking Order", bo_name, "status") if status == "Collected": frappe.throw( frappe._("Cannot cancel this Loading Operation contains " "{} which is already Collected.".format( frappe.get_desk_link("Booking Order", bo_name))))
def create_new_ship_track(si_doc): track = frappe.new_doc("Carrier Tracking") track.carrier_name = si_doc.transporters track.awb_number = si_doc.lr_no track.receiver_document = "Customer" track.receiver_name = si_doc.customer track.document = "Sales Invoice" track.document_name = si_doc.name # track.shipment_package_details = [{"shipment_package":"PKG00001", "package_weight":1, "weight_uom":"Kg"}] track.flags.ignore_permissions = True track.insert() frappe.msgprint(("Created New {0}").format(frappe.get_desk_link('Carrier Tracking', track.name)))
def validate_duplicate_log(self): doc = frappe.db.exists( "Employee Checkin", { "employee": self.employee, "time": self.time, "name": ["!=", self.name] }) if doc: doc_link = frappe.get_desk_link("Employee Checkin", doc) frappe.throw( _("This employee already has a log with the same timestamp.{0}" ).format("<Br>" + doc_link))
def _validate_default(self): existing = frappe.db.exists( "Booking Order Charge Template", { "is_default": 1, "name": ("!=", self.name) }, ) if existing: frappe.throw( frappe._("{} is already the default template".format( frappe.get_desk_link("Booking Order Charge Template", existing))))
def _get_filters(doctype, filters): vat_exempt_accounts = [ x[0] for x in frappe.get_all( "POS Bahrain Settings Tax Exempt", fields=["account"], as_list=1) ] if not vat_exempt_accounts: frappe.throw( frappe._("Please set {}: <em>VAT Exempt Accounts</em>".format( frappe.get_desk_link("POS Bahrain Settings", "")))) inv_clauses = [ "d.docstatus = 1", "d.posting_date BETWEEN %(from_date)s AND %(to_date)s", "IFNULL(dt.account_head, '') != ''", "dt.account_head {} %(tax_accounts)s".format( "IN" if filters.vat_type == "exempt" else "NOT IN"), ] glp_clauses = concatv( inv_clauses, ["d.payment_type IN %(payment_types)s", "a.account_type = 'Tax'"]) values = merge( pick(["vat_type"], filters), { "from_date": filters.date_range[0], "to_date": filters.date_range[1], "tax_accounts": vat_exempt_accounts, "payment_types": ["Incoming"] if doctype == "Sales Invoice" else ["Outgoing", "Internal Transfer"], }, ) return ( { "doctype": doctype, "item_doctype": "{} Item".format(doctype), "tax_doctype": "{} Taxes and Charges".format("Sales" if doctype == "Sales Invoice" else "Purchase"), "party_name": "{}_name".format("customer" if doctype == "Sales Invoice" else "supplier"), "invoice_clauses": " AND ".join(inv_clauses), "glp_clauses": " AND ".join(glp_clauses), }, values, )
def get_available_item_locations(item_code, from_warehouses, required_qty, company, ignore_validation=False): locations = [] locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company) total_qty_available = sum(location.get('qty') for location in locations) remaining_qty = required_qty - total_qty_available if remaining_qty > 0 and not ignore_validation: frappe.msgprint(_('{0} units of Item {1} is not available.') .format(remaining_qty, frappe.get_desk_link('Item', item_code)), title=_("Insufficient Stock")) return locations
def validate(doc, method): if doc.reference_type == 'Communication': if doc.reference_name: comm_doc = frappe.get_doc('Communication', doc.reference_name) else: frappe.throw( 'Reference Name is Mandatory for {} Reference Type'.format( doc.reference_name)) if comm_doc.follow_up == 1 and doc.status == 'Closed': frappe.msgprint( "If you don't wish to receive ToDo for this Communication \ then Click on Communication and uncheck the Follow Up Check Box \ or Change the next action date to be reminded again about this communication \ {}".format(frappe.get_desk_link("Communication", doc.reference_name)))
def raise_exceptions(self): msg_list = [] for warehouse, exceptions in iteritems(self.exceptions): deficiency = min(e["diff"] for e in exceptions) if ((exceptions[0]["voucher_type"], exceptions[0]["voucher_no"]) in frappe.local.flags.currently_saving): msg = _( "{0} units of {1} needed in {2} to complete this transaction." ).format( abs(deficiency), frappe.get_desk_link('Item', exceptions[0]["item_code"]), frappe.get_desk_link('Warehouse', warehouse)) else: msg = _( "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." ).format( abs(deficiency), frappe.get_desk_link('Item', exceptions[0]["item_code"]), frappe.get_desk_link('Warehouse', warehouse), exceptions[0]["posting_date"], exceptions[0]["posting_time"], frappe.get_desk_link(exceptions[0]["voucher_type"], exceptions[0]["voucher_no"])) if msg: msg_list.append(msg) if msg_list: message = "\n\n".join(msg_list) if self.verbose: frappe.throw(message, NegativeStockError, title='Insufficient Stock') else: raise NegativeStockError(message)
def _validate_freight_qty(doc): bo = frappe.get_cached_doc("Booking Order", doc.gg_booking_order) get_freight_row = compose( excepts(StopIteration, first, lambda _: None), lambda x: filter(lambda row: row.name == x, bo.freight), ) for item in doc.items: if item.gg_bo_detail: freight_row = get_freight_row(item.gg_bo_detail) if not freight_row: frappe.throw( frappe. _("Invalid Booking Order Freight Detail found in row #{} for {}" .format(item.idx, frappe.get_desk_link("Sales Invoice", doc.name)))) total_qty = (frappe.get_all( "Sales Invoice Item", filters={ "docstatus": 1, "gg_bo_detail": item.gg_bo_detail }, fields=["sum(qty)"], as_list=1, )[0][0] or 0) if total_qty + item.qty > _get_freight_qty(freight_row): frappe.throw( frappe. _("Total Qty in #{} for {} will exceed Freight Qty declared in {}" .format( item.idx, frappe.get_desk_link("Sales Invoice", doc.name), frappe.get_desk_link("Booking Order", doc.gg_booking_order), )))
def validate_default_permission(self): ''' validate user permission overlap for default value of a particular doctype ''' overlap_exists = [] if self.is_default: overlap_exists = frappe.get_all(self.doctype, filters={ 'allow': self.allow, 'user': self.user, 'is_default': 1, 'name': ['!=', self.name] }, or_filters={ 'applicable_for': cstr(self.applicable_for), 'apply_to_all_doctypes': 1 }, limit=1) if overlap_exists: ref_link = frappe.get_desk_link(self.doctype, overlap_exists[0].name) frappe.throw(_("{0} has already assigned default value for {1}.".format(ref_link, self.allow)))
def validate_default_permission(self): """validate user permission overlap for default value of a particular doctype""" overlap_exists = [] if self.is_default: overlap_exists = frappe.get_all( self.doctype, filters={"allow": self.allow, "user": self.user, "is_default": 1, "name": ["!=", self.name]}, or_filters={ "applicable_for": cstr(self.applicable_for), "apply_to_all_doctypes": 1, }, limit=1, ) if overlap_exists: ref_link = frappe.get_desk_link(self.doctype, overlap_exists[0].name) frappe.throw(_("{0} has already assigned default value for {1}.").format(ref_link, self.allow))
def validate(doc, method): def get_error_type(): if doc.gg_loading_operation: existing = frappe.db.exists( "Sales Invoice", { "name": ("!=", doc.name), "docstatus": 1, "gg_booking_order": doc.gg_booking_order, "gg_loading_operation": doc.gg_loading_operation, }, ) if existing: return "freight" else: existing = frappe.db.sql( """ SELECT COUNT(name) FROM `tabSales Invoice` WHERE name != %(name)s AND docstatus = 1 AND gg_booking_order = %(booking_order)s AND IFNULL(gg_loading_operation, '') = '' """, values={ "name": doc.name, "booking_order": doc.gg_booking_order }, )[0][0] if existing: return "charges" return None if doc.gg_booking_order: error_type = get_error_type() if error_type: frappe.throw( frappe. _("Sales Invoice for {} already existing for {}. ".format( error_type, frappe.get_desk_link("Booking Order", doc.gg_booking_order), ) + "If you want to proceed, please cancel the previous Invoice." )) if doc.flags.validate_loading and doc.gg_loading_operation: _validate_freight_qty(doc)
def get_available_item_locations(item_code, from_warehouses, required_qty, company): locations = [] if frappe.get_cached_value('Item', item_code, 'has_serial_no'): locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty, company) elif frappe.get_cached_value('Item', item_code, 'has_batch_no'): locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty, company) else: locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company) total_qty_available = sum(location.get('qty') for location in locations) remaining_qty = required_qty - total_qty_available if remaining_qty > 0: frappe.msgprint(_('{0} units of {1} is not available.') .format(remaining_qty, frappe.get_desk_link('Item', item_code))) return locations
def validate(self): existing_loading_unit = frappe.db.get_value( "Booking Log", filters={ "name": ("!=", self.name), "booking_order": self.booking_order, "activity": ("!=", "Booked"), }, fieldname="loading_unit", ) if existing_loading_unit and self.loading_unit != existing_loading_unit: frappe.throw( frappe. _("Previous Loading Operation on {} has already being performed based on {}. " .format( frappe.get_desk_link("Booking Order", self.booking_order), existing_loading_unit, ) + "Please execute the current one based on the same unit."))
def on_cancel(self): for (log_name, ) in frappe.get_all( "Booking Log", filters={"booking_order": self.name}, as_list=1): frappe.delete_doc("Booking Log", log_name, ignore_permissions=True) for (si_name, ) in frappe.get_all( "Sales Invoice", filters={ "docstatus": 1, "gg_booking_order": self.name }, as_list=1, ): si = frappe.get_doc("Sales Invoice", si_name) if si.status == "Paid": frappe.throw( frappe._("Cannot cancel Paid invoice {}".format( frappe.get_desk_link("Sales Invoice", si_name)))) si.flags.ignore_permissions = True si.cancel()
def new_brc_tracking(doc,method): #If SI is from Cancelled DOC then UPDATE the details of same in BRC stct_doc = frappe.get_doc("Sales Taxes and Charges Template", doc.taxes_and_charges) add_doc = frappe.get_doc("Address", doc.shipping_address_name) if stct_doc.is_export == 1 and add_doc.country != "India": if doc.amended_from: is_exist = frappe.db.sql("""SELECT name FROM `tabBRC MEIS Tracking` WHERE reference_name = '%s' """ %(doc.amended_from), as_list=1) if not is_exist: create_new_brc_tracking(doc,method) else: exist_brc = frappe.get_doc("BRC MEIS Tracking", is_exist[0][0]) exist_brc.reference_name = doc.name exist_brc.flags.ignore_permissions = True exist_brc.save() frappe.msgprint(("Updated {0}").format(frappe.get_desk_link('BRC MEIS Tracking', exist_brc.name))) else: is_exist = frappe.db.sql("""SELECT name FROM `tabBRC MEIS Tracking` WHERE reference_name = '%s' """ %(doc.name), as_list=1) if not is_exist: create_new_brc_tracking(doc,method)
def get_alert_dict(doc): alert_dict = frappe._dict() owner_name = get_fullname(doc.owner) doc_link = frappe.get_desk_link(doc.reference_doctype, doc.reference_name) points = doc.points bold_points = frappe.bold(doc.points) if doc.type == 'Auto': if points == 1: message = _('You gained {0} point') else: message = _('You gained {0} points') alert_dict.message = message.format(bold_points) alert_dict.indicator = 'green' elif doc.type == 'Appreciation': if points == 1: message = _('{0} appreciated your work on {1} with {2} point') else: message = _('{0} appreciated your work on {1} with {2} points') alert_dict.message = message.format(owner_name, doc_link, bold_points) alert_dict.indicator = 'green' elif doc.type == 'Criticism': if points == 1: message = _('{0} criticized your work on {1} with {2} point') else: message = _('{0} criticized your work on {1} with {2} points') alert_dict.message = message.format(owner_name, doc_link, bold_points) alert_dict.indicator = 'red' elif doc.type == 'Revert': if points == 1: message = _('{0} reverted your point on {1}') else: message = _('{0} reverted your points on {1}') alert_dict.message = message.format( owner_name, doc_link, ) alert_dict.indicator = 'red' return alert_dict
def create_new_communication(created_by, next_action_by, row): comm = frappe.new_doc("Communication") comm.owner = created_by comm.user = next_action_by comm.communication_date = row.communication_date comm.duration = row.duration comm.sender = created_by #add custom field for next_action_date in Communication #add custom field for communication_subtype in Communication if row.no_action_required != 1: comm.follow_up = 1 comm.next_action_date = row.next_action_date #This would add a TODO to USER fields' account on that day comm.communication_subtype = "Sales Related" comm.communication_medium = row.type_of_communication #Change the above Select field by customize form view in Communication comm.communication_type = "Communication" comm.content = row.details if row.document == "Customer": comm.reference_doctype = "Contact" comm.reference_name = row.contact comm.timeline_doctype = row.document comm.timeline_name = row.document_name comm.subject = "Sales Call: " + row.type_of_communication + " To:" + \ row.document + ":" + row.document_name + " Contact:" + row.contact elif row.document == "Lead": comm.reference_doctype = row.document comm.reference_name = row.document_name comm.subject = "Sales Call: " + row.type_of_communication + " To:" + \ row.document + ":" + row.document_name + " Org:" + \ row.lead_organisation_name + " Contact:" + row.lead_contact_name else: frappe.throw("Error Contact [email protected]") comm.insert() frappe.db.set_value('Daily Call Details', row.name, 'communication', comm.name) row.communication = comm.name frappe.msgprint("Created New Communication {}".format( frappe.get_desk_link('Communication', comm.name)))
def create_customer(self): if self.customer: frappe.throw( frappe._("Customer already created for {}".format( frappe.get_desk_link("Booking Party", self.name)))) doc = frappe.get_doc({ "doctype": "Customer", "customer_name": self.booking_party_name, "customer_group": frappe.get_cached_value("Selling Settings", None, "customer_group"), "territory": frappe.get_cached_value("Selling Settings", None, "territory"), "customer_primary_address": self.primary_address, }).insert(ignore_permissions=True, ignore_mandatory=True) for (parent, ) in frappe.get_all( "Dynamic Link", filters={ "parenttype": "Address", "link_doctype": "Booking Party", "link_name": self.name, }, fields=["parent"], as_list=1, ): address = frappe.get_doc("Address", parent) address.append("links", { "link_doctype": doc.doctype, "link_name": doc.name }) address.save(ignore_permissions=True) self.db_set("customer", doc.name) return doc
def validate_negative_qty_in_future_sle(args, allow_negative_stock=False): if allow_negative_stock or is_negative_stock_allowed(item_code=args.item_code): return if not (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation"): return neg_sle = get_future_sle_with_negative_qty(args) if neg_sle: message = _( "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." ).format( abs(neg_sle[0]["qty_after_transaction"]), frappe.get_desk_link("Item", args.item_code), frappe.get_desk_link("Warehouse", args.warehouse), neg_sle[0]["posting_date"], neg_sle[0]["posting_time"], frappe.get_desk_link(neg_sle[0]["voucher_type"], neg_sle[0]["voucher_no"]), ) frappe.throw(message, NegativeStockError, title=_("Insufficient Stock")) if not args.batch_no: return neg_batch_sle = get_future_sle_with_negative_batch_qty(args) if neg_batch_sle: message = _( "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." ).format( abs(neg_batch_sle[0]["cumulative_total"]), frappe.get_desk_link("Batch", args.batch_no), frappe.get_desk_link("Warehouse", args.warehouse), neg_batch_sle[0]["posting_date"], neg_batch_sle[0]["posting_time"], frappe.get_desk_link(neg_batch_sle[0]["voucher_type"], neg_batch_sle[0]["voucher_no"]), ) frappe.throw(message, NegativeStockError, title=_("Insufficient Stock for Batch"))
def validate(self): if self.call_details: for row in self.call_details: if row.communication: frappe.throw('Communication {} already exists for Row# {}'.\ format(frappe.get_desk_link('Communication', row.communication), row.idx)) if row.document == "Customer": if row.document_name: if row.contact: check_contact(row.document, row.document_name, row.contact) else: row.contact = check_contact(row.document, row.document_name, row.contact)[0][0] else: frappe.throw("Customer is Mandatory") elif row.document == "Lead": #Check if Lead is converted if row.document_name: lead = frappe.get_doc("Lead", row.document_name) if not row.lead_status: row.lead_status = lead.status else: if row.lead_status != lead.status: update_lead_status(lead, row.lead_status) row.lead_contact_name = lead.lead_name row.lead_organisation_name = lead.company_name if lead.status == "Converted": customer = frappe.db.sql("""SELECT name FROM `tabCustomer` WHERE lead_name = '%s'""" %(row.document_name), as_list=1) if customer: frappe.throw(("Selected Lead is already converted to {}. \n\ Please select the customer and not this Lead in Row # {}.").\ format(frappe.get_desk_link("Customer", customer[0][0]), \ row.idx)) else: frappe.throw("Selected Lead {} in Row# {} is Marked as Converted. \n\ Either Change the Lead Status or Link it with a Customer. \n\ Since No Customer is Linked to this Lead".\ format(frappe.get_desk_link("Lead", row.document_name), row.idx)) else: frappe.throw("Document Field is Mandatory") if row.communication_date: if self.allow_back_dated_entries == 1: back_dated_days = self.back_dated_days else: back_dated_days = 0 check_date_time_diff(row.communication_date, days_diff=(-1*back_dated_days), \ type_of_check='date', name_of_field = 'Communication') else: frappe.throw("Communication Date is Mandatory") if row.next_action_date: check_date_time_diff(row.next_action_date, hours_diff=1, \ type_of_check= 'time', name_of_field = 'Next Action') if not row.type_of_communication: frappe.throw('Type of Communication is Mandatory') if not row.details: frappe.throw('Details of Communication are Mandatory') if row.no_action_required == 1: #Check only System Managers can do this Entry user = frappe.session.user roles = frappe.db.sql("""SELECT role from `tabUserRole` where parent = '%s' """ \ %user, as_list=1) row.next_action_date = "" else: if not row.next_action_date: frappe.throw("Please add a Next Action Date") else: frappe.throw("Enter Call Details before creating Communications") if self.created_by: pass else: frappe.throw("Mandatory Field Created By") if self.next_action_by: pass else: frappe.throw("Mandatory Field Next Action By")