Merge branch 'develop' into iff-invoicing
This commit is contained in:
commit
5d6b07558d
@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"doctype": "DocType",
|
||||
@ -82,6 +81,7 @@
|
||||
"item_tax_rate",
|
||||
"bom",
|
||||
"include_exploded_items",
|
||||
"purchase_invoice_item",
|
||||
"col_break6",
|
||||
"purchase_order",
|
||||
"po_detail",
|
||||
@ -769,12 +769,21 @@
|
||||
"collapsible": 1,
|
||||
"fieldname": "col_break7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.update_stock == 1",
|
||||
"fieldname": "purchase_invoice_item",
|
||||
"fieldtype": "Data",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Purchase Invoice Item",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-22 10:37:35.103176",
|
||||
"modified": "2020-08-20 11:48:01.398356",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-06-04 11:02:19",
|
||||
"doctype": "DocType",
|
||||
@ -87,6 +86,7 @@
|
||||
"edit_references",
|
||||
"sales_order",
|
||||
"so_detail",
|
||||
"sales_invoice_item",
|
||||
"column_break_74",
|
||||
"delivery_note",
|
||||
"dn_detail",
|
||||
@ -790,12 +790,22 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.update_stock == 1",
|
||||
"fieldname": "sales_invoice_item",
|
||||
"fieldtype": "Data",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Sales Invoice Item",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-07-18 12:24:41.749986",
|
||||
"modified": "2020-08-20 11:24:41.749986",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
@ -378,7 +378,7 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
|
||||
if filters and filters.get('presentation_currency') != d.default_currency:
|
||||
currency_info['company'] = d.name
|
||||
currency_info['company_currency'] = d.default_currency
|
||||
convert_to_presentation_currency(gl_entries, currency_info)
|
||||
convert_to_presentation_currency(gl_entries, currency_info, filters.get('company'))
|
||||
|
||||
for entry in gl_entries:
|
||||
key = entry.account_number or entry.account_name
|
||||
|
@ -423,7 +423,7 @@ def set_gl_entries_by_account(
|
||||
distributed_cost_center_query=distributed_cost_center_query), gl_filters, as_dict=True) #nosec
|
||||
|
||||
if filters and filters.get('presentation_currency'):
|
||||
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
||||
convert_to_presentation_currency(gl_entries, get_currency(filters), filters.get('company'))
|
||||
|
||||
for entry in gl_entries:
|
||||
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
||||
|
@ -180,7 +180,7 @@ def get_gl_entries(filters):
|
||||
filters, as_dict=1)
|
||||
|
||||
if filters.get('presentation_currency'):
|
||||
return convert_to_presentation_currency(gl_entries, currency_map)
|
||||
return convert_to_presentation_currency(gl_entries, currency_map, filters.get('company'))
|
||||
else:
|
||||
return gl_entries
|
||||
|
||||
|
@ -6,10 +6,6 @@ from erpnext.accounts.doctype.fiscal_year.fiscal_year import get_from_and_to_dat
|
||||
from frappe.utils import cint, get_datetime_str, formatdate, flt
|
||||
|
||||
__exchange_rates = {}
|
||||
P_OR_L_ACCOUNTS = list(
|
||||
sum(frappe.get_list('Account', fields=['name'], or_filters=[{'root_type': 'Income'}, {'root_type': 'Expense'}], as_list=True), ())
|
||||
)
|
||||
|
||||
|
||||
def get_currency(filters):
|
||||
"""
|
||||
@ -73,18 +69,7 @@ def get_rate_as_at(date, from_currency, to_currency):
|
||||
|
||||
return rate
|
||||
|
||||
|
||||
def is_p_or_l_account(account_name):
|
||||
"""
|
||||
Check if the given `account name` is an `Account` with `root_type` of either 'Income'
|
||||
or 'Expense'.
|
||||
:param account_name:
|
||||
:return: Boolean
|
||||
"""
|
||||
return account_name in P_OR_L_ACCOUNTS
|
||||
|
||||
|
||||
def convert_to_presentation_currency(gl_entries, currency_info):
|
||||
def convert_to_presentation_currency(gl_entries, currency_info, company):
|
||||
"""
|
||||
Take a list of GL Entries and change the 'debit' and 'credit' values to currencies
|
||||
in `currency_info`.
|
||||
@ -96,6 +81,9 @@ def convert_to_presentation_currency(gl_entries, currency_info):
|
||||
presentation_currency = currency_info['presentation_currency']
|
||||
company_currency = currency_info['company_currency']
|
||||
|
||||
pl_accounts = [d.name for d in frappe.get_list('Account',
|
||||
filters={'report_type': 'Profit and Loss', 'company': company})]
|
||||
|
||||
for entry in gl_entries:
|
||||
account = entry['account']
|
||||
debit = flt(entry['debit'])
|
||||
@ -107,7 +95,7 @@ def convert_to_presentation_currency(gl_entries, currency_info):
|
||||
if account_currency != presentation_currency:
|
||||
value = debit or credit
|
||||
|
||||
date = currency_info['report_date'] if not is_p_or_l_account(account) else entry['posting_date']
|
||||
date = entry['posting_date'] if account in pl_accounts else currency_info['report_date']
|
||||
converted_value = convert(value, presentation_currency, company_currency, date)
|
||||
|
||||
if entry.get('debit'):
|
||||
|
@ -559,9 +559,19 @@ class BuyingController(StockController):
|
||||
"serial_no": cstr(d.serial_no).strip()
|
||||
})
|
||||
if self.is_return:
|
||||
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"voucher_type": "Purchase Receipt", "voucher_no": self.return_against,
|
||||
"item_code": d.item_code}, "incoming_rate")
|
||||
filters = {
|
||||
"voucher_type": self.doctype,
|
||||
"voucher_no": self.return_against,
|
||||
"item_code": d.item_code
|
||||
}
|
||||
|
||||
if (self.doctype == "Purchase Invoice" and self.update_stock
|
||||
and d.get("purchase_invoice_item")):
|
||||
filters["voucher_detail_no"] = d.purchase_invoice_item
|
||||
elif self.doctype == "Purchase Receipt" and d.get("purchase_receipt_item"):
|
||||
filters["voucher_detail_no"] = d.purchase_receipt_item
|
||||
|
||||
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry", filters, "incoming_rate")
|
||||
|
||||
sle.update({
|
||||
"outgoing_rate": original_incoming_rate
|
||||
|
@ -281,6 +281,8 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
||||
target_doc.po_detail = source_doc.po_detail
|
||||
target_doc.pr_detail = source_doc.pr_detail
|
||||
target_doc.purchase_invoice_item = source_doc.name
|
||||
|
||||
elif doctype == "Delivery Note":
|
||||
target_doc.against_sales_order = source_doc.against_sales_order
|
||||
target_doc.against_sales_invoice = source_doc.against_sales_invoice
|
||||
@ -296,6 +298,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
target_doc.so_detail = source_doc.so_detail
|
||||
target_doc.dn_detail = source_doc.dn_detail
|
||||
target_doc.expense_account = source_doc.expense_account
|
||||
target_doc.sales_invoice_item = source_doc.name
|
||||
if default_warehouse_for_sales_return:
|
||||
target_doc.warehouse = default_warehouse_for_sales_return
|
||||
|
||||
|
@ -217,7 +217,9 @@ class SellingController(StockController):
|
||||
'target_warehouse': p.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate,
|
||||
'sales_invoice_item': d.get("sales_invoice_item"),
|
||||
'delivery_note_item': d.get("dn_detail")
|
||||
}))
|
||||
else:
|
||||
il.append(frappe._dict({
|
||||
@ -233,7 +235,9 @@ class SellingController(StockController):
|
||||
'target_warehouse': d.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate,
|
||||
'sales_invoice_item': d.get("sales_invoice_item"),
|
||||
'delivery_note_item': d.get("dn_detail")
|
||||
}))
|
||||
return il
|
||||
|
||||
@ -302,7 +306,11 @@ class SellingController(StockController):
|
||||
d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
|
||||
return_rate = 0
|
||||
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
||||
return_rate = self.get_incoming_rate_for_return(d.item_code, self.return_against)
|
||||
against_document_no = (d.get("sales_invoice_item")
|
||||
if self.doctype == "Sales Invoice" else d.get("delivery_note_item"))
|
||||
|
||||
return_rate = self.get_incoming_rate_for_return(d.item_code,
|
||||
self.return_against, against_document_no)
|
||||
|
||||
# On cancellation or if return entry submission, make stock ledger entry for
|
||||
# target warehouse first, to update serial no values properly
|
||||
|
@ -301,14 +301,19 @@ class StockController(AccountsController):
|
||||
|
||||
return serialized_items
|
||||
|
||||
def get_incoming_rate_for_return(self, item_code, against_document):
|
||||
def get_incoming_rate_for_return(self, item_code, against_document, against_document_no=None):
|
||||
incoming_rate = 0.0
|
||||
cond = ''
|
||||
if against_document and item_code:
|
||||
if against_document_no:
|
||||
cond = " and voucher_detail_no = %s" %(frappe.db.escape(against_document_no))
|
||||
|
||||
incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
|
||||
from `tabStock Ledger Entry`
|
||||
where voucher_type = %s and voucher_no = %s
|
||||
and item_code = %s limit 1""",
|
||||
and item_code = %s {0} limit 1""".format(cond),
|
||||
(self.doctype, against_document, item_code))
|
||||
|
||||
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
|
||||
|
||||
return incoming_rate
|
||||
|
@ -325,7 +325,7 @@ def auto_close_opportunity():
|
||||
doc.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity_from_communication(communication, ignore_communication_links=False):
|
||||
def make_opportunity_from_communication(communication, company, ignore_communication_links=False):
|
||||
from erpnext.crm.doctype.lead.lead import make_lead_from_communication
|
||||
doc = frappe.get_doc("Communication", communication)
|
||||
|
||||
@ -337,6 +337,7 @@ def make_opportunity_from_communication(communication, ignore_communication_link
|
||||
|
||||
opportunity = frappe.get_doc({
|
||||
"doctype": "Opportunity",
|
||||
"company": company,
|
||||
"opportunity_from": opportunity_from,
|
||||
"party_name": lead
|
||||
}).insert(ignore_permissions=True)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe import _
|
||||
@ -24,8 +25,7 @@ class JobOffer(Document):
|
||||
check_vacancies = frappe.get_single("HR Settings").check_vacancies
|
||||
if staffing_plan and check_vacancies:
|
||||
job_offers = self.get_job_offer(staffing_plan.from_date, staffing_plan.to_date)
|
||||
|
||||
if not staffing_plan.get("vacancies") or staffing_plan.vacancies - len(job_offers) <= 0:
|
||||
if not staffing_plan.get("vacancies") or cint(staffing_plan.vacancies) - len(job_offers) <= 0:
|
||||
error_variable = 'for ' + frappe.bold(self.designation)
|
||||
if staffing_plan.get("parent"):
|
||||
error_variable = frappe.bold(get_link_to_form("Staffing Plan", staffing_plan.parent))
|
||||
@ -65,7 +65,7 @@ def get_staffing_plan_detail(designation, company, offer_date):
|
||||
AND %s between sp.from_date and sp.to_date
|
||||
""", (designation, company, offer_date), as_dict=1)
|
||||
|
||||
return frappe._dict(detail[0]) if detail else None
|
||||
return frappe._dict(detail[0]) if (detail and detail[0].parent) else None
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_employee(source_name, target_doc=None):
|
||||
|
@ -7,7 +7,7 @@ frappe.ui.form.on("Communication", {
|
||||
},
|
||||
|
||||
setup_custom_buttons: (frm) => {
|
||||
let confirm_msg = "Are you sure you want to create {0} from this email";
|
||||
let confirm_msg = "Are you sure you want to create {0} from this email?";
|
||||
if(frm.doc.reference_doctype !== "Issue") {
|
||||
frm.add_custom_button(__("Issue"), () => {
|
||||
frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
|
||||
@ -62,17 +62,36 @@ frappe.ui.form.on("Communication", {
|
||||
},
|
||||
|
||||
make_opportunity_from_communication: (frm) => {
|
||||
return frappe.call({
|
||||
const fields = [{
|
||||
fieldtype: 'Link',
|
||||
label: __('Select a Company'),
|
||||
fieldname: 'company',
|
||||
options: 'Company',
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_user_default("Company")
|
||||
}];
|
||||
|
||||
frappe.prompt(fields, data => {
|
||||
frappe.call({
|
||||
method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
|
||||
args: {
|
||||
communication: frm.doc.name
|
||||
communication: frm.doc.name,
|
||||
company: data.company
|
||||
},
|
||||
freeze: true,
|
||||
callback: (r) => {
|
||||
if(r.message) {
|
||||
frm.reload_doc()
|
||||
frm.reload_doc();
|
||||
frappe.show_alert({
|
||||
message: __("Opportunity {0} created",
|
||||
['<a href="#Form/Opportunity/'+r.message+'">' + r.message + '</a>']),
|
||||
indicator: 'green'
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
'Create an Opportunity',
|
||||
'Create');
|
||||
}
|
||||
});
|
@ -22,6 +22,8 @@
|
||||
}
|
||||
|
||||
.filter-options {
|
||||
margin-left: -5px;
|
||||
padding-left: 5px;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
@ -726,9 +726,6 @@ def make_regional_gl_entries(gl_entries, doc):
|
||||
if country != 'India':
|
||||
return gl_entries
|
||||
|
||||
if not doc.total_taxes_and_charges:
|
||||
return gl_entries
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
gst_accounts = get_gst_accounts(doc.company)
|
||||
gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
|
||||
@ -738,6 +735,7 @@ def make_regional_gl_entries(gl_entries, doc):
|
||||
if tax.category not in ("Total", "Valuation and Total"):
|
||||
continue
|
||||
|
||||
dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
|
||||
if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
|
||||
account_currency = get_account_currency(tax.account_head)
|
||||
|
||||
@ -747,8 +745,8 @@ def make_regional_gl_entries(gl_entries, doc):
|
||||
"cost_center": tax.cost_center,
|
||||
"posting_date": doc.posting_date,
|
||||
"against": doc.supplier,
|
||||
"credit": tax.base_tax_amount_after_discount_amount,
|
||||
"credits_in_account_currency": tax.base_tax_amount_after_discount_amount \
|
||||
dr_or_cr: tax.base_tax_amount_after_discount_amount,
|
||||
dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \
|
||||
if account_currency==doc.company_currency \
|
||||
else tax.tax_amount_after_discount_amount
|
||||
}, account_currency, item=tax)
|
||||
|
@ -3,7 +3,7 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Retail Operations",
|
||||
"links": "[\n {\n \"description\": \"Setup default values for POS Invoices\",\n \"label\": \"Point-of-Sale Profile\",\n \"name\": \"POS Profile\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"POS Profile\"\n ],\n \"description\": \"Point of Sale\",\n \"label\": \"POS\",\n \"name\": \"pos\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"description\": \"Cashier Closing\",\n \"label\": \"Cashier Closing\",\n \"name\": \"Cashier Closing\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup mode of POS (Online / Offline)\",\n \"label\": \"POS Settings\",\n \"name\": \"POS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To make Customer based incentive schemes.\",\n \"label\": \"Loyalty Program\",\n \"name\": \"Loyalty Program\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n \"label\": \"Loyalty Point Entry\",\n \"name\": \"Loyalty Point Entry\",\n \"type\": \"doctype\"\n }\n]"
|
||||
"links": "[\n {\n \"description\": \"Setup default values for POS Invoices\",\n \"label\": \"Point of Sale Profile\",\n \"name\": \"POS Profile\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"POS Profile\"\n ],\n \"description\": \"Point of Sale\",\n \"label\": \"Point of Sale\",\n \"name\": \"point-of-sale\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"description\": \"Setup mode of POS (Online / Offline)\",\n \"label\": \"POS Settings\",\n \"name\": \"POS Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Cashier Closing\",\n \"label\": \"Cashier Closing\",\n \"name\": \"Cashier Closing\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To make Customer based incentive schemes.\",\n \"label\": \"Loyalty Program\",\n \"name\": \"Loyalty Program\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n \"label\": \"Loyalty Point Entry\",\n \"name\": \"Loyalty Point Entry\",\n \"type\": \"doctype\"\n }\n]"
|
||||
}
|
||||
],
|
||||
"category": "Domains",
|
||||
@ -14,10 +14,11 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "Desk Page",
|
||||
"extends_another_page": 0,
|
||||
"hide_custom": 0,
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Retail",
|
||||
"modified": "2020-04-26 22:42:39.346750",
|
||||
"modified": "2020-08-20 18:00:07.515691",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Retail",
|
||||
@ -25,5 +26,27 @@
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
"restrict_to_domain": "Retail",
|
||||
"shortcuts": []
|
||||
"shortcuts": [
|
||||
{
|
||||
"color": "#9deca2",
|
||||
"doc_view": "",
|
||||
"format": "{} Active",
|
||||
"label": "Point of Sale Profile",
|
||||
"link_to": "POS Profile",
|
||||
"stats_filter": "{\n \"disabled\": 0\n}",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Point of Sale",
|
||||
"link_to": "point-of-sale",
|
||||
"type": "Page"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "POS Settings",
|
||||
"link_to": "POS Settings",
|
||||
"type": "DocType"
|
||||
}
|
||||
]
|
||||
}
|
@ -7,6 +7,7 @@ import frappe
|
||||
from erpnext.accounts.doctype.cash_flow_mapper.default_cash_flow_mapper import DEFAULT_MAPPERS
|
||||
from .default_success_action import get_default_success_action
|
||||
from frappe import _
|
||||
from frappe.utils import cint
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
|
||||
from erpnext.setup.default_energy_point_rules import get_default_energy_point_rules
|
||||
@ -29,7 +30,7 @@ def after_install():
|
||||
|
||||
|
||||
def check_setup_wizard_not_completed():
|
||||
if frappe.db.get_default('desktop:home_page') != 'setup-wizard':
|
||||
if cint(frappe.db.get_single_value('System Settings', 'setup_complete') or 0):
|
||||
message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed.
|
||||
You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"""
|
||||
frappe.throw(message)
|
||||
|
@ -18,6 +18,28 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
set_perpetual_inventory(0)
|
||||
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
|
||||
|
||||
def test_reverse_purchase_receipt_sle(self):
|
||||
|
||||
frappe.db.set_value('UOM', '_Test UOM', 'must_be_whole_number', 0)
|
||||
|
||||
pr = make_purchase_receipt(qty=0.5)
|
||||
|
||||
sl_entry = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
|
||||
"voucher_no": pr.name}, ['actual_qty'])
|
||||
|
||||
self.assertEqual(len(sl_entry), 1)
|
||||
self.assertEqual(sl_entry[0].actual_qty, 0.5)
|
||||
|
||||
pr.cancel()
|
||||
|
||||
sl_entry_cancelled = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
|
||||
"voucher_no": pr.name}, ['actual_qty'], order_by='creation')
|
||||
|
||||
self.assertEqual(len(sl_entry_cancelled), 2)
|
||||
self.assertEqual(sl_entry_cancelled[1].actual_qty, -0.5)
|
||||
|
||||
frappe.db.set_value('UOM', '_Test UOM', 'must_be_whole_number', 1)
|
||||
|
||||
def test_make_purchase_invoice(self):
|
||||
pr = make_purchase_receipt(do_not_save=True)
|
||||
self.assertRaises(frappe.ValidationError, make_purchase_invoice, pr.name)
|
||||
|
@ -31,7 +31,7 @@ def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_vouc
|
||||
sle['posting_time'] = now_datetime().strftime('%H:%M:%S.%f')
|
||||
|
||||
if cancel:
|
||||
sle['actual_qty'] = -flt(sle.get('actual_qty'), 0)
|
||||
sle['actual_qty'] = -flt(sle.get('actual_qty'))
|
||||
|
||||
if sle['actual_qty'] < 0 and not sle.get('outgoing_rate'):
|
||||
sle['outgoing_rate'] = get_incoming_outgoing_rate_for_cancel(sle.item_code,
|
||||
|
Loading…
x
Reference in New Issue
Block a user