def test_purchase_order_creation(self): bo = make_blanket_order(blanket_order_type="Purchasing") frappe.flags.args.doctype = 'Purchase Order' po = make_order(bo.name) po.currency = get_company_currency(po.company) po.schedule_date = today() po.items[0].qty = 10 po.submit() self.assertEqual(po.doctype, "Purchase Order") self.assertEqual(len(po.get("items")), len(bo.get("items"))) # check the rate, quantity and updation for the ordered quantity self.assertEqual(po.items[0].rate, po.items[0].rate) bo = frappe.get_doc("Blanket Order", bo.name) self.assertEqual(po.items[0].qty, bo.items[0].ordered_qty) # test the quantity frappe.flags.args.doctype = 'Purchase Order' po1 = make_order(bo.name) po1.currency = get_company_currency(po1.company) self.assertEqual(po1.items[0].qty, (bo.items[0].qty - bo.items[0].ordered_qty))
def test_sales_order_creation(self): bo = make_blanket_order(blanket_order_type="Selling") frappe.flags.args.doctype = 'Sales Order' so = make_order(bo.name) so.currency = get_company_currency(so.company) so.delivery_date = today() so.items[0].qty = 10 so.submit() self.assertEqual(so.doctype, "Sales Order") self.assertEqual(len(so.get("items")), len(bo.get("items"))) # check the rate, quantity and updation for the ordered quantity self.assertEqual(so.items[0].rate, bo.items[0].rate) bo = frappe.get_doc("Blanket Order", bo.name) self.assertEqual(so.items[0].qty, bo.items[0].ordered_qty) # test the quantity frappe.flags.args.doctype = 'Sales Order' so1 = make_order(bo.name) so1.currency = get_company_currency(so1.company) self.assertEqual(so1.items[0].qty, (bo.items[0].qty - bo.items[0].ordered_qty))
def get_incoming_rate(args, raise_error_if_no_rate=True): """Get Incoming Rate based on valuation method""" from erpbee.stock.stock_ledger import get_previous_sle, get_valuation_rate if isinstance(args, string_types): args = json.loads(args) in_rate = 0 if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) else: valuation_method = get_valuation_method(args.get("item_code")) previous_sle = get_previous_sle(args) if valuation_method == 'FIFO': if previous_sle: previous_stock_queue = json.loads( previous_sle.get('stock_queue', '[]') or '[]') in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0 elif valuation_method == 'Moving Average': in_rate = previous_sle.get('valuation_rate') or 0 if not in_rate: voucher_no = args.get('voucher_no') or args.get('name') in_rate = get_valuation_rate( args.get('item_code'), args.get('warehouse'), args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'), currency=erpbee.get_company_currency(args.get('company')), company=args.get('company'), raise_error_if_no_rate=raise_error_if_no_rate) return flt(in_rate)
def get_currency(filters): """ Returns a dictionary containing currency information. The keys of the dict are - company: The company for which we are fetching currency information. if no company is specified, it will fallback to the default company. - company currency: The functional currency of the said company. - presentation currency: The presentation currency to use. Only currencies that have been used for transactions will be allowed. - report date: The report date. :param filters: Report filters :type filters: dict :return: str - Currency """ company = get_appropriate_company(filters) company_currency = get_company_currency(company) presentation_currency = filters['presentation_currency'] if filters.get( 'presentation_currency') else company_currency report_date = filters.get('to_date') if not report_date: fiscal_year_to_date = get_from_and_to_date( filters.get('to_fiscal_year'))["to_date"] report_date = formatdate(get_datetime_str(fiscal_year_to_date), "dd-MM-yyyy") currency_map = dict(company=company, company_currency=company_currency, presentation_currency=presentation_currency, report_date=report_date) return currency_map
def get_accounts_from_gle(self): company_currency = erpbee.get_company_currency(self.company) accounts = frappe.db.sql_list( """ select name from tabAccount where is_group = 0 and report_type = 'Balance Sheet' and root_type in ('Asset', 'Liability', 'Equity') and account_type != 'Stock' and company=%s and account_currency != %s order by name""", (self.company, company_currency)) account_details = [] if accounts: account_details = frappe.db.sql(""" select account, party_type, party, account_currency, sum(debit_in_account_currency) - sum(credit_in_account_currency) as balance_in_account_currency, sum(debit) - sum(credit) as balance from `tabGL Entry` where account in (%s) group by account, party_type, party having sum(debit) != sum(credit) order by account """ % ', '.join(['%s'] * len(accounts)), tuple(accounts), as_dict=1) return account_details
def _execute(filters=None): if not filters: filters = {} columns = get_columns() company_currency = erpbee.get_company_currency(filters.company) item_list = get_items(filters) if item_list: itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency) data = [] added_item = [] for d in item_list: if (d.parent, d.item_code) not in added_item: row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty] total_tax = 0 for tax in tax_columns: item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) total_tax += flt(item_tax.get("tax_amount", 0)) row += [d.base_net_amount + total_tax] row += [d.base_net_amount] for tax in tax_columns: item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) row += [item_tax.get("tax_amount", 0)] data.append(row) added_item.append((d.parent, d.item_code)) if data: data = get_merged_data(columns, data) # merge same hsn code data return columns, data
def update_against_account(voucher_type, voucher_no): entries = frappe.db.get_all("GL Entry", filters={ "voucher_type": voucher_type, "voucher_no": voucher_no }, fields=[ "name", "party", "against", "debit", "credit", "account", "company" ]) if not entries: return company_currency = erpbee.get_company_currency(entries[0].company) precision = get_field_precision( frappe.get_meta("GL Entry").get_field("debit"), company_currency) accounts_debited, accounts_credited = [], [] for d in entries: if flt(d.debit, precision) > 0: accounts_debited.append(d.party or d.account) if flt(d.credit, precision) > 0: accounts_credited.append(d.party or d.account) for d in entries: if flt(d.debit, precision) > 0: new_against = ", ".join(list(set(accounts_credited))) if flt(d.credit, precision) > 0: new_against = ", ".join(list(set(accounts_debited))) if d.against != new_against: frappe.db.set_value("GL Entry", d.name, "against", new_against)
def execute(filters=None): if not filters: filters = {} columns = get_columns(filters) entries = get_entries(filters) item_details = get_item_details() data = [] company_currency = get_company_currency(filters.get("company")) for d in entries: if d.stock_qty > 0 or filters.get('show_return_entries', 0): data.append([ d.name, d.customer, d.territory, d.warehouse, d.posting_date, d.item_code, item_details.get(d.item_code, {}).get("item_group"), item_details.get(d.item_code, {}).get("brand"), d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt, company_currency ]) if data: total_row = [""] * len(data[0]) data.append(total_row) return columns, data
def merge_similar_entries(gl_map): merged_gl_map = [] accounting_dimensions = get_accounting_dimensions() for entry in gl_map: # if there is already an entry in this account then just add it # to that entry same_head = check_if_in_list(entry, merged_gl_map, accounting_dimensions) if same_head: same_head.debit = flt(same_head.debit) + flt(entry.debit) same_head.debit_in_account_currency = \ flt(same_head.debit_in_account_currency) + flt(entry.debit_in_account_currency) same_head.credit = flt(same_head.credit) + flt(entry.credit) same_head.credit_in_account_currency = \ flt(same_head.credit_in_account_currency) + flt(entry.credit_in_account_currency) else: merged_gl_map.append(entry) company = gl_map[0].company if gl_map else erpbee.get_default_company() company_currency = erpbee.get_company_currency(company) precision = get_field_precision( frappe.get_meta("GL Entry").get_field("debit"), company_currency) # filter zero debit and credit entries merged_gl_map = filter( lambda x: flt(x.debit, precision) != 0 or flt(x.credit, precision) != 0, merged_gl_map) merged_gl_map = list(merged_gl_map) return merged_gl_map
def get_data(filters, mode_of_payments): data = [] conditions = get_conditions(filters) entry = frappe.db.sql(""" select branch, mode_of_payment, sum(net_pay) as net_pay, sum(gross_pay) as gross_pay from `tabSalary Slip` sal where docstatus = 1 %s group by branch, mode_of_payment """ % (conditions), as_dict=1) branch_wise_entries, gross_pay = prepare_data(entry) branches = frappe.db.sql_list(""" select distinct branch from `tabSalary Slip` sal where docstatus = 1 %s """ % (conditions)) total_row = {"total": 0, "branch": "Total"} for branch in branches: total = 0 row = { "branch": branch } for mode in mode_of_payments: if branch_wise_entries.get(branch).get(mode): row[mode] = branch_wise_entries.get(branch).get(mode) total += branch_wise_entries.get(branch).get(mode) row["total"] = total data.append(row) total_row = get_total_based_on_mode_of_payment(data, mode_of_payments) total_deductions = gross_pay - total_row.get("total") report_summary = [] if data: data.append(total_row) data.append({}) data.append({ "branch": "<b>Total Gross Pay</b>", mode_of_payments[0]:gross_pay }) data.append({ "branch": "<b>Total Deductions</b>", mode_of_payments[0]:total_deductions }) data.append({ "branch": "<b>Total Net Pay</b>", mode_of_payments[0]:total_row.get("total") }) currency = erpbee.get_company_currency(filters.company) report_summary = get_report_summary(gross_pay, total_deductions, total_row.get("total"), currency) return data, total_row, report_summary
def execute(filters=None): if not filters: filters = {} currency = None if filters.get('currency'): currency = filters.get('currency') company_currency = erpbee.get_company_currency(filters.get("company")) salary_slips = get_salary_slips(filters, company_currency) if not salary_slips: return [], [] columns, earning_types, ded_types = get_columns(salary_slips) ss_earning_map = get_ss_earning_map(salary_slips, currency, company_currency) ss_ded_map = get_ss_ded_map(salary_slips, currency, company_currency) doj_map = get_employee_doj_map() data = [] for ss in salary_slips: row = [ ss.name, ss.employee, ss.employee_name, doj_map.get(ss.employee), ss.branch, ss.department, ss.designation, ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days ] if ss.branch is not None: columns[3] = columns[3].replace('-1', '120') if ss.department is not None: columns[4] = columns[4].replace('-1', '120') if ss.designation is not None: columns[5] = columns[5].replace('-1', '120') if ss.leave_without_pay is not None: columns[9] = columns[9].replace('-1', '130') for e in earning_types: row.append(ss_earning_map.get(ss.name, {}).get(e)) if currency == company_currency: row += [flt(ss.gross_pay) * flt(ss.exchange_rate)] else: row += [ss.gross_pay] for d in ded_types: row.append(ss_ded_map.get(ss.name, {}).get(d)) row.append(ss.total_loan_repayment) if currency == company_currency: row += [ flt(ss.total_deduction) * flt(ss.exchange_rate), flt(ss.net_pay) * flt(ss.exchange_rate) ] else: row += [ss.total_deduction, ss.net_pay] row.append(currency or company_currency) data.append(row) return columns, data
def create_tax_slab(payroll_period, effective_date=None, allow_tax_exemption=False, dont_submit=False, currency=None, company=None): if not currency: currency = erpbee.get_default_currency() if company: currency = erpbee.get_company_currency(company) slabs = [{ "from_amount": 250000, "to_amount": 500000, "percent_deduction": 5, "condition": "annual_taxable_earning > 500000" }, { "from_amount": 500001, "to_amount": 1000000, "percent_deduction": 20 }, { "from_amount": 1000001, "percent_deduction": 30 }] income_tax_slab_name = frappe.db.get_value("Income Tax Slab", {"currency": currency}) if not income_tax_slab_name: income_tax_slab = frappe.new_doc("Income Tax Slab") income_tax_slab.name = "Tax Slab: " + payroll_period.name + " " + cstr( currency) income_tax_slab.effective_from = effective_date or add_days( payroll_period.start_date, -2) income_tax_slab.company = company or '' income_tax_slab.currency = currency if allow_tax_exemption: income_tax_slab.allow_tax_exemption = 1 income_tax_slab.standard_tax_exemption_amount = 50000 for item in slabs: income_tax_slab.append("slabs", item) income_tax_slab.append("other_taxes_and_charges", { "description": "cess", "percent": 4 }) income_tax_slab.save() if not dont_submit: income_tax_slab.submit() return income_tax_slab.name else: return income_tax_slab_name
def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.data = [] self.doctype = self.filters.based_on_document self.child_doctype = self.doctype + " Item" self.based_on_field = ("qty" if self.filters.based_on_field == "Qty" else "amount") self.fieldtype = "Float" if self.based_on_field == "qty" else "Currency" self.company_currency = erpbee.get_company_currency( self.filters.company)
def create_purchase_invoice(supplier_name, file_name, args, name): args = frappe._dict(args) pi = frappe.get_doc({ "doctype": "Purchase Invoice", "company": args.company, "currency": erpbee.get_company_currency(args.company), "naming_series": args.naming_series, "supplier": supplier_name, "is_return": args.is_return, "posting_date": today(), "bill_no": args.bill_no, "buying_price_list": args.buying_price_list, "bill_date": args.bill_date, "destination_code": args.destination_code, "document_type": args.document_type, "disable_rounded_total": 1, "items": args["items"], "taxes": args["taxes"] }) try: pi.set_missing_values() pi.insert(ignore_mandatory=True) #if discount exists in file, apply any discount on grand total if args.total_discount > 0: pi.apply_discount_on = "Grand Total" pi.discount_amount = args.total_discount pi.save() #adjust payment amount to match with grand total calculated calc_total = 0 adj = 0 for term in args.terms: calc_total += flt(term["payment_amount"]) if flt(calc_total - flt(pi.grand_total)) != 0: adj = calc_total - flt(pi.grand_total) pi.payment_schedule = [] for term in args.terms: pi.append( 'payment_schedule', { "mode_of_payment_code": term["mode_of_payment_code"], "bank_account_iban": term["bank_account_iban"], "due_date": term["due_date"], "payment_amount": flt(term["payment_amount"]) - adj }) adj = 0 pi.imported_grand_total = calc_total pi.save() return pi.name except Exception as e: frappe.db.set_value("Import Supplier Invoice", name, "status", "Error") frappe.log_error(message=e, title="Create Purchase Invoice: " + args.get("bill_no") + "File Name: " + file_name) return None
def validate_expense_accounts(self): company_currency = erpbee.get_company_currency(self.company) for account in self.taxes: if get_account_currency( account.expense_account) != company_currency: frappe.throw(_( "Row {}: Expense account currency should be same as company's default currency." ).format(account.idx) + _( "Please select expense account with account currency as {}." ).format(frappe.bold(company_currency)), title=_("Invalid Account Currency"))
def validate_employee_currency_with_company_currency(applicant, company): from erpbee.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_employee_currency if not applicant: frappe.throw(_("Please select Applicant")) if not company: frappe.throw(_("Please select Company")) employee_currency = get_employee_currency(applicant) company_currency = erpbee.get_company_currency(company) if employee_currency != company_currency: frappe.throw( _("Loan cannot be repayed from salary for Employee {0} because salary is processed in currency {1}" ).format(applicant, employee_currency))
def validate_conversion_rate(self): # validate conversion rate company_currency = erpbee.get_company_currency(self.doc.company) if not self.doc.currency or self.doc.currency == company_currency: self.doc.currency = company_currency self.doc.conversion_rate = 1.0 else: validate_conversion_rate( self.doc.currency, self.doc.conversion_rate, self.doc.meta.get_label("conversion_rate"), self.doc.company) self.doc.conversion_rate = flt(self.doc.conversion_rate)
def make_employee_advance(employee_name): doc = frappe.new_doc("Employee Advance") doc.employee = employee_name doc.company = "_Test company" doc.purpose = "For site visit" doc.currency = erpbee.get_company_currency("_Test company") doc.exchange_rate = 1 doc.advance_amount = 1000 doc.posting_date = nowdate() doc.advance_account = "_Test Employee Advance - _TC" doc.insert() doc.submit() return doc
def validate_currency(self): company_currency = erpbee.get_company_currency(self.company) account_currency = get_account_currency(self.account) if not self.account_currency: self.account_currency = company_currency if account_currency != self.account_currency: frappe.throw( _("{0} {1}: Accounting Entry for {2} can only be made in currency: {3}" ).format(self.voucher_type, self.voucher_no, self.account, (account_currency or company_currency)), InvalidAccountCurrency) if self.party_type and self.party: validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
def get_dashboard_info(self): info = { "total_paid": 0, "total_unpaid": 0, "currency": erpbee.get_company_currency(self.company) } fees_amount = frappe.db.sql( """select sum(grand_total), sum(outstanding_amount) from tabFees where fee_schedule=%s and docstatus=1""", (self.name)) if fees_amount: info["total_paid"] = flt(fees_amount[0][0]) - flt( fees_amount[0][1]) info["total_unpaid"] = flt(fees_amount[0][1]) return info
def get_accounts_data(self, account=None): accounts = [] self.validate_mandatory() company_currency = erpbee.get_company_currency(self.company) precision = get_field_precision( frappe.get_meta("Exchange Rate Revaluation Account").get_field( "new_balance_in_base_currency"), company_currency) account_details = self.get_accounts_from_gle() for d in account_details: current_exchange_rate = d.balance / d.balance_in_account_currency \ if d.balance_in_account_currency else 0 new_exchange_rate = get_exchange_rate(d.account_currency, company_currency, self.posting_date) new_balance_in_base_currency = flt(d.balance_in_account_currency * new_exchange_rate) gain_loss = flt(new_balance_in_base_currency, precision) - flt( d.balance, precision) if gain_loss: accounts.append({ "account": d.account, "party_type": d.party_type, "party": d.party, "account_currency": d.account_currency, "balance_in_base_currency": d.balance, "balance_in_account_currency": d.balance_in_account_currency, "current_exchange_rate": current_exchange_rate, "new_exchange_rate": new_exchange_rate, "new_balance_in_base_currency": new_balance_in_base_currency }) if not accounts: self.throw_invalid_response_message(account_details) return accounts
def get_serialized_values(self, sle): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) serial_nos = cstr(sle.serial_no).split("\n") if incoming_rate < 0: # wrong incoming rate incoming_rate = self.wh_data.valuation_rate stock_value_change = 0 if incoming_rate: stock_value_change = actual_qty * incoming_rate elif actual_qty < 0: # In case of delivery/stock issue, get average purchase rate # of serial nos of current entry if not sle.is_cancelled: outgoing_value = self.get_incoming_value_for_serial_nos( sle, serial_nos) stock_value_change = -1 * outgoing_value else: stock_value_change = actual_qty * sle.outgoing_rate new_stock_qty = self.wh_data.qty_after_transaction + actual_qty if new_stock_qty > 0: new_stock_value = ( self.wh_data.qty_after_transaction * self.wh_data.valuation_rate) + stock_value_change if new_stock_value >= 0: # calculate new valuation rate only if stock value is positive # else it remains the same as that of previous entry self.wh_data.valuation_rate = new_stock_value / new_stock_qty if not self.wh_data.valuation_rate and sle.voucher_detail_no: allow_zero_rate = self.check_if_allow_zero_valuation_rate( sle.voucher_type, sle.voucher_detail_no) if not allow_zero_rate: self.wh_data.valuation_rate = get_valuation_rate( sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpbee.get_company_currency(sle.company))
def create_journal_entry(self, je_payment_amount, user_remark): payroll_payable_account = self.payroll_payable_account precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") accounts = [] currencies = [] multi_currency = 0 company_currency = erpbee.get_company_currency(self.company) exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry( self.payment_account, je_payment_amount, company_currency, currencies) accounts.append({ "account": self.payment_account, "bank_account": self.bank_account, "credit_in_account_currency": flt(amount, precision), "exchange_rate": flt(exchange_rate), }) exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry( payroll_payable_account, je_payment_amount, company_currency, currencies) accounts.append({ "account": payroll_payable_account, "debit_in_account_currency": flt(amount, precision), "exchange_rate": flt(exchange_rate), "reference_type": self.doctype, "reference_name": self.name }) if len(currencies) > 1: multi_currency = 1 journal_entry = frappe.new_doc('Journal Entry') journal_entry.voucher_type = 'Bank Entry' journal_entry.user_remark = _('Payment of {0} from {1} to {2}')\ .format(user_remark, self.start_date, self.end_date) journal_entry.company = self.company journal_entry.posting_date = self.posting_date journal_entry.multi_currency = multi_currency journal_entry.set("accounts", accounts) journal_entry.save(ignore_permissions=True)
def get_moving_average_values(self, sle): actual_qty = flt(sle.actual_qty) new_stock_qty = flt(self.wh_data.qty_after_transaction) + actual_qty if new_stock_qty >= 0: if actual_qty > 0: if flt(self.wh_data.qty_after_transaction) <= 0: self.wh_data.valuation_rate = sle.incoming_rate else: new_stock_value = (self.wh_data.qty_after_transaction * self.wh_data.valuation_rate) + \ (actual_qty * sle.incoming_rate) self.wh_data.valuation_rate = new_stock_value / new_stock_qty elif sle.outgoing_rate: if new_stock_qty: new_stock_value = (self.wh_data.qty_after_transaction * self.wh_data.valuation_rate) + \ (actual_qty * sle.outgoing_rate) self.wh_data.valuation_rate = new_stock_value / new_stock_qty else: self.wh_data.valuation_rate = sle.outgoing_rate else: if flt(self.wh_data.qty_after_transaction ) >= 0 and sle.outgoing_rate: self.wh_data.valuation_rate = sle.outgoing_rate if not self.wh_data.valuation_rate and actual_qty > 0: self.wh_data.valuation_rate = sle.incoming_rate # Get valuation rate from previous SLE or Item master, if item does not have the # allow zero valuration rate flag set if not self.wh_data.valuation_rate and sle.voucher_detail_no: allow_zero_valuation_rate = self.check_if_allow_zero_valuation_rate( sle.voucher_type, sle.voucher_detail_no) if not allow_zero_valuation_rate: self.wh_data.valuation_rate = get_valuation_rate( sle.item_code, sle.warehouse, sle.voucher_type, sle.voucher_no, self.allow_zero_rate, currency=erpbee.get_company_currency(sle.company))
def update_totals(gst_tax, base_gst_tax, doc): doc.base_grand_total -= base_gst_tax doc.grand_total -= gst_tax if doc.meta.get_field("rounded_total"): if doc.is_rounded_total_disabled(): doc.outstanding_amount = doc.grand_total else: doc.rounded_total = round_based_on_smallest_currency_fraction(doc.grand_total, doc.currency, doc.precision("rounded_total")) doc.rounding_adjustment += flt(doc.rounded_total - doc.grand_total, doc.precision("rounding_adjustment")) doc.outstanding_amount = doc.rounded_total or doc.grand_total doc.in_words = money_in_words(doc.grand_total, doc.currency) doc.base_in_words = money_in_words(doc.base_grand_total, erpbee.get_company_currency(doc.company)) doc.set_payment_schedule()
def validate_quantity(doc, args, ref, valid_items, already_returned_items): fields = ['stock_qty'] if doc.doctype in ['Purchase Receipt', 'Purchase Invoice']: fields.extend(['received_qty', 'rejected_qty']) already_returned_data = already_returned_items.get(args.item_code) or {} company_currency = erpbee.get_company_currency(doc.company) stock_qty_precision = get_field_precision( frappe.get_meta(doc.doctype + " Item").get_field("stock_qty"), company_currency) for column in fields: returned_qty = flt(already_returned_data.get( column, 0)) if len(already_returned_data) > 0 else 0 if column == 'stock_qty': reference_qty = ref.get(column) current_stock_qty = args.get(column) else: reference_qty = ref.get(column) * ref.get("conversion_factor", 1.0) current_stock_qty = args.get(column) * args.get( "conversion_factor", 1.0) max_returnable_qty = flt(reference_qty, stock_qty_precision) - returned_qty label = column.replace('_', ' ').title() if reference_qty: if flt(args.get(column)) > 0: frappe.throw( _("{0} must be negative in return document").format(label)) elif returned_qty >= reference_qty and args.get(column): frappe.throw( _("Item {0} has already been returned").format( args.item_code), StockOverReturnError) elif abs(flt(current_stock_qty, stock_qty_precision)) > max_returnable_qty: frappe.throw( _("Row # {0}: Cannot return more than {1} for Item {2}" ).format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
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 = erpbee.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 tax_account_query(doctype, txt, searchfield, start, page_len, filters): company_currency = erpbee.get_company_currency(filters.get('company')) def get_accounts(with_account_type_filter): account_type_condition = '' if with_account_type_filter: account_type_condition = "AND account_type in %(account_types)s" accounts = frappe.db.sql( """ SELECT name, parent_account FROM `tabAccount` WHERE `tabAccount`.docstatus!=2 {account_type_condition} AND is_group = 0 AND company = %(company)s AND account_currency = %(currency)s AND `{searchfield}` LIKE %(txt)s {mcond} ORDER BY idx DESC, name LIMIT %(offset)s, %(limit)s """.format(account_type_condition=account_type_condition, searchfield=searchfield, mcond=get_match_cond(doctype)), dict(account_types=filters.get("account_type"), company=filters.get("company"), currency=company_currency, txt="%{}%".format(txt), offset=start, limit=page_len)) return accounts tax_accounts = get_accounts(True) if not tax_accounts: tax_accounts = get_accounts(False) return tax_accounts
def set_missing_accounts_and_fields(self): if not self.company: self.company = frappe.defaults.get_defaults().company if not self.currency: self.currency = erpbee.get_company_currency(self.company) if not (self.receivable_account and self.income_account and self.cost_center): accounts_details = frappe.get_all("Company", fields=[ "default_receivable_account", "default_income_account", "cost_center" ], filters={"name": self.company})[0] if not self.receivable_account: self.receivable_account = accounts_details.default_receivable_account if not self.income_account: self.income_account = accounts_details.default_income_account if not self.cost_center: self.cost_center = accounts_details.cost_center if not self.student_email: self.student_email = self.get_student_emails()
def get_account_details(account, company, posting_date, party_type=None, party=None): account_currency, account_type = frappe.db.get_value( "Account", account, ["account_currency", "account_type"]) if account_type in ["Receivable", "Payable" ] and not (party_type and party): frappe.throw( _("Party Type and Party is mandatory for {0} account").format( account_type)) account_details = {} company_currency = erpbee.get_company_currency(company) balance = get_balance_on(account, party_type=party_type, party=party, in_account_currency=False) if balance: balance_in_account_currency = get_balance_on(account, party_type=party_type, party=party) current_exchange_rate = balance / balance_in_account_currency if balance_in_account_currency else 0 new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate account_details = { "account_currency": account_currency, "balance_in_base_currency": balance, "balance_in_account_currency": balance_in_account_currency, "current_exchange_rate": current_exchange_rate, "new_exchange_rate": new_exchange_rate, "new_balance_in_base_currency": new_balance_in_base_currency } return account_details