def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0): actual_expense = amount or get_actual_expense(args) if actual_expense > budget_amount: diff = actual_expense - budget_amount currency = dataent.get_cached_value('Company', args.company, 'default_currency') msg = _( "{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}" ).format(_(action_for), dataent.bold(args.account), args.budget_against_field, dataent.bold(budget_against), dataent.bold(fmt_money(budget_amount, currency=currency)), dataent.bold(fmt_money(diff, currency=currency))) if (dataent.flags.exception_approver_role and dataent.flags.exception_approver_role in dataent.get_roles( dataent.session.user)): action = "Warn" if action == "Stop": dataent.throw(msg, BudgetError) else: dataent.msgprint(msg, indicator='orange')
def convert_to_simple_type(self, v, formatted=0): """Format date, time, longint values.""" return v from dataent.utils import formatdate, fmt_money if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, integer_types)): if isinstance(v, datetime.date): v = text_type(v) if formatted: v = formatdate(v) # time elif isinstance(v, (datetime.timedelta, datetime.datetime)): v = text_type(v) # long elif isinstance(v, integer_types): v = int(v) # convert to strings... (if formatted) if formatted: if isinstance(v, float): v = fmt_money(v) elif isinstance(v, int): v = text_type(v) return v
def test_decimal(self): dataent.db.set_default("number_format", "#.###,##") self.assertEqual(fmt_money(-100), "-100,00") self.assertEqual(fmt_money(-1000), "-1.000,00") self.assertEqual(fmt_money(-10000), "-10.000,00") self.assertEqual(fmt_money(-100000), "-100.000,00") self.assertEqual(fmt_money(-1000000), "-1.000.000,00") self.assertEqual(fmt_money(-10000000), "-10.000.000,00") self.assertEqual(fmt_money(-100000000), "-100.000.000,00") self.assertEqual(fmt_money(-1000000000), "-1.000.000.000,00")
def test_standard(self): dataent.db.set_default("number_format", "#,###.##") self.assertEqual(fmt_money(100), "100.00") self.assertEqual(fmt_money(1000), "1,000.00") self.assertEqual(fmt_money(10000), "10,000.00") self.assertEqual(fmt_money(100000), "100,000.00") self.assertEqual(fmt_money(1000000), "1,000,000.00") self.assertEqual(fmt_money(10000000), "10,000,000.00") self.assertEqual(fmt_money(100000000), "100,000,000.00") self.assertEqual(fmt_money(1000000000), "1,000,000,000.00")
def test_negative(self): dataent.db.set_default("number_format", "#,###.##") self.assertEqual(fmt_money(-100), "-100.00") self.assertEqual(fmt_money(-1000), "-1,000.00") self.assertEqual(fmt_money(-10000), "-10,000.00") self.assertEqual(fmt_money(-100000), "-100,000.00") self.assertEqual(fmt_money(-1000000), "-1,000,000.00") self.assertEqual(fmt_money(-10000000), "-10,000,000.00") self.assertEqual(fmt_money(-100000000), "-100,000,000.00") self.assertEqual(fmt_money(-1000000000), "-1,000,000,000.00")
def test_no_precision(self): dataent.db.set_default("number_format", "#,###") self.assertEqual(fmt_money(0.3), "0") self.assertEqual(fmt_money(100.3), "100") self.assertEqual(fmt_money(1000.3), "1,000") self.assertEqual(fmt_money(10000.3), "10,000") self.assertEqual(fmt_money(-0.3), "0") self.assertEqual(fmt_money(-100.3), "-100") self.assertEqual(fmt_money(-1000.3), "-1,000")
def validate_overlapping_shipping_rule_conditions(self): def overlap_exists_between(num_range1, num_range2): """ num_range1 and num_range2 are two ranges ranges are represented as a tuple e.g. range 100 to 300 is represented as (100, 300) if condition num_range1 = 100 to 300 then condition num_range2 can only be like 50 to 99 or 301 to 400 hence, non-overlapping condition = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2) """ (x1, x2), (y1, y2) = num_range1, num_range2 separate = (x1 <= x2 <= y1 <= y2) or (y1 <= y2 <= x1 <= x2) return (not separate) overlaps = [] for i in range(0, len(self.conditions)): for j in range(i + 1, len(self.conditions)): d1, d2 = self.conditions[i], self.conditions[j] if d1.as_dict() != d2.as_dict(): # in our case, to_value can be zero, hence pass the from_value if so range_a = (d1.from_value, d1.to_value or d1.from_value) range_b = (d2.from_value, d2.to_value or d2.from_value) if overlap_exists_between(range_a, range_b): overlaps.append([d1, d2]) if overlaps: company_currency = epaas.get_company_currency(self.company) msgprint(_("Overlapping conditions found between:")) messages = [] for d1, d2 in overlaps: messages.append( "%s-%s = %s " % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) + _("and") + " %s-%s = %s" % (d2.from_value, d2.to_value, fmt_money(d2.shipping_amount, currency=company_currency))) msgprint("\n".join(messages), raise_exception=OverlappingConditionError)
def test_currency_precision_de_format(self): dataent.db.set_default("currency_precision", "4") dataent.db.set_default("number_format", "#.###,##") self.assertEqual(fmt_money(100), "100,00") self.assertEqual(fmt_money(1000), "1.000,00") self.assertEqual(fmt_money(10000), "10.000,00") self.assertEqual(fmt_money(100000), "100.000,00") self.assertEqual(fmt_money(100.23), "100,23") self.assertEqual(fmt_money(1000.456), "1.000,456") dataent.db.set_default("currency_precision", "")
def get_context(context): context.no_cache = 1 # all these keys exist in form_dict if not (set(expected_keys) - set(list(dataent.form_dict))): for key in expected_keys: context[key] = dataent.form_dict[key] gateway_controller = get_gateway_controller(context.reference_doctype, context.reference_docname) context.publishable_key = get_api_key(context.reference_docname, gateway_controller) context.image = get_header_image(context.reference_docname, gateway_controller) context['amount'] = fmt_money(amount=context['amount'], currency=context['currency']) if dataent.db.get_value(context.reference_doctype, context.reference_docname, "is_a_subscription"): payment_plan = dataent.db.get_value(context.reference_doctype, context.reference_docname, "payment_plan") recurrence = dataent.db.get_value("Payment Plan", payment_plan, "recurrence") context['amount'] = context['amount'] + " " + _(recurrence) else: dataent.redirect_to_message( _('Some information is missing'), _('Looks like someone sent you to an incomplete URL. Please ask them to look into it.' )) dataent.local.flags.redirect_location = dataent.local.response.location raise dataent.Redirect
def get_price(item_code, price_list, customer_group, company, qty=1): template_item_code = dataent.db.get_value("Item", item_code, "variant_of") if price_list: price = dataent.get_all("Item Price", fields=["price_list_rate", "currency"], filters={ "price_list": price_list, "item_code": item_code }) if template_item_code and not price: price = dataent.get_all("Item Price", fields=["price_list_rate", "currency"], filters={ "price_list": price_list, "item_code": template_item_code }) if price: pricing_rule = get_pricing_rule_for_item( dataent._dict({ "item_code": item_code, "qty": qty, "transaction_type": "selling", "price_list": price_list, "customer_group": customer_group, "company": company, "conversion_rate": 1, "for_shopping_cart": True, "currency": dataent.db.get_value("Price List", price_list, "currency") })) if pricing_rule: if pricing_rule.pricing_rule_for == "Discount Percentage": price[0].price_list_rate = flt( price[0].price_list_rate * (1.0 - (flt(pricing_rule.discount_percentage) / 100.0))) if pricing_rule.pricing_rule_for == "Rate": price[0].price_list_rate = pricing_rule.price_list_rate price_obj = price[0] if price_obj: price_obj["formatted_price"] = fmt_money( price_obj["price_list_rate"], currency=price_obj["currency"]) price_obj["currency_symbol"] = not cint(dataent.db.get_default("hide_currency_symbol")) \ and (dataent.db.get_value("Currency", price_obj.currency, "symbol", cache=True) or price_obj.currency) \ or "" uom_conversion_factor = dataent.db.sql( """select C.conversion_factor from `tabUOM Conversion Detail` C inner join `tabItem` I on C.parent = I.name and C.uom = I.sales_uom where I.name = %s""", item_code) uom_conversion_factor = uom_conversion_factor[0][ 0] if uom_conversion_factor else 1 price_obj["formatted_price_sales_uom"] = fmt_money( price_obj["price_list_rate"] * uom_conversion_factor, currency=price_obj["currency"]) if not price_obj["price_list_rate"]: price_obj["price_list_rate"] = 0 if not price_obj["currency"]: price_obj["currency"] = "" if not price_obj["formatted_price"]: price_obj["formatted_price"] = "" return price_obj
def fmt_money(self, value, absol=True): if absol: return fmt_money(abs(value), currency=self.currency) else: return fmt_money(value, currency=self.currency)
def get_payment_entries(self): if not (self.bank_account and self.from_date and self.to_date): msgprint(_("Bank Account, From Date and To Date are Mandatory")) return condition = "" if not self.include_reconciled_entries: condition = "and (clearance_date is null or clearance_date='0000-00-00')" journal_entries = dataent.db.sql(""" select "Journal Entry" as payment_document, t1.name as payment_entry, t1.cheque_no as cheque_number, t1.cheque_date, sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit, t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency from `tabJournal Entry` t1, `tabJournal Entry Account` t2 where t2.parent = t1.name and t2.account = %s and t1.docstatus=1 and t1.posting_date >= %s and t1.posting_date <= %s and ifnull(t1.is_opening, 'No') = 'No' {0} group by t2.account, t1.name order by t1.posting_date ASC, t1.name DESC """.format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1) payment_entries = dataent.db.sql(""" select "Payment Entry" as payment_document, name as payment_entry, reference_no as cheque_number, reference_date as cheque_date, if(paid_from=%(account)s, paid_amount, 0) as credit, if(paid_from=%(account)s, 0, received_amount) as debit, posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date, if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency from `tabPayment Entry` where (paid_from=%(account)s or paid_to=%(account)s) and docstatus=1 and posting_date >= %(from)s and posting_date <= %(to)s {0} order by posting_date ASC, name DESC """.format(condition), { "account": self.bank_account, "from": self.from_date, "to": self.to_date }, as_dict=1) pos_entries = [] if self.include_pos_transactions: pos_entries = dataent.db.sql(""" select "Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit, si.posting_date, si.debit_to as against_account, sip.clearance_date, account.account_currency, 0 as credit from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account where sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s {0} order by si.posting_date ASC, si.name DESC """.format(condition), { "account": self.bank_account, "from": self.from_date, "to": self.to_date }, as_dict=1) entries = sorted(list(payment_entries) + list(journal_entries + list(pos_entries)), key=lambda k: k['posting_date'] or getdate(nowdate())) self.set('payment_entries', []) self.total_amount = 0.0 for d in entries: row = self.append('payment_entries', {}) amount = flt(d.get('debit', 0)) - flt(d.get('credit', 0)) formatted_amount = fmt_money(abs(amount), 2, d.account_currency) d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr")) d.pop("credit") d.pop("debit") d.pop("account_currency") row.update(d) self.total_amount += flt(amount)
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False): if party_type and party: party_condition = " and party_type='{0}' and party='{1}'"\ .format(dataent.db.escape(party_type), dataent.db.escape(party)) else: party_condition = "" # get final outstanding amt bal = flt(dataent.db.sql(""" select sum(debit_in_account_currency) - sum(credit_in_account_currency) from `tabGL Entry` where against_voucher_type=%s and against_voucher=%s and account = %s {0}""".format(party_condition), (against_voucher_type, against_voucher, account))[0][0] or 0.0) if against_voucher_type == 'Purchase Invoice': bal = -bal elif against_voucher_type == "Journal Entry": against_voucher_amount = flt(dataent.db.sql(""" select sum(debit_in_account_currency) - sum(credit_in_account_currency) from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s and account = %s and (against_voucher is null or against_voucher='') {0}""" .format(party_condition), (against_voucher, account))[0][0]) if not against_voucher_amount: dataent.throw(_("Against Journal Entry {0} is already adjusted against some other voucher") .format(against_voucher)) bal = against_voucher_amount + bal if against_voucher_amount < 0: bal = -bal # Validation : Outstanding can not be negative for JV if bal < 0 and not on_cancel: dataent.throw(_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal))) # Update outstanding amt on against voucher if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]: ref_doc = dataent.get_doc(against_voucher_type, against_voucher) ref_doc.db_set('outstanding_amount', bal) ref_doc.set_status(update=True)
def format_value(value, df=None, doc=None, currency=None, translated=False): '''Format value based on given fieldtype, document reference, currency reference. If docfield info (df) is not given, it will try and guess based on the datatype of the value''' if isinstance(df, string_types): df = dataent._dict(fieldtype=df) if not df: df = dataent._dict() if isinstance(value, datetime.datetime): df.fieldtype = 'Datetime' elif isinstance(value, datetime.date): df.fieldtype = 'Date' elif isinstance(value, datetime.timedelta): df.fieldtype = 'Time' elif isinstance(value, int): df.fieldtype = 'Int' elif isinstance(value, float): df.fieldtype = 'Float' else: df.fieldtype = 'Data' elif (isinstance(df, dict)): # Convert dict to object if necessary df = dataent._dict(df) if value is None: value = "" elif translated: value = dataent._(value) if not df: return value elif df.get("fieldtype") == "Date": return formatdate(value) elif df.get("fieldtype") == "Datetime": return format_datetime(value) elif df.get("fieldtype") == "Time": return format_time(value) elif value == 0 and df.get("fieldtype") in ( "Int", "Float", "Currency", "Percent") and df.get("print_hide_if_no_value"): # this is required to show 0 as blank in table columns return "" elif df.get("fieldtype") == "Currency" or (df.get("fieldtype") == "Float" and (df.options or "").strip()): return fmt_money(value, precision=get_field_precision(df, doc), currency=currency if currency else (get_field_currency(df, doc) if doc else None)) elif df.get("fieldtype") == "Float": precision = get_field_precision(df, doc) # show 1.000000 as 1 # options should not specified if not df.options and value is not None: temp = cstr(value).split(".") if len(temp) == 1 or cint(temp[1]) == 0: precision = 0 return fmt_money(value, precision=precision) elif df.get("fieldtype") == "Percent": return "{}%".format(flt(value, 2)) elif df.get("fieldtype") in ("Text", "Small Text"): if not re.search("(\<br|\<div|\<p)", value): return value.replace("\n", "<br>") return value
def test_currency_precision(self): dataent.db.set_default("currency_precision", "4") dataent.db.set_default("number_format", "#,###.##") self.assertEqual(fmt_money(100), "100.00") self.assertEqual(fmt_money(1000), "1,000.00") self.assertEqual(fmt_money(10000), "10,000.00") self.assertEqual(fmt_money(100000), "100,000.00") self.assertEqual(fmt_money(1000000), "1,000,000.00") self.assertEqual(fmt_money(10000000), "10,000,000.00") self.assertEqual(fmt_money(100000000), "100,000,000.00") self.assertEqual(fmt_money(1000000000), "1,000,000,000.00") self.assertEqual(fmt_money(100.23), "100.23") self.assertEqual(fmt_money(1000.456), "1,000.456") self.assertEqual(fmt_money(10000.7890), "10,000.789") self.assertEqual(fmt_money(100000.1234), "100,000.1234") self.assertEqual(fmt_money(1000000.3456), "1,000,000.3456") self.assertEqual(fmt_money(10000000.3344567), "10,000,000.3345") self.assertEqual(fmt_money(100000000.37827268), "100,000,000.3783") self.assertEqual(fmt_money(1000000000.2718272637), "1,000,000,000.2718") dataent.db.set_default("currency_precision", "")