Merge branch 'develop' into employee-util-report
This commit is contained in:
commit
926a9aed58
@ -582,7 +582,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(frm.doc.payment_type == "Receive")
|
if(frm.doc.payment_type == "Receive")
|
||||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount, 1);
|
||||||
else
|
else
|
||||||
frm.events.set_unallocated_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
},
|
},
|
||||||
@ -606,9 +606,9 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
|
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
|
||||||
{fieldtype:"Section Break"},
|
{fieldtype:"Section Break"},
|
||||||
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
|
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
|
||||||
"get_query": function() {
|
"get_query": function() {
|
||||||
return {
|
return {
|
||||||
"filters": {"company": frm.doc.company}
|
"filters": {"company": frm.doc.company}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -743,7 +743,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
|
allocate_party_amount_against_ref_docs: function(frm, paid_amount, paid_amount_change) {
|
||||||
var total_positive_outstanding_including_order = 0;
|
var total_positive_outstanding_including_order = 0;
|
||||||
var total_negative_outstanding = 0;
|
var total_negative_outstanding = 0;
|
||||||
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||||
@ -800,22 +800,15 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
//If allocate payment amount checkbox is unchecked, set zero to allocate amount
|
//If allocate payment amount checkbox is unchecked, set zero to allocate amount
|
||||||
row.allocated_amount = 0;
|
row.allocated_amount = 0;
|
||||||
|
|
||||||
} else if (frappe.flags.allocate_payment_amount != 0 && !row.allocated_amount) {
|
} else if (frappe.flags.allocate_payment_amount != 0 && (!row.allocated_amount || paid_amount_change)) {
|
||||||
if (row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
|
if (row.outstanding_amount > 0 && allocated_positive_outstanding >= 0) {
|
||||||
if (row.outstanding_amount >= allocated_positive_outstanding) {
|
row.allocated_amount = (row.outstanding_amount >= allocated_positive_outstanding) ?
|
||||||
row.allocated_amount = allocated_positive_outstanding;
|
allocated_positive_outstanding : row.outstanding_amount;
|
||||||
} else {
|
|
||||||
row.allocated_amount = row.outstanding_amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocated_positive_outstanding -= flt(row.allocated_amount);
|
allocated_positive_outstanding -= flt(row.allocated_amount);
|
||||||
} else if (row.outstanding_amount < 0 && allocated_negative_outstanding) {
|
|
||||||
if (Math.abs(row.outstanding_amount) >= allocated_negative_outstanding) {
|
|
||||||
row.allocated_amount = -1*allocated_negative_outstanding;
|
|
||||||
} else {
|
|
||||||
row.allocated_amount = row.outstanding_amount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
} else if (row.outstanding_amount < 0 && allocated_negative_outstanding) {
|
||||||
|
row.allocated_amount = (Math.abs(row.outstanding_amount) >= allocated_negative_outstanding) ?
|
||||||
|
-1*allocated_negative_outstanding : row.outstanding_amount;
|
||||||
allocated_negative_outstanding -= Math.abs(flt(row.allocated_amount));
|
allocated_negative_outstanding -= Math.abs(flt(row.allocated_amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, upd
|
|||||||
gl_map = process_gl_map(gl_map, merge_entries)
|
gl_map = process_gl_map(gl_map, merge_entries)
|
||||||
if gl_map and len(gl_map) > 1:
|
if gl_map and len(gl_map) > 1:
|
||||||
save_entries(gl_map, adv_adj, update_outstanding, from_repost)
|
save_entries(gl_map, adv_adj, update_outstanding, from_repost)
|
||||||
else:
|
# Post GL Map proccess there may no be any GL Entries
|
||||||
|
elif gl_map:
|
||||||
frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
|
frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
|
||||||
else:
|
else:
|
||||||
make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
|
make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
|
||||||
|
@ -90,6 +90,8 @@ class AccountsController(TransactionBase):
|
|||||||
self.ensure_supplier_is_not_blocked()
|
self.ensure_supplier_is_not_blocked()
|
||||||
|
|
||||||
self.validate_date_with_fiscal_year()
|
self.validate_date_with_fiscal_year()
|
||||||
|
self.validate_party_accounts()
|
||||||
|
|
||||||
self.validate_inter_company_reference()
|
self.validate_inter_company_reference()
|
||||||
|
|
||||||
self.set_incoming_rate()
|
self.set_incoming_rate()
|
||||||
@ -233,6 +235,23 @@ class AccountsController(TransactionBase):
|
|||||||
validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company,
|
validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company,
|
||||||
self.meta.get_label(date_field), self)
|
self.meta.get_label(date_field), self)
|
||||||
|
|
||||||
|
def validate_party_accounts(self):
|
||||||
|
if self.doctype not in ('Sales Invoice', 'Purchase Invoice'):
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.doctype == 'Sales Invoice':
|
||||||
|
party_account_field = 'debit_to'
|
||||||
|
item_field = 'income_account'
|
||||||
|
else:
|
||||||
|
party_account_field = 'credit_to'
|
||||||
|
item_field = 'expense_account'
|
||||||
|
|
||||||
|
for item in self.get('items'):
|
||||||
|
if item.get(item_field) == self.get(party_account_field):
|
||||||
|
frappe.throw(_("Row {0}: {1} {2} cannot be same as {3} (Party Account) {4}").format(item.idx,
|
||||||
|
frappe.bold(frappe.unscrub(item_field)), item.get(item_field),
|
||||||
|
frappe.bold(frappe.unscrub(party_account_field)), self.get(party_account_field)))
|
||||||
|
|
||||||
def validate_inter_company_reference(self):
|
def validate_inter_company_reference(self):
|
||||||
if self.doctype not in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
|
if self.doctype not in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
|
||||||
return
|
return
|
||||||
@ -240,7 +259,7 @@ class AccountsController(TransactionBase):
|
|||||||
if self.is_internal_transfer():
|
if self.is_internal_transfer():
|
||||||
if not (self.get('inter_company_reference') or self.get('inter_company_invoice_reference')
|
if not (self.get('inter_company_reference') or self.get('inter_company_invoice_reference')
|
||||||
or self.get('inter_company_order_reference')):
|
or self.get('inter_company_order_reference')):
|
||||||
msg = _("Internal Sale or Delivery Reference missing. ")
|
msg = _("Internal Sale or Delivery Reference missing.")
|
||||||
msg += _("Please create purchase from internal sale or delivery document itself")
|
msg += _("Please create purchase from internal sale or delivery document itself")
|
||||||
frappe.throw(msg, title=_("Internal Sales Reference Missing"))
|
frappe.throw(msg, title=_("Internal Sales Reference Missing"))
|
||||||
|
|
||||||
|
@ -262,7 +262,8 @@ def copy_attributes_to_variant(item, variant):
|
|||||||
# copy non no-copy fields
|
# copy non no-copy fields
|
||||||
|
|
||||||
exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website",
|
exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website",
|
||||||
"show_variant_in_website", "opening_stock", "variant_of", "valuation_rate"]
|
"show_variant_in_website", "opening_stock", "variant_of", "valuation_rate",
|
||||||
|
"has_variants", "attributes"]
|
||||||
|
|
||||||
if item.variant_based_on=='Manufacturer':
|
if item.variant_based_on=='Manufacturer':
|
||||||
# don't copy manufacturer values if based on part no
|
# don't copy manufacturer values if based on part no
|
||||||
|
@ -773,3 +773,4 @@ erpnext.patches.v13_0.fix_non_unique_represents_company
|
|||||||
erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
|
erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
|
||||||
erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021
|
erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021
|
||||||
erpnext.patches.v13_0.update_shipment_status
|
erpnext.patches.v13_0.update_shipment_status
|
||||||
|
erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
"""Remove has_variants and attribute fields from item variant settings."""
|
||||||
|
frappe.reload_doc("stock", "doctype", "Item Variant Settings")
|
||||||
|
|
||||||
|
frappe.db.sql("""delete from `tabVariant Field`
|
||||||
|
where field_name in ('attributes', 'has_variants')""")
|
@ -179,9 +179,6 @@ class Project(Document):
|
|||||||
if self.percent_complete == 100:
|
if self.percent_complete == 100:
|
||||||
self.status = "Completed"
|
self.status = "Completed"
|
||||||
|
|
||||||
else:
|
|
||||||
self.status = "Open"
|
|
||||||
|
|
||||||
def update_costing(self):
|
def update_costing(self):
|
||||||
from_time_sheet = frappe.db.sql("""select
|
from_time_sheet = frappe.db.sql("""select
|
||||||
sum(costing_amount) as costing_amount,
|
sum(costing_amount) as costing_amount,
|
||||||
|
@ -32,7 +32,8 @@ frappe.ui.form.on("Task", {
|
|||||||
|
|
||||||
frm.set_query("parent_task", function () {
|
frm.set_query("parent_task", function () {
|
||||||
let filters = {
|
let filters = {
|
||||||
"is_group": 1
|
"is_group": 1,
|
||||||
|
"name": ["!=", frm.doc.name]
|
||||||
};
|
};
|
||||||
if (frm.doc.project) filters["project"] = frm.doc.project;
|
if (frm.doc.project) filters["project"] = frm.doc.project;
|
||||||
return {
|
return {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2019-10-15 12:33:21.845329",
|
"creation": "2019-10-15 12:33:21.845329",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@ -86,12 +87,14 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:!doc.__islocal",
|
||||||
"fieldname": "upload_xml_invoices_section",
|
"fieldname": "upload_xml_invoices_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Upload XML Invoices"
|
"label": "Upload XML Invoices"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2020-05-25 21:32:49.064579",
|
"links": [],
|
||||||
|
"modified": "2021-04-24 10:33:12.250687",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Regional",
|
"module": "Regional",
|
||||||
"name": "Import Supplier Invoice",
|
"name": "Import Supplier Invoice",
|
||||||
|
@ -28,14 +28,19 @@ class ImportSupplierInvoice(Document):
|
|||||||
self.name = "Import Invoice on " + format_datetime(self.creation)
|
self.name = "Import Invoice on " + format_datetime(self.creation)
|
||||||
|
|
||||||
def import_xml_data(self):
|
def import_xml_data(self):
|
||||||
import_file = frappe.get_doc("File", {"file_url": self.zip_file})
|
zip_file = frappe.get_doc("File", {
|
||||||
|
"file_url": self.zip_file,
|
||||||
|
"attached_to_doctype": self.doctype,
|
||||||
|
"attached_to_name": self.name
|
||||||
|
})
|
||||||
|
|
||||||
self.publish("File Import", _("Processing XML Files"), 1, 3)
|
self.publish("File Import", _("Processing XML Files"), 1, 3)
|
||||||
|
|
||||||
self.file_count = 0
|
self.file_count = 0
|
||||||
self.purchase_invoices_count = 0
|
self.purchase_invoices_count = 0
|
||||||
self.default_uom = frappe.db.get_value("Stock Settings", fieldname="stock_uom")
|
self.default_uom = frappe.db.get_value("Stock Settings", fieldname="stock_uom")
|
||||||
|
|
||||||
with zipfile.ZipFile(get_full_path(self.zip_file)) as zf:
|
with zipfile.ZipFile(zip_file.get_full_path()) as zf:
|
||||||
for file_name in zf.namelist():
|
for file_name in zf.namelist():
|
||||||
content = get_file_content(file_name, zf)
|
content = get_file_content(file_name, zf)
|
||||||
file_content = bs(content, "xml")
|
file_content = bs(content, "xml")
|
||||||
@ -126,8 +131,7 @@ class ImportSupplierInvoice(Document):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def process_file_data(self):
|
def process_file_data(self):
|
||||||
self.status = "Processing File Data"
|
self.db_set("status", "Processing File Data", notify=True, commit=True)
|
||||||
self.save()
|
|
||||||
frappe.enqueue_doc(self.doctype, self.name, "import_xml_data", queue="long", timeout=3600)
|
frappe.enqueue_doc(self.doctype, self.name, "import_xml_data", queue="long", timeout=3600)
|
||||||
|
|
||||||
def publish(self, title, message, count, total):
|
def publish(self, title, message, count, total):
|
||||||
@ -381,24 +385,3 @@ def create_uom(uom):
|
|||||||
new_uom.uom_name = uom
|
new_uom.uom_name = uom
|
||||||
new_uom.save()
|
new_uom.save()
|
||||||
return new_uom.uom_name
|
return new_uom.uom_name
|
||||||
|
|
||||||
def get_full_path(file_name):
|
|
||||||
"""Returns file path from given file name"""
|
|
||||||
file_path = file_name
|
|
||||||
|
|
||||||
if "/" not in file_path:
|
|
||||||
file_path = "/files/" + file_path
|
|
||||||
|
|
||||||
if file_path.startswith("/private/files/"):
|
|
||||||
file_path = get_files_path(*file_path.split("/private/files/", 1)[1].split("/"), is_private=1)
|
|
||||||
|
|
||||||
elif file_path.startswith("/files/"):
|
|
||||||
file_path = get_files_path(*file_path.split("/files/", 1)[1].split("/"))
|
|
||||||
|
|
||||||
elif file_path.startswith("http"):
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif not self.file_url:
|
|
||||||
frappe.throw(_("There is some problem with the file url: {0}").format(file_path))
|
|
||||||
|
|
||||||
return file_path
|
|
||||||
|
@ -199,7 +199,7 @@ class Gstr1Report(object):
|
|||||||
self.item_tax_rate = frappe._dict()
|
self.item_tax_rate = frappe._dict()
|
||||||
|
|
||||||
items = frappe.db.sql("""
|
items = frappe.db.sql("""
|
||||||
select item_code, parent, taxable_value, item_tax_rate
|
select item_code, parent, taxable_value, base_net_amount, item_tax_rate
|
||||||
from `tab%s Item`
|
from `tab%s Item`
|
||||||
where parent in (%s)
|
where parent in (%s)
|
||||||
""" % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
|
""" % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
|
||||||
@ -207,7 +207,7 @@ class Gstr1Report(object):
|
|||||||
for d in items:
|
for d in items:
|
||||||
if d.item_code not in self.invoice_items.get(d.parent, {}):
|
if d.item_code not in self.invoice_items.get(d.parent, {}):
|
||||||
self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code,
|
self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code,
|
||||||
sum(i.get('taxable_value', 0) for i in items
|
sum((i.get('taxable_value', 0) or i.get('base_net_amount', 0)) for i in items
|
||||||
if i.item_code == d.item_code and i.parent == d.parent))
|
if i.item_code == d.item_code and i.parent == d.parent))
|
||||||
|
|
||||||
item_tax_rate = {}
|
item_tax_rate = {}
|
||||||
|
@ -63,7 +63,7 @@ class Item(WebsiteGenerator):
|
|||||||
if self.variant_of:
|
if self.variant_of:
|
||||||
if not self.item_code:
|
if not self.item_code:
|
||||||
template_item_name = frappe.db.get_value("Item", self.variant_of, "item_name")
|
template_item_name = frappe.db.get_value("Item", self.variant_of, "item_name")
|
||||||
self.item_code = make_variant_item_code(self.variant_of, template_item_name, self)
|
make_variant_item_code(self.variant_of, template_item_name, self)
|
||||||
else:
|
else:
|
||||||
from frappe.model.naming import set_name_by_naming_series
|
from frappe.model.naming import set_name_by_naming_series
|
||||||
set_name_by_naming_series(self)
|
set_name_by_naming_series(self)
|
||||||
@ -674,10 +674,10 @@ class Item(WebsiteGenerator):
|
|||||||
if not records: return
|
if not records: return
|
||||||
document = _("Stock Reconciliation") if len(records) == 1 else _("Stock Reconciliations")
|
document = _("Stock Reconciliation") if len(records) == 1 else _("Stock Reconciliations")
|
||||||
|
|
||||||
msg = _("The items {0} and {1} are present in the following {2} : ").format(
|
msg = _("The items {0} and {1} are present in the following {2} :").format(
|
||||||
frappe.bold(old_name), frappe.bold(new_name), document)
|
frappe.bold(old_name), frappe.bold(new_name), document)
|
||||||
|
|
||||||
msg += '<br>'
|
msg += ' <br>'
|
||||||
msg += ', '.join([get_link_to_form("Stock Reconciliation", d.parent) for d in records]) + "<br><br>"
|
msg += ', '.join([get_link_to_form("Stock Reconciliation", d.parent) for d in records]) + "<br><br>"
|
||||||
|
|
||||||
msg += _("Note: To merge the items, create a separate Stock Reconciliation for the old item {0}").format(
|
msg += _("Note: To merge the items, create a separate Stock Reconciliation for the old item {0}").format(
|
||||||
|
@ -13,10 +13,11 @@ class ItemVariantSettings(Document):
|
|||||||
def set_default_fields(self):
|
def set_default_fields(self):
|
||||||
self.fields = []
|
self.fields = []
|
||||||
fields = frappe.get_meta('Item').fields
|
fields = frappe.get_meta('Item').fields
|
||||||
exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website",
|
exclude_fields = {"naming_series", "item_code", "item_name", "show_in_website",
|
||||||
"show_variant_in_website", "standard_rate", "opening_stock", "image", "description",
|
"show_variant_in_website", "standard_rate", "opening_stock", "image", "description",
|
||||||
"variant_of", "valuation_rate", "description", "barcodes",
|
"variant_of", "valuation_rate", "description", "barcodes",
|
||||||
"website_image", "thumbnail", "website_specifiations", "web_long_description"]
|
"website_image", "thumbnail", "website_specifiations", "web_long_description",
|
||||||
|
"has_variants", "attributes"}
|
||||||
|
|
||||||
for d in fields:
|
for d in fields:
|
||||||
if not d.no_copy and d.fieldname not in exclude_fields and \
|
if not d.no_copy and d.fieldname not in exclude_fields and \
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
"url": "https://github.com/frappe/erpnext/issues"
|
"url": "https://github.com/frappe/erpnext/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"snyk": "^1.290.1"
|
"snyk": "^1.518.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"onscan.js": "^1.5.2"
|
"onscan.js": "^1.5.2"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user