def remove_items_with_no_change(self):
        """Remove items if qty or rate is not changed"""
        self.difference_amount = 0.0

        def _changed(item):
            qty, rate = get_stock_balance(
                item.item_code, item.warehouse, self.posting_date, self.posting_time, with_valuation_rate=True
            )
            if (item.qty == None or item.qty == qty) and (item.valuation_rate == None or item.valuation_rate == rate):
                return False
            else:
                item.current_qty = qty
                item.current_valuation_rate = rate
                self.difference_amount += flt(item.qty or qty) * flt(item.valuation_rate or rate) - (
                    flt(qty) * flt(rate)
                )
                return True

        items = filter(lambda d: _changed(d), self.items)

        if not items:
            frappe.throw(
                _("None of the items have any change in quantity or value."), EmptyStockReconciliationItemsError
            )

        elif len(items) != len(self.items):
            self.items = items
            for i, item in enumerate(self.items):
                item.idx = i + 1
            frappe.msgprint(_("Removed items with no change in quantity or value."))
Example #2
0
 def set_transfer_qty(self):
     for item in self.get("items"):
         if not flt(item.qty):
             frappe.throw(_("Row {0}: Qty is mandatory").format(item.idx))
         if not flt(item.conversion_factor):
             frappe.throw(_("Row {0}: UOM Conversion Factor is mandatory").format(item.idx))
         item.transfer_qty = flt(item.qty * item.conversion_factor, self.precision("transfer_qty", item))
Example #3
0
    def validate_journal_entry(self):
        for d in self.get("references"):
            if d.allocated_amount and d.reference_doctype == "Journal Entry":
                je_accounts = frappe.db.sql(
                    """select debit, credit from `tabJournal Entry Account`
					where account = %s and party=%s and docstatus = 1 and parent = %s
					and (reference_type is null or reference_type in ("", "Sales Order", "Purchase Order"))
					""",
                    (self.party_account, self.party, d.reference_name),
                    as_dict=True,
                )

                if not je_accounts:
                    frappe.throw(
                        _(
                            "Row #{0}: Journal Entry {1} does not have account {2} or already matched against another voucher"
                        ).format(d.idx, d.reference_name, self.party_account)
                    )
                else:
                    dr_or_cr = "debit" if self.payment_type == "Receive" else "credit"
                    valid = False
                    for jvd in je_accounts:
                        if flt(jvd[dr_or_cr]) > 0:
                            valid = True
                    if not valid:
                        frappe.throw(
                            _("Against Journal Entry {0} does not have any unmatched {1} entry").format(
                                d.reference_name, dr_or_cr
                            )
                        )
Example #4
0
    def check_prev_docstatus(self):
        for d in self.get("items"):
            if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
                frappe.throw(_("Sales Order {0} is not submitted").format(d.sales_order))

            if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
                throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
Example #5
0
    def validate_date(self):
        if self.date_of_birth and getdate(self.date_of_birth) > getdate(today()):
            throw(_("Date of Birth cannot be greater than today."))

        if self.date_of_birth and self.date_of_joining and getdate(self.date_of_birth) >= getdate(self.date_of_joining):
            throw(_("Date of Joining must be greater than Date of Birth"))

        elif (
            self.date_of_retirement
            and self.date_of_joining
            and (getdate(self.date_of_retirement) <= getdate(self.date_of_joining))
        ):
            throw(_("Date Of Retirement must be greater than Date of Joining"))

        elif (
            self.relieving_date
            and self.date_of_joining
            and (getdate(self.relieving_date) <= getdate(self.date_of_joining))
        ):
            throw(_("Relieving Date must be greater than Date of Joining"))

        elif (
            self.contract_end_date
            and self.date_of_joining
            and (getdate(self.contract_end_date) <= getdate(self.date_of_joining))
        ):
            throw(_("Contract End Date must be greater than Date of Joining"))
Example #6
0
def get_expiry_message():
    if "System Manager" not in frappe.get_roles():
        return ""

    limits = get_limits()
    if not limits.expiry:
        return ""

    expires_on = getdate(get_limits().get("expiry"))
    today = now_datetime().date()

    message = ""
    if today > expires_on:
        message = _("Your subscription has expired.")
    else:
        days_to_expiry = (expires_on - today).days

        if days_to_expiry == 0:
            message = _("Your subscription will expire today.")

        elif days_to_expiry == 1:
            message = _("Your subscription will expire tomorrow.")

        elif days_to_expiry <= EXPIRY_WARNING_DAYS:
            message = _("Your subscription will expire on {0}.").format(formatdate(expires_on))

    if message and limits.upgrade_url:
        upgrade_link = get_upgrade_link(limits.upgrade_url)
        message += " " + _("To renew, {0}.").format(upgrade_link)

    return message
Example #7
0
def get_data():
    return [
        {
            "label": _("Banking and Payments"),
            "items": [
                {"type": "doctype", "name": "Receipts", "description": _("Formal Receipts for Payments Received")},
                {"type": "doctype", "name": "Payments", "description": _("Tool to Make Payments.")},
            ],
        },
        {
            "label": _("Standard Reports"),
            "items": [
                {
                    "type": "report",
                    "doctype": "Sales Invoice",
                    "is_query_report": True,
                    "name": "Finance Outstanding",
                    "description": "Shows Finance Outstanding",
                },
                {
                    "type": "report",
                    "doctype": "Sales Invoice",
                    "is_query_report": True,
                    "name": "Sales Taxes Report",
                    "description": "Generates a Report for Different Sales Taxes",
                },
            ],
        },
    ]
def send_sms1(numbers, msg, user):
    import math

    num = json.loads(numbers)
    i = datetime.datetime.now()
    today = datetime.date.today()
    if msg:
        counter = frappe.db.sql("select sms_credits from `tabUser` where name='%s'" % (user), as_list=1)
        sms_len = math.ceil(len(msg) / 160.0)
        count = len(num) * cint(sms_len)
        if counter and count <= cint(counter[0][0]):
            credit_count = counter[0][0] - count
            send_sms(num, cstr(msg))
            log = frappe.new_doc("SMS Log")
            log.sender_name = user
            log.sent_on = today
            log.receiver_list = numbers
            log.message = msg
            log.sms_sending_status = "SMS Sent Successfully"
            log.insert()
            frappe.db.sql("update `tabUser` set sms_credits='%s' where name='%s'" % (credit_count, user))
            frappe.db.commit()
            frappe.msgprint(_("SMS Sent Successfully..."))
        else:
            log = frappe.new_doc("SMS Log")
            log.sender_name = user
            log.sent_on = today
            log.receiver_list = numbers
            log.message = msg
            log.sms_sending_status = "Sending Fail"
            log.insert(ignore_permissions=True)
            frappe.db.commit()
            frappe.throw(_("SMS credit is not available for sending SMS, Sending fail..!"))
    else:
        frappe.throw(_("Message should not be blank,Please enter text message..."))
    def validate_website_image(self):
        """Validate if the website image is a public file"""
        auto_set_website_image = False
        if not self.website_image and self.image:
            auto_set_website_image = True
            self.website_image = self.image

        if not self.website_image:
            return

            # find if website image url exists as public
        file = frappe.get_all(
            "File",
            filters={"file_url": self.website_image},
            fields=["name", "is_private"],
            order_by="is_private asc",
            limit_page_length=1,
        )

        if file:
            file = file[0]

        if not file:
            if not auto_set_website_image:
                frappe.msgprint(
                    _("Website Image {0} attached to Item {1} cannot be found").format(self.website_image, self.name)
                )

            self.website_image = None

        elif file.is_private:
            if not auto_set_website_image:
                frappe.msgprint(_("Website Image should be a public file or website URL"))

            self.website_image = None
def clear_all_jasper_user_cache_v4(force=True):
    from memcache_stats import MemcachedStats

    removed = 0
    # use memcache_stats for delete any cache that remains
    memc = MemcachedStats()
    for m in memc.keys():
        if "jasper:user" in m:
            if force:
                # remove site from key
                value = m.split(":", 1)
                frappe.cache().delete_value(value[1])
                removed += 1
            else:
                # remove jasper from key
                value = m.split(":", 1)
                v = value[1].split(":", 1)
                deleted = check_if_expire(v[1])
                if deleted:
                    frappe.cache().delete_value(value[1])
                    removed += 1
    if removed == 0:
        print _("No user cache was removed.")
    else:
        print _("Was removed {0} user cache(s)".format(removed))
    return removed
Example #11
0
    def _validate_selects(self):
        if frappe.flags.in_import:
            return

        for df in self.meta.get_select_fields():
            if df.fieldname == "naming_series" or not (self.get(df.fieldname) and df.options):
                continue

            options = (df.options or "").split("\n")

            # if only empty options
            if not filter(None, options):
                continue

                # strip and set
            self.set(df.fieldname, cstr(self.get(df.fieldname)).strip())
            value = self.get(df.fieldname)

            if value not in options and not (frappe.flags.in_test and value.startswith("_T-")):
                # show an elaborate message
                prefix = _("Row #{0}:").format(self.idx) if self.get("parentfield") else ""
                label = _(self.meta.get_label(df.fieldname))
                comma_options = '", "'.join(_(each) for each in options)

                frappe.throw(
                    _('{0} {1} cannot be "{2}". It should be one of "{3}"').format(prefix, label, value, comma_options)
                )
Example #12
0
def get_list_context(context=None):
    from erpnext.controllers.website_list_for_contact import get_list_context

    list_context = get_list_context(context)
    list_context["title"] = _("My Orders")
    list_context["parents"] = [{"title": _("My Account"), "name": "me"}]
    return list_context
Example #13
0
def check_record(d):
    """check for mandatory, select options, dates. these should ideally be in doclist"""
    from frappe.utils.dateutils import parse_date

    doc = frappe.get_doc(d)

    for key in d:
        docfield = doc.meta.get_field(key)
        val = d[key]
        if docfield:
            if docfield.reqd and (val == "" or val == None):
                frappe.msgprint(_("{0} is required").format(docfield.label), raise_exception=1)

            if docfield.fieldtype == "Select" and val and docfield.options:
                if val not in docfield.options.split("\n"):
                    frappe.throw(
                        _("{0} must be one of {1}").format(_(docfield.label), comma_or(docfield.options.split("\n")))
                    )

            if val and docfield.fieldtype == "Date":
                d[key] = parse_date(val)
            elif val and docfield.fieldtype in ["Int", "Check"]:
                d[key] = cint(val)
            elif val and docfield.fieldtype in ["Currency", "Float", "Percent"]:
                d[key] = flt(val)
def make_round_off_gle(gl_map, debit_credit_diff):
    round_off_account, round_off_cost_center = frappe.db.get_value(
        "Company", gl_map[0].company, ["round_off_account", "round_off_cost_center"]
    ) or [None, None]
    if not round_off_account:
        frappe.throw(_("Please mention Round Off Account in Company"))

    if not round_off_cost_center:
        frappe.throw(_("Please mention Round Off Cost Center in Company"))

    round_off_gle = frappe._dict()
    for k in ["voucher_type", "voucher_no", "company", "posting_date", "remarks", "fiscal_year", "is_opening"]:
        round_off_gle[k] = gl_map[0][k]

    round_off_gle.update(
        {
            "account": round_off_account,
            "debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
            "credit": debit_credit_diff if debit_credit_diff > 0 else 0,
            "cost_center": round_off_cost_center,
            "party_type": None,
            "party": None,
            "against_voucher_type": None,
            "against_voucher": None,
        }
    )

    gl_map.append(round_off_gle)
Example #15
0
    def sync_variants(self):
        variant_item_codes = self.get_variant_item_codes()

        # delete missing variants
        existing_variants = [d.name for d in frappe.get_all("Item", filters={"variant_of": self.name})]

        updated, deleted = [], []
        for existing_variant in existing_variants:
            if existing_variant not in variant_item_codes:
                frappe.delete_doc("Item", existing_variant)
                deleted.append(existing_variant)
            else:
                self.update_variant(existing_variant)
                updated.append(existing_variant)

        inserted = []
        for item_code in variant_item_codes:
            if item_code not in existing_variants:
                self.make_variant(item_code)
                inserted.append(item_code)

        if inserted:
            frappe.msgprint(_("Item Variants {0} created").format(", ".join(inserted)))

        if updated:
            frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))

        if deleted:
            frappe.msgprint(_("Item Variants {0} deleted").format(", ".join(deleted)))
Example #16
0
def build_standard_config(module):
    if not frappe.db.get_value("Module Def", module):
        frappe.throw(_("Module Not Found"))

    data = []

    doctypes = frappe.db.sql(
        """select "doctype" as type, name, description,
		ifnull(document_type, "") as document_type
		from `tabDocType` where module=%s and ifnull(istable, 0)=0
		order by document_type desc, name asc""",
        module,
        as_dict=True,
    )

    documents = [d for d in doctypes if d.document_type in ("Transaction", "Master", "")]
    if documents:
        data.append({"label": _("Documents"), "icon": "icon-star", "items": documents})

    setup = [d for d in doctypes if d.document_type in ("System", "Other")]
    if setup:
        data.append({"label": _("Setup"), "icon": "icon-cog", "items": setup})

    reports = get_report_list(module, is_standard="Yes")
    if reports:
        data.append({"label": _("Standard Reports"), "icon": "icon-list", "items": reports})

    return data
Example #17
0
def validate_space_limit(file_size):
    """Stop from writing file if max space limit is reached"""
    from frappe.utils.file_manager import MaxFileSizeReachedError

    limits = get_limits()
    if not limits.space:
        return

        # to MB
    space_limit = flt(limits.space * 1024.0, 2)

    # in MB
    usage = frappe._dict(limits.space_usage or {})
    if not usage:
        # first time
        usage = frappe._dict(update_space_usage())

    file_size = file_size / (1024.0 ** 2)

    if flt(flt(usage.total) + file_size, 2) > space_limit:
        # Stop from attaching file
        frappe.throw(
            _("You have exceeded the max space of {0} for your plan. {1}.").format(
                "<b>{0}MB</b>".format(cint(space_limit))
                if (space_limit < 1024)
                else "<b>{0}GB</b>".format(limits.space),
                '<a href="#usage-info">{0}</a>'.format(_("Click here to check your usage or upgrade to a higher plan")),
            ),
            MaxFileSizeReachedError,
        )

        # update files size in frappe subscription
    usage.files_size = flt(usage.files_size) + file_size
    update_limits({"space_usage": usage})
Example #18
0
    def validate_supplier_invoice(self):
        if self.bill_date:
            if getdate(self.bill_date) > getdate(self.posting_date):
                frappe.throw(_("Supplier Invoice Date cannot be greater than Posting Date"))

        if self.bill_no:
            if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
                fiscal_year = get_fiscal_year(self.posting_date, company=self.company, as_dict=True)

                pi = frappe.db.sql(
                    """select name from `tabPurchase Invoice`
					where
						bill_no = %(bill_no)s
						and name != %(name)s
						and docstatus < 2
						and posting_date between %(year_start_date)s and %(year_end_date)s""",
                    {
                        "bill_no": self.bill_no,
                        "name": self.name,
                        "year_start_date": fiscal_year.year_start_date,
                        "year_end_date": fiscal_year.year_end_date,
                    },
                )

                if pi:
                    pi = pi[0][0]
                    frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}".format(pi)))
Example #19
0
    def validate_purchase_order(self):
        """Throw exception if more raw material is transferred against Purchase Order than in
		the raw materials supplied table"""
        if self.purpose == "Subcontract" and self.purchase_order:
            purchase_order = frappe.get_doc("Purchase Order", self.purchase_order)
            for se_item in self.items:
                total_allowed = sum(
                    [flt(d.required_qty) for d in purchase_order.supplied_items if d.rm_item_code == se_item.item_code]
                )
                if not total_allowed:
                    frappe.throw(
                        _("Item {0} not found in 'Raw Materials Supplied' table in Purchase Order {1}").format(
                            se_item.item_code, self.purchase_order
                        )
                    )
                total_supplied = frappe.db.sql(
                    """select sum(qty)
					from `tabStock Entry Detail`, `tabStock Entry`
					where `tabStock Entry`.purchase_order = %s
						and `tabStock Entry`.docstatus = 1
						and `tabStock Entry Detail`.item_code = %s
						and `tabStock Entry Detail`.parent = `tabStock Entry`.name""",
                    (self.purchase_order, se_item.item_code),
                )[0][0]

                if total_supplied > total_allowed:
                    frappe.throw(
                        _("Not allowed to tranfer more {0} than {1} against Purchase Order {2}").format(
                            se_item.item_code, total_allowed, self.purchase_order
                        )
                    )
Example #20
0
    def get_pending_raw_materials(self, pro_obj):
        """
			issue (item quantity) that is pending to issue or desire to transfer,
			whichever is less
		"""
        item_dict = self.get_bom_raw_materials(1)
        issued_item_qty = self.get_issued_qty()

        max_qty = flt(pro_obj.qty)
        only_pending_fetched = []

        for item in item_dict:
            pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
            desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]
            if desire_to_transfer <= pending_to_issue:
                item_dict[item]["qty"] = desire_to_transfer
            else:
                item_dict[item]["qty"] = pending_to_issue
                if pending_to_issue:
                    only_pending_fetched.append(item)

                    # delete items with 0 qty
        for item in item_dict.keys():
            if not item_dict[item]["qty"]:
                del item_dict[item]

                # show some message
        if not len(item_dict):
            frappe.msgprint(_("""All items have already been transferred for this Production Order."""))

        elif only_pending_fetched:
            frappe.msgprint(_("Pending Items {0} updated").format(only_pending_fetched))

        return item_dict
Example #21
0
def send(email, append_to=None):
    """send the message or add it to Outbox Email"""
    if frappe.flags.in_test:
        frappe.flags.sent_mail = email.as_string()
        return

    if frappe.are_emails_muted():
        frappe.msgprint(_("Emails are muted"))
        return

    try:
        smtpserver = SMTPServer(append_to=append_to)
        if (
            hasattr(smtpserver, "always_use_account_email_id_as_sender")
            and cint(smtpserver.always_use_account_email_id_as_sender)
            and smtpserver.login
        ):
            if not email.reply_to:
                email.reply_to = email.sender
            email.sender = smtpserver.login

        smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []), email.as_string())

    except smtplib.SMTPSenderRefused:
        frappe.msgprint(_("Invalid login or password"))
        raise
    except smtplib.SMTPRecipientsRefused:
        frappe.msgprint(_("Invalid recipient address"))
        raise
Example #22
0
    def validate(self):
        """Validate DocType before saving.

		- Check if developer mode is set.
		- Validate series
		- Check fieldnames (duplication etc)
		- Clear permission table for child tables
		- Add `amended_from` and `ameneded_by` if Amendable"""
        if not frappe.conf.get("developer_mode") and not self.custom:
            frappe.throw(_("Not in Developer Mode! Set in site_config.json or make 'Custom' DocType."))
        for c in [".", "/", "#", "&", "=", ":", "'", '"']:
            if c in self.name:
                frappe.throw(_("{0} not allowed in name").format(c))
        self.validate_series()
        self.scrub_field_names()
        self.validate_title_field()
        validate_fields(self)

        if self.istable:
            # no permission records for child table
            self.permissions = []
        else:
            validate_permissions(self)

        self.make_amendable()
Example #23
0
def accept():
    args = frappe.form_dict
    files = []

    web_form = frappe.get_doc("Web Form", args.web_form)
    if args.doctype != web_form.doc_type:
        frappe.throw(_("Invalid Request"))

    if args.name:
        # update
        doc = frappe.get_doc(args.doctype, args.name)
    else:
        # insert
        doc = frappe.new_doc(args.doctype)

        # set values
    for fieldname, value in args.iteritems():
        if fieldname not in ("web_form", "cmd", "owner"):
            if value and value.startswith("{"):
                try:
                    filedata = json.loads(value)
                    if "__file_attachment" in filedata:
                        files.append((fieldname, filedata))
                        continue

                except ValueError:
                    pass

            doc.set(fieldname, value)

    if args.name:
        if doc.owner == frappe.session.user:
            doc.save(ignore_permissions=True)
        else:
            # only if permissions are present
            doc.save()

    else:
        # insert
        if web_form.login_required and frappe.session.user == "Guest":
            frappe.throw(_("You must login to submit this form"))

        doc.insert(ignore_permissions=True)

        # add files
    if files:
        for f in files:
            fieldname, filedata = f

            # remove earlier attachmed file (if exists)
            if doc.get(fieldname):
                remove_file_by_url(doc.get(fieldname), doc.doctype, doc.name)

                # save new file
            filedoc = save_file(filedata["filename"], filedata["dataurl"], doc.doctype, doc.name, decode=True)

            # update values
            doc.set(fieldname, filedoc.file_url)

        doc.save()
Example #24
0
    def set_actual_qty(self):
        allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))

        for d in self.get("items"):
            previous_sle = get_previous_sle(
                {
                    "item_code": d.item_code,
                    "warehouse": d.s_warehouse or d.t_warehouse,
                    "posting_date": self.posting_date,
                    "posting_time": self.posting_time,
                }
            )

            # get actual stock at source warehouse
            d.actual_qty = previous_sle.get("qty_after_transaction") or 0

            # validate qty during submit
            if d.docstatus == 1 and d.s_warehouse and not allow_negative_stock and d.actual_qty < d.transfer_qty:
                frappe.throw(
                    _(
                        "Row {0}: Qty not available for {4} in warehouse {1} at posting time of the entry ({2} {3})".format(
                            d.idx,
                            frappe.bold(d.s_warehouse),
                            formatdate(self.posting_date),
                            format_time(self.posting_time),
                            frappe.bold(d.item_code),
                        )
                    )
                    + "<br><br>"
                    + _("Available qty is {0}, you need {1}").format(
                        frappe.bold(d.actual_qty), frappe.bold(d.transfer_qty)
                    ),
                    NegativeStockError,
                    title=_("Insufficient Stock"),
                )
Example #25
0
    def get_gl_entries(self, warehouse_account):
        expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")

        gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)

        for d in self.get("items"):
            additional_cost = flt(d.additional_cost, d.precision("additional_cost"))
            if additional_cost:
                gl_entries.append(
                    self.get_gl_dict(
                        {
                            "account": expenses_included_in_valuation,
                            "against": d.expense_account,
                            "cost_center": d.cost_center,
                            "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
                            "credit": additional_cost,
                        }
                    )
                )

                gl_entries.append(
                    self.get_gl_dict(
                        {
                            "account": d.expense_account,
                            "against": expenses_included_in_valuation,
                            "cost_center": d.cost_center,
                            "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
                            "credit": -1 * additional_cost,  # put it as negative credit instead of debit purposefully
                        }
                    )
                )

        return gl_entries
Example #26
0
def file_upload():
    # only administrator can upload reports!!
    comment = ""
    dt = frappe.form_dict.doctype
    dn = frappe.form_dict.docname
    parent = frappe.form_dict.parent_report
    filename = frappe.form_dict.filename

    if not filename:
        frappe.msgprint(_("Please select a file."), raise_exception=True)

    filedata = save_uploaded(dn, parent)

    if dt and dn:
        comment = frappe.get_doc(dt, dn).add_comment(
            "Attachment",
            _("Added {0}").format("<a href='{file_url}' target='_blank'>{file_name}</a>".format(**filedata.as_dict())),
        )

    return {
        "name": filedata.name,
        "file_name": filedata.file_name,
        "file_url": "".join(filedata.file_url.split("/files")[-1]),
        "parent_report": parent,
        "comment": comment.as_dict(),
    }
Example #27
0
def send_mail(mail, sender):
    if sender:
        mail_config = frappe.db.get_value("Email Config", {"email_id": sender}, "name")
        server_details = frappe.get_doc("Email Config", mail_config)

        try:
            smtpserver = SMTPServer(
                login=server_details.email_id,
                password=server_details.password,
                server=server_details.smtp_server,
                port=587,
                use_ssl=1,
                append_to=None,
            )

            mail.sender = smtpserver.login

            smtpserver.sess.sendmail(mail.sender, mail.recipients + (mail.cc or []), mail.as_string())

        except smtplib.SMTPSenderRefused:
            frappe.msgprint(_("Invalid login or password"))
            raise
        except smtplib.SMTPRecipientsRefused:
            frappe.msgprint(_("Invalid recipient address"))
            raise
    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"))
Example #29
0
    def validate_payment_against_negative_invoice(self):
        if (self.payment_type == "Pay" and self.party_type == "Customer") or (
            self.payment_type == "Receive" and self.party_type == "Supplier"
        ):

            total_negative_outstanding = sum(
                [abs(flt(d.outstanding_amount)) for d in self.get("references") if flt(d.outstanding_amount) < 0]
            )

            party_amount = self.paid_amount if self.payment_type == "Receive" else self.received_amount

            if not total_negative_outstanding:
                frappe.throw(
                    _("Cannot {0} {1} {2} without any negative outstanding invoice").format(
                        self.payment_type, ("to" if self.party_type == "Customer" else "from"), self.party_type
                    ),
                    InvalidPaymentEntry,
                )

            elif party_amount > total_negative_outstanding:
                frappe.throw(
                    _("Paid Amount cannot be greater than total negative outstanding amount {0}").format(
                        total_negative_outstanding
                    ),
                    InvalidPaymentEntry,
                )
    def validate_item(self, item_code, row_num):
        from erpnext.stock.doctype.item.item import (
            validate_end_of_life,
            validate_is_stock_item,
            validate_cancelled_item,
        )

        # using try except to catch all validation msgs and display together

        try:
            item = frappe.get_doc("Item", item_code)

            # end of life and stock item
            validate_end_of_life(item_code, item.end_of_life, item.disabled, verbose=0)
            validate_is_stock_item(item_code, item.is_stock_item, verbose=0)

            # item should not be serialized
            if item.has_serial_no == 1:
                raise frappe.ValidationError, _(
                    "Serialized Item {0} cannot be updated \
					using Stock Reconciliation"
                ).format(item_code)

                # item managed batch-wise not allowed
            if item.has_batch_no == 1:
                raise frappe.ValidationError, _(
                    "Item: {0} managed batch-wise, can not be reconciled using \
					Stock Reconciliation, instead use Stock Entry"
                ).format(item_code)

                # docstatus should be < 2
            validate_cancelled_item(item_code, item.docstatus, verbose=0)

        except Exception, e:
            self.validation_messages.append(_("Row # ") + ("%d: " % (row_num)) + cstr(e))