Merge branch 'develop' into workstation-type-feat-for-bom
This commit is contained in:
commit
31afae3e75
@ -16,8 +16,8 @@ repos:
|
|||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- id: check-ast
|
- id: check-ast
|
||||||
|
|
||||||
- repo: https://gitlab.com/pycqa/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 3.9.2
|
rev: 5.0.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: [
|
additional_dependencies: [
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Accounting Dimension Filter', {
|
frappe.ui.form.on('Accounting Dimension Filter', {
|
||||||
refresh: function(frm, cdt, cdn) {
|
refresh: function(frm, cdt, cdn) {
|
||||||
if (frm.doc.accounting_dimension) {
|
|
||||||
frm.set_df_property('dimensions', 'label', frm.doc.accounting_dimension, cdn, 'dimension_value');
|
|
||||||
}
|
|
||||||
|
|
||||||
let help_content =
|
let help_content =
|
||||||
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||||
<tr><td>
|
<tr><td>
|
||||||
@ -68,6 +64,7 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
|||||||
frm.clear_table("dimensions");
|
frm.clear_table("dimensions");
|
||||||
let row = frm.add_child("dimensions");
|
let row = frm.add_child("dimensions");
|
||||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||||
|
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
|
||||||
frm.refresh_field("dimensions");
|
frm.refresh_field("dimensions");
|
||||||
frm.trigger('setup_filters');
|
frm.trigger('setup_filters');
|
||||||
},
|
},
|
||||||
|
@ -45,21 +45,6 @@ frappe.ui.form.on("Journal Entry Template", {
|
|||||||
|
|
||||||
frm.trigger("clear_child");
|
frm.trigger("clear_child");
|
||||||
switch(frm.doc.voucher_type){
|
switch(frm.doc.voucher_type){
|
||||||
case "Opening Entry":
|
|
||||||
frm.set_value("is_opening", "Yes");
|
|
||||||
frappe.call({
|
|
||||||
type:"GET",
|
|
||||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_opening_accounts",
|
|
||||||
args: {
|
|
||||||
"company": frm.doc.company
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
if(r.message) {
|
|
||||||
add_accounts(frm.doc, r.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "Bank Entry":
|
case "Bank Entry":
|
||||||
case "Cash Entry":
|
case "Cash Entry":
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
@ -62,7 +62,6 @@ class PaymentEntry(AccountsController):
|
|||||||
self.set_missing_values()
|
self.set_missing_values()
|
||||||
self.validate_payment_type()
|
self.validate_payment_type()
|
||||||
self.validate_party_details()
|
self.validate_party_details()
|
||||||
self.validate_bank_accounts()
|
|
||||||
self.set_exchange_rate()
|
self.set_exchange_rate()
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
self.validate_reference_documents()
|
self.validate_reference_documents()
|
||||||
@ -243,23 +242,6 @@ class PaymentEntry(AccountsController):
|
|||||||
if not frappe.db.exists(self.party_type, self.party):
|
if not frappe.db.exists(self.party_type, self.party):
|
||||||
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
||||||
|
|
||||||
if self.party_account and self.party_type in ("Customer", "Supplier"):
|
|
||||||
self.validate_account_type(
|
|
||||||
self.party_account, [erpnext.get_party_account_type(self.party_type)]
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_bank_accounts(self):
|
|
||||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
|
||||||
self.validate_account_type(self.paid_from, ["Bank", "Cash"])
|
|
||||||
|
|
||||||
if self.payment_type in ("Receive", "Internal Transfer"):
|
|
||||||
self.validate_account_type(self.paid_to, ["Bank", "Cash"])
|
|
||||||
|
|
||||||
def validate_account_type(self, account, account_types):
|
|
||||||
account_type = frappe.db.get_value("Account", account, "account_type")
|
|
||||||
# if account_type not in account_types:
|
|
||||||
# frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
|
|
||||||
|
|
||||||
def set_exchange_rate(self, ref_doc=None):
|
def set_exchange_rate(self, ref_doc=None):
|
||||||
self.set_source_exchange_rate(ref_doc)
|
self.set_source_exchange_rate(ref_doc)
|
||||||
self.set_target_exchange_rate(ref_doc)
|
self.set_target_exchange_rate(ref_doc)
|
||||||
|
@ -2098,7 +2098,7 @@
|
|||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"collapsible_depends_on": "write_off_amount",
|
"collapsible_depends_on": "write_off_amount",
|
||||||
"depends_on": "grand_total",
|
"depends_on": "is_pos",
|
||||||
"fieldname": "write_off_section",
|
"fieldname": "write_off_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hide_days": 1,
|
"hide_days": 1,
|
||||||
@ -2126,7 +2126,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-11-07 16:02:07.972258",
|
"modified": "2022-11-15 09:33:47.870616",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
@ -571,13 +571,14 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
# validate if deferred revenue is enabled for any item
|
# validate if deferred revenue is enabled for any item
|
||||||
# Don't allow to update the invoice if deferred revenue is enabled
|
# Don't allow to update the invoice if deferred revenue is enabled
|
||||||
for item in self.get("items"):
|
if needs_repost:
|
||||||
if item.enable_deferred_revenue:
|
for item in self.get("items"):
|
||||||
frappe.throw(
|
if item.enable_deferred_revenue:
|
||||||
_(
|
frappe.throw(
|
||||||
"Deferred Revenue is enabled for item {0}. You cannot update the invoice after submission."
|
_(
|
||||||
).format(item.item_code)
|
"Deferred Revenue is enabled for item {0}. You cannot update the invoice after submission."
|
||||||
)
|
).format(item.item_code)
|
||||||
|
)
|
||||||
|
|
||||||
self.db_set("repost_required", needs_repost)
|
self.db_set("repost_required", needs_repost)
|
||||||
|
|
||||||
@ -1393,7 +1394,11 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
def make_write_off_gl_entry(self, gl_entries):
|
def make_write_off_gl_entry(self, gl_entries):
|
||||||
# write off entries, applicable if only pos
|
# write off entries, applicable if only pos
|
||||||
if self.write_off_account and flt(self.write_off_amount, self.precision("write_off_amount")):
|
if (
|
||||||
|
self.is_pos
|
||||||
|
and self.write_off_account
|
||||||
|
and flt(self.write_off_amount, self.precision("write_off_amount"))
|
||||||
|
):
|
||||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||||
default_cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
default_cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ class SubcontractingController(StockController):
|
|||||||
and self._doc_before_save
|
and self._doc_before_save
|
||||||
):
|
):
|
||||||
for row in self._doc_before_save.get("items"):
|
for row in self._doc_before_save.get("items"):
|
||||||
item_dict[row.name] = (row.item_code, row.received_qty or row.qty)
|
item_dict[row.name] = (row.item_code, row.qty)
|
||||||
|
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
@ -118,9 +118,7 @@ class SubcontractingController(StockController):
|
|||||||
|
|
||||||
for row in self.items:
|
for row in self.items:
|
||||||
self.__reference_name.append(row.name)
|
self.__reference_name.append(row.name)
|
||||||
if (row.name not in item_dict) or (row.item_code, row.received_qty or row.qty) != item_dict[
|
if (row.name not in item_dict) or (row.item_code, row.qty) != item_dict[row.name]:
|
||||||
row.name
|
|
||||||
]:
|
|
||||||
self.__changed_name.append(row.name)
|
self.__changed_name.append(row.name)
|
||||||
|
|
||||||
if item_dict.get(row.name):
|
if item_dict.get(row.name):
|
||||||
@ -463,13 +461,12 @@ class SubcontractingController(StockController):
|
|||||||
|
|
||||||
def __get_qty_based_on_material_transfer(self, item_row, transfer_item):
|
def __get_qty_based_on_material_transfer(self, item_row, transfer_item):
|
||||||
key = (item_row.item_code, item_row.get(self.subcontract_data.order_field))
|
key = (item_row.item_code, item_row.get(self.subcontract_data.order_field))
|
||||||
item_qty = item_row.received_qty or item_row.qty
|
|
||||||
|
|
||||||
if self.qty_to_be_received.get(key) == item_qty:
|
if self.qty_to_be_received == item_row.qty:
|
||||||
return transfer_item.qty
|
return transfer_item.qty
|
||||||
|
|
||||||
if self.qty_to_be_received:
|
if self.qty_to_be_received:
|
||||||
qty = (flt(item_qty) * flt(transfer_item.qty)) / flt(self.qty_to_be_received.get(key, 0))
|
qty = (flt(item_row.qty) * flt(transfer_item.qty)) / flt(self.qty_to_be_received.get(key, 0))
|
||||||
transfer_item.item_details.required_qty = transfer_item.qty
|
transfer_item.item_details.required_qty = transfer_item.qty
|
||||||
|
|
||||||
if transfer_item.serial_no or frappe.get_cached_value(
|
if transfer_item.serial_no or frappe.get_cached_value(
|
||||||
@ -494,11 +491,7 @@ class SubcontractingController(StockController):
|
|||||||
for bom_item in self.__get_materials_from_bom(
|
for bom_item in self.__get_materials_from_bom(
|
||||||
row.item_code, row.bom, row.get("include_exploded_items")
|
row.item_code, row.bom, row.get("include_exploded_items")
|
||||||
):
|
):
|
||||||
qty = (
|
qty = flt(bom_item.qty_consumed_per_unit) * flt(row.qty) * row.conversion_factor
|
||||||
flt(bom_item.qty_consumed_per_unit)
|
|
||||||
* flt(row.received_qty or row.qty)
|
|
||||||
* row.conversion_factor
|
|
||||||
)
|
|
||||||
bom_item.main_item_code = row.item_code
|
bom_item.main_item_code = row.item_code
|
||||||
self.__update_reserve_warehouse(bom_item, row)
|
self.__update_reserve_warehouse(bom_item, row)
|
||||||
self.__set_alternative_item(bom_item)
|
self.__set_alternative_item(bom_item)
|
||||||
|
@ -649,23 +649,13 @@ class ProductionPlan(Document):
|
|||||||
else:
|
else:
|
||||||
material_request = material_request_map[key]
|
material_request = material_request_map[key]
|
||||||
|
|
||||||
conversion_factor = 1.0
|
|
||||||
if (
|
|
||||||
material_request_type == "Purchase"
|
|
||||||
and item_doc.purchase_uom
|
|
||||||
and item_doc.purchase_uom != item_doc.stock_uom
|
|
||||||
):
|
|
||||||
conversion_factor = (
|
|
||||||
get_conversion_factor(item_doc.name, item_doc.purchase_uom).get("conversion_factor") or 1.0
|
|
||||||
)
|
|
||||||
|
|
||||||
# add item
|
# add item
|
||||||
material_request.append(
|
material_request.append(
|
||||||
"items",
|
"items",
|
||||||
{
|
{
|
||||||
"item_code": item.item_code,
|
"item_code": item.item_code,
|
||||||
"from_warehouse": item.from_warehouse,
|
"from_warehouse": item.from_warehouse,
|
||||||
"qty": item.quantity / conversion_factor,
|
"qty": item.quantity,
|
||||||
"schedule_date": schedule_date,
|
"schedule_date": schedule_date,
|
||||||
"warehouse": item.warehouse,
|
"warehouse": item.warehouse,
|
||||||
"sales_order": item.sales_order,
|
"sales_order": item.sales_order,
|
||||||
@ -1053,11 +1043,25 @@ def get_material_request_items(
|
|||||||
if include_safety_stock:
|
if include_safety_stock:
|
||||||
required_qty += flt(row["safety_stock"])
|
required_qty += flt(row["safety_stock"])
|
||||||
|
|
||||||
|
item_details = frappe.get_cached_value(
|
||||||
|
"Item", row.item_code, ["purchase_uom", "stock_uom"], as_dict=1
|
||||||
|
)
|
||||||
|
|
||||||
|
conversion_factor = 1.0
|
||||||
|
if (
|
||||||
|
row.get("default_material_request_type") == "Purchase"
|
||||||
|
and item_details.purchase_uom
|
||||||
|
and item_details.purchase_uom != item_details.stock_uom
|
||||||
|
):
|
||||||
|
conversion_factor = (
|
||||||
|
get_conversion_factor(row.item_code, item_details.purchase_uom).get("conversion_factor") or 1.0
|
||||||
|
)
|
||||||
|
|
||||||
if required_qty > 0:
|
if required_qty > 0:
|
||||||
return {
|
return {
|
||||||
"item_code": row.item_code,
|
"item_code": row.item_code,
|
||||||
"item_name": row.item_name,
|
"item_name": row.item_name,
|
||||||
"quantity": required_qty,
|
"quantity": required_qty / conversion_factor,
|
||||||
"required_bom_qty": total_qty,
|
"required_bom_qty": total_qty,
|
||||||
"stock_uom": row.get("stock_uom"),
|
"stock_uom": row.get("stock_uom"),
|
||||||
"warehouse": warehouse
|
"warehouse": warehouse
|
||||||
|
@ -826,6 +826,11 @@ class TestProductionPlan(FrappeTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
pln.make_material_request()
|
pln.make_material_request()
|
||||||
|
|
||||||
|
for row in pln.mr_items:
|
||||||
|
self.assertEqual(row.uom, "Nos")
|
||||||
|
self.assertEqual(row.quantity, 1)
|
||||||
|
|
||||||
for row in frappe.get_all(
|
for row in frappe.get_all(
|
||||||
"Material Request Item",
|
"Material Request Item",
|
||||||
filters={"production_plan": pln.name},
|
filters={"production_plan": pln.name},
|
||||||
|
@ -11,7 +11,7 @@ $.extend(erpnext.bulk_transaction_processing, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let count_of_rows = checked_items.length;
|
let count_of_rows = checked_items.length;
|
||||||
frappe.confirm(__("Create {0} {1} ?", [count_of_rows, to_doctype]), ()=>{
|
frappe.confirm(__("Create {0} {1} ?", [count_of_rows, __(to_doctype)]), ()=>{
|
||||||
if (doc_name.length == 0) {
|
if (doc_name.length == 0) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.utilities.bulk_transaction.transaction_processing",
|
method: "erpnext.utilities.bulk_transaction.transaction_processing",
|
||||||
@ -20,11 +20,11 @@ $.extend(erpnext.bulk_transaction_processing, {
|
|||||||
|
|
||||||
});
|
});
|
||||||
if (count_of_rows > 10) {
|
if (count_of_rows > 10) {
|
||||||
frappe.show_alert("Starting a background job to create {0} {1}", [count_of_rows, to_doctype]);
|
frappe.show_alert("Starting a background job to create {0} {1}", [count_of_rows, __(to_doctype)]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint(__("Selected document must be in submitted state"));
|
frappe.msgprint(__("Selected document must be in submitted state"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@ import json
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.utils import cint
|
||||||
from frappe.utils.nestedset import get_root_of
|
from frappe.utils.nestedset import get_root_of
|
||||||
|
|
||||||
from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability
|
from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability
|
||||||
@ -108,10 +109,10 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te
|
|||||||
item.name asc
|
item.name asc
|
||||||
LIMIT
|
LIMIT
|
||||||
{page_length} offset {start}""".format(
|
{page_length} offset {start}""".format(
|
||||||
start=start,
|
start=cint(start),
|
||||||
page_length=page_length,
|
page_length=cint(page_length),
|
||||||
lft=lft,
|
lft=cint(lft),
|
||||||
rgt=rgt,
|
rgt=cint(rgt),
|
||||||
condition=condition,
|
condition=condition,
|
||||||
bin_join_selection=bin_join_selection,
|
bin_join_selection=bin_join_selection,
|
||||||
bin_join_condition=bin_join_condition,
|
bin_join_condition=bin_join_condition,
|
||||||
|
@ -58,7 +58,6 @@ class SubcontractingReceipt(SubcontractingController):
|
|||||||
def before_validate(self):
|
def before_validate(self):
|
||||||
super(SubcontractingReceipt, self).before_validate()
|
super(SubcontractingReceipt, self).before_validate()
|
||||||
self.set_items_bom()
|
self.set_items_bom()
|
||||||
self.set_received_qty()
|
|
||||||
self.set_items_cost_center()
|
self.set_items_cost_center()
|
||||||
self.set_items_expense_account()
|
self.set_items_expense_account()
|
||||||
|
|
||||||
@ -213,10 +212,6 @@ class SubcontractingReceipt(SubcontractingController):
|
|||||||
"bom",
|
"bom",
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_received_qty(self):
|
|
||||||
for item in self.items:
|
|
||||||
item.received_qty = flt(item.qty) + flt(item.rejected_qty)
|
|
||||||
|
|
||||||
def set_items_cost_center(self):
|
def set_items_cost_center(self):
|
||||||
if self.company:
|
if self.company:
|
||||||
cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||||
|
@ -515,17 +515,18 @@ class TestSubcontractingReceipt(FrappeTestCase):
|
|||||||
scr.items[0].rejected_qty = 3
|
scr.items[0].rejected_qty = 3
|
||||||
scr.save()
|
scr.save()
|
||||||
|
|
||||||
# consumed_qty should be ((received_qty) * (transfered_qty / qty)) = ((5 + 3) * (20 / 10)) = 16
|
# consumed_qty should be (accepted_qty * (transfered_qty / qty)) = (5 * (20 / 10)) = 10
|
||||||
self.assertEqual(scr.supplied_items[0].consumed_qty, 16)
|
self.assertEqual(scr.supplied_items[0].consumed_qty, 10)
|
||||||
|
|
||||||
# Set Backflush Based On as "BOM"
|
# Set Backflush Based On as "BOM"
|
||||||
set_backflush_based_on("BOM")
|
set_backflush_based_on("BOM")
|
||||||
|
|
||||||
|
scr.items[0].qty = 6 # Accepted Qty
|
||||||
scr.items[0].rejected_qty = 4
|
scr.items[0].rejected_qty = 4
|
||||||
scr.save()
|
scr.save()
|
||||||
|
|
||||||
# consumed_qty should be ((received_qty) * (qty_consumed_per_unit)) = ((5 + 4) * (1)) = 9
|
# consumed_qty should be (accepted_qty * qty_consumed_per_unit) = (6 * 1) = 6
|
||||||
self.assertEqual(scr.supplied_items[0].consumed_qty, 9)
|
self.assertEqual(scr.supplied_items[0].consumed_qty, 6)
|
||||||
|
|
||||||
|
|
||||||
def make_return_subcontracting_receipt(**args):
|
def make_return_subcontracting_receipt(**args):
|
||||||
|
Loading…
Reference in New Issue
Block a user