Merge branch 'version-13-hotfix' of https://github.com/frappe/erpnext into mergify/bp/version-13-hotfix/pr-32777

This commit is contained in:
Deepesh Garg
2022-11-08 10:40:07 +05:30
15 changed files with 180 additions and 81 deletions

View File

@@ -569,6 +569,10 @@ frappe.ui.form.on("Purchase Invoice", {
erpnext.queries.setup_queries(frm, "Warehouse", function() { erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc); return erpnext.queries.warehouse(frm.doc);
}); });
if (frm.is_new()) {
frm.clear_table("tax_withheld_vouchers");
}
}, },
is_subcontracted: function(frm) { is_subcontracted: function(frm) {

View File

@@ -67,6 +67,9 @@ class PurchaseInvoice(BuyingController):
supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
self.set_onload("supplier_tds", supplier_tds) self.set_onload("supplier_tds", supplier_tds)
if self.is_new():
self.set("tax_withheld_vouchers", [])
def before_save(self): def before_save(self):
if not self.on_hold: if not self.on_hold:
self.release_date = "" self.release_date = ""
@@ -1373,7 +1376,7 @@ class PurchaseInvoice(BuyingController):
"GL Entry", "GL Entry",
"Stock Ledger Entry", "Stock Ledger Entry",
"Repost Item Valuation", "Repost Item Valuation",
"Purchase Invoice", "Tax Withheld Vouchers",
) )
self.update_advance_tax_references(cancel=1) self.update_advance_tax_references(cancel=1)

View File

@@ -916,7 +916,8 @@ class TestSalesInvoice(unittest.TestCase):
pos_return.insert() pos_return.insert()
pos_return.submit() pos_return.submit()
self.assertEqual(pos_return.get("payments")[0].amount, -1000) self.assertEqual(pos_return.get("payments")[0].amount, -500)
self.assertEqual(pos_return.get("payments")[1].amount, -500)
def test_pos_change_amount(self): def test_pos_change_amount(self):
make_pos_profile( make_pos_profile(

View File

@@ -835,10 +835,7 @@ def remove_return_pos_invoices(party_type, party, invoice_list):
else: else:
return invoice_list return invoice_list
# remove pos return invoices from invoice_list invoice_list = [x for x in invoice_list if x.voucher_no not in return_pos]
for idx, inv in enumerate(invoice_list, 0):
if inv.voucher_no in return_pos:
del invoice_list[idx]
return invoice_list return invoice_list

View File

@@ -384,7 +384,11 @@ frappe.ui.form.on('Asset', {
set_values_from_purchase_doc: function(frm, doctype, purchase_doc) { set_values_from_purchase_doc: function(frm, doctype, purchase_doc) {
frm.set_value('company', purchase_doc.company); frm.set_value('company', purchase_doc.company);
frm.set_value('purchase_date', purchase_doc.posting_date); if (purchase_doc.bill_date) {
frm.set_value('purchase_date', purchase_doc.bill_date);
} else {
frm.set_value('purchase_date', purchase_doc.posting_date);
}
const item = purchase_doc.items.find(item => item.item_code === frm.doc.item_code); const item = purchase_doc.items.find(item => item.item_code === frm.doc.item_code);
if (!item) { if (!item) {
doctype_field = frappe.scrub(doctype) doctype_field = frappe.scrub(doctype)

View File

@@ -152,6 +152,7 @@ class AccountsController(TransactionBase):
self.validate_inter_company_reference() self.validate_inter_company_reference()
self.disable_pricing_rule_on_internal_transfer() self.disable_pricing_rule_on_internal_transfer()
self.disable_tax_included_prices_for_internal_transfer()
self.set_incoming_rate() self.set_incoming_rate()
if self.meta.get_field("currency"): if self.meta.get_field("currency"):
@@ -395,6 +396,20 @@ class AccountsController(TransactionBase):
alert=1, alert=1,
) )
def disable_tax_included_prices_for_internal_transfer(self):
if self.is_internal_transfer():
tax_updated = False
for tax in self.get("taxes"):
if tax.get("included_in_print_rate"):
tax.included_in_print_rate = 0
tax_updated = True
if tax_updated:
frappe.msgprint(
_("Disabled tax included prices since this {} is an internal transfer").format(self.doctype),
alert=1,
)
def validate_due_date(self): def validate_due_date(self):
if self.get("is_pos"): if self.get("is_pos"):
return return

View File

@@ -890,24 +890,33 @@ class calculate_taxes_and_totals(object):
self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc) self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
def set_total_amount_to_default_mop(self, total_amount_to_pay): def set_total_amount_to_default_mop(self, total_amount_to_pay):
default_mode_of_payment = frappe.db.get_value( total_paid_amount = 0
"POS Payment Method", for payment in self.doc.get("payments"):
{"parent": self.doc.pos_profile, "default": 1}, total_paid_amount += (
["mode_of_payment"], payment.amount if self.doc.party_account_currency == self.doc.currency else payment.base_amount
as_dict=1,
)
if default_mode_of_payment:
self.doc.payments = []
self.doc.append(
"payments",
{
"mode_of_payment": default_mode_of_payment.mode_of_payment,
"amount": total_amount_to_pay,
"default": 1,
},
) )
pending_amount = total_amount_to_pay - total_paid_amount
if pending_amount > 0:
default_mode_of_payment = frappe.db.get_value(
"POS Payment Method",
{"parent": self.doc.pos_profile, "default": 1},
["mode_of_payment"],
as_dict=1,
)
if default_mode_of_payment:
self.doc.payments = []
self.doc.append(
"payments",
{
"mode_of_payment": default_mode_of_payment.mode_of_payment,
"amount": pending_amount,
"default": 1,
},
)
def get_itemised_tax_breakup_html(doc): def get_itemised_tax_breakup_html(doc):
if not doc.taxes: if not doc.taxes:

View File

@@ -555,66 +555,69 @@ erpnext.work_order = {
} }
} }
if(!frm.doc.skip_transfer){ if (frm.doc.status != 'Stopped') {
// If "Material Consumption is check in Manufacturing Settings, allow Material Consumption // If "Material Consumption is check in Manufacturing Settings, allow Material Consumption
if (flt(doc.material_transferred_for_manufacturing) > 0 && frm.doc.status != 'Stopped') { if (frm.doc.__onload && frm.doc.__onload.material_consumption == 1) {
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))) { if (flt(doc.material_transferred_for_manufacturing) > 0 || frm.doc.skip_transfer) {
frm.has_finish_btn = true; // Only show "Material Consumption" when required_qty > consumed_qty
var counter = 0;
if (frm.doc.__onload && frm.doc.__onload.material_consumption == 1) { var tbl = frm.doc.required_items || [];
// Only show "Material Consumption" when required_qty > consumed_qty var tbl_lenght = tbl.length;
var counter = 0; for (var i = 0, len = tbl_lenght; i < len; i++) {
var tbl = frm.doc.required_items || []; let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
var tbl_lenght = tbl.length; if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
for (var i = 0, len = tbl_lenght; i < len; i++) { counter += 1;
let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
counter += 1;
}
}
if (counter > 0) {
var consumption_btn = frm.add_custom_button(__('Material Consumption'), function() {
const backflush_raw_materials_based_on = frm.doc.__onload.backflush_raw_materials_based_on;
erpnext.work_order.make_consumption_se(frm, backflush_raw_materials_based_on);
});
consumption_btn.addClass('btn-primary');
} }
} }
if (counter > 0) {
var consumption_btn = frm.add_custom_button(__('Material Consumption'), function() {
const backflush_raw_materials_based_on = frm.doc.__onload.backflush_raw_materials_based_on;
erpnext.work_order.make_consumption_se(frm, backflush_raw_materials_based_on);
});
consumption_btn.addClass('btn-primary');
}
}
}
if(!frm.doc.skip_transfer){
if (flt(doc.material_transferred_for_manufacturing) > 0) {
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))) {
frm.has_finish_btn = true;
var finish_btn = frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
if(doc.material_transferred_for_manufacturing>=doc.qty) {
// all materials transferred for manufacturing, make this primary
finish_btn.addClass('btn-primary');
}
} else {
frappe.db.get_doc("Manufacturing Settings").then((doc) => {
let allowance_percentage = doc.overproduction_percentage_for_work_order;
if (allowance_percentage > 0) {
let allowed_qty = frm.doc.qty + ((allowance_percentage / 100) * frm.doc.qty);
if ((flt(doc.produced_qty) < allowed_qty)) {
frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
}
}
});
}
}
} else {
if ((flt(doc.produced_qty) < flt(doc.qty))) {
var finish_btn = frm.add_custom_button(__('Finish'), function() { var finish_btn = frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture'); erpnext.work_order.make_se(frm, 'Manufacture');
}); });
finish_btn.addClass('btn-primary');
if(doc.material_transferred_for_manufacturing>=doc.qty) {
// all materials transferred for manufacturing, make this primary
finish_btn.addClass('btn-primary');
}
} else {
frappe.db.get_doc("Manufacturing Settings").then((doc) => {
let allowance_percentage = doc.overproduction_percentage_for_work_order;
if (allowance_percentage > 0) {
let allowed_qty = frm.doc.qty + ((allowance_percentage / 100) * frm.doc.qty);
if ((flt(doc.produced_qty) < allowed_qty)) {
frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
}
}
});
} }
} }
} else {
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
var finish_btn = frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
finish_btn.addClass('btn-primary');
}
} }
} }
}, },
calculate_cost: function(doc) { calculate_cost: function(doc) {
if (doc.operations){ if (doc.operations){

View File

@@ -47,6 +47,12 @@ erpnext.setup_auto_gst_taxation = (doctype) => {
} }
} }
}); });
},
reverse_charge: function(frm) {
if (frm.doc.reverse_charge == "Y") {
frm.set_value('eligibility_for_itc', 'ITC on Reverse Charge');
}
} }
}); });
} }

View File

@@ -983,8 +983,6 @@ def validate_reverse_charge_transaction(doc, method):
frappe.throw(msg) frappe.throw(msg)
doc.eligibility_for_itc = "ITC on Reverse Charge"
def update_itc_availed_fields(doc, method): def update_itc_availed_fields(doc, method):
country = frappe.get_cached_value("Company", doc.company, "country") country = frappe.get_cached_value("Company", doc.company, "country")

View File

@@ -67,7 +67,7 @@ erpnext.PointOfSale.Controller = class {
{ {
fieldtype: 'Link', label: __('POS Profile'), fieldtype: 'Link', label: __('POS Profile'),
options: 'POS Profile', fieldname: 'pos_profile', reqd: 1, options: 'POS Profile', fieldname: 'pos_profile', reqd: 1,
get_query: () => pos_profile_query, get_query: () => pos_profile_query(),
onchange: () => fetch_pos_payment_methods() onchange: () => fetch_pos_payment_methods()
}, },
{ {
@@ -101,9 +101,11 @@ erpnext.PointOfSale.Controller = class {
primary_action_label: __('Submit') primary_action_label: __('Submit')
}); });
dialog.show(); dialog.show();
const pos_profile_query = { const pos_profile_query = () => {
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query', return {
filters: { company: dialog.fields_dict.company.get_value() } query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
filters: { company: dialog.fields_dict.company.get_value() }
}
}; };
} }

View File

@@ -285,7 +285,7 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False, serial_no=None):
batches = get_batches(item_code, warehouse, qty, throw, serial_no) batches = get_batches(item_code, warehouse, qty, throw, serial_no)
for batch in batches: for batch in batches:
if cint(qty) <= cint(batch.qty): if flt(qty) <= flt(batch.qty):
batch_no = batch.batch_id batch_no = batch.batch_id
break break

View File

@@ -1050,9 +1050,22 @@ class TestDeliveryNote(FrappeTestCase):
do_not_submit=True, do_not_submit=True,
) )
dn.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"description": "Tax 1",
"rate": 14,
"cost_center": "_Test Cost Center - _TC",
"included_in_print_rate": 1,
},
)
self.assertEqual(dn.items[0].rate, 500) # haven't saved yet self.assertEqual(dn.items[0].rate, 500) # haven't saved yet
dn.save() dn.save()
self.assertEqual(dn.ignore_pricing_rule, 1) self.assertEqual(dn.ignore_pricing_rule, 1)
self.assertEqual(dn.taxes[0].included_in_print_rate, 0)
# rate should reset to incoming rate # rate should reset to incoming rate
self.assertEqual(dn.items[0].rate, rate) self.assertEqual(dn.items[0].rate, rate)
@@ -1063,6 +1076,7 @@ class TestDeliveryNote(FrappeTestCase):
dn.save() dn.save()
self.assertEqual(dn.items[0].rate, rate) self.assertEqual(dn.items[0].rate, rate)
self.assertEqual(dn.items[0].net_rate, rate)
def test_internal_transfer_precision_gle(self): def test_internal_transfer_precision_gle(self):
from erpnext.selling.doctype.customer.test_customer import create_internal_customer from erpnext.selling.doctype.customer.test_customer import create_internal_customer

View File

@@ -74,10 +74,21 @@ def get_conditions(filters):
else: else:
frappe.throw(_("'To Date' is required")) frappe.throw(_("'To Date' is required"))
for field in ["item_code", "warehouse", "batch_no", "company"]: for field in ["item_code", "batch_no", "company"]:
if filters.get(field): if filters.get(field):
conditions += " and {0} = {1}".format(field, frappe.db.escape(filters.get(field))) conditions += " and {0} = {1}".format(field, frappe.db.escape(filters.get(field)))
if filters.get("warehouse"):
warehouse_details = frappe.db.get_value(
"Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1
)
if warehouse_details:
conditions += (
" and exists (select name from `tabWarehouse` wh \
where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"
% (warehouse_details.lft, warehouse_details.rgt)
)
return conditions return conditions
@@ -87,7 +98,7 @@ def get_stock_ledger_entries(filters):
return frappe.db.sql( return frappe.db.sql(
""" """
select item_code, batch_no, warehouse, posting_date, sum(actual_qty) as actual_qty select item_code, batch_no, warehouse, posting_date, sum(actual_qty) as actual_qty
from `tabStock Ledger Entry` from `tabStock Ledger Entry` as sle
where is_cancelled = 0 and docstatus < 2 and ifnull(batch_no, '') != '' %s where is_cancelled = 0 and docstatus < 2 and ifnull(batch_no, '') != '' %s
group by voucher_no, batch_no, item_code, warehouse group by voucher_no, batch_no, item_code, warehouse
order by item_code, warehouse""" order by item_code, warehouse"""

View File

@@ -9865,3 +9865,35 @@ Leave Type Allocation,Zuordnung Abwesenheitsarten,
From Lead,Aus Lead, From Lead,Aus Lead,
From Opportunity,Aus Chance, From Opportunity,Aus Chance,
Publish in Website,Auf Webseite veröffentlichen, Publish in Website,Auf Webseite veröffentlichen,
Total Allocated Leave(s),Gesamte zugewiesene Urlaubstage,
Expired Leave(s),Verfallene Urlaubstage,
Used Leave(s),Verbrauchte Urlaubstage,
Leave(s) Pending Approval,Urlaubstage zur Genehmigung ausstehend,
Available Leave(s),Verfügbare Urlaubstage,
Party Specific Item,Parteispezifischer Artikel,
Active Customers,Aktive Kunden,
Annual Sales,Jährlicher Umsatz,
Total Outgoing Bills,Ausgangsrechnungen insgesamt,
Total Incoming Bills,Eingangsrechnungen insgesamt,
Total Incoming Payment,Zahlungseingang insgesamt,
Total Outgoing Payment,Zahlungsausgang insgesamt,
Incoming Bills (Purchase Invoice),Eingehende Rechnungen (Eingangsrechnung),
Outgoing Bills (Sales Invoice),Ausgehende Rechnungen (Ausgangsrechnung),
Accounts Receivable Ageing,Fälligkeit Forderungen,
Accounts Payable Ageing,Fälligkeit Verbindlichkeiten,
Budget Variance,Budgetabweichung,
Based On Value,Basierend auf Wert,
Restrict Items Based On,Artikel einschränken auf Basis von,
Earnings & Deductions,Erträge & Abzüge,
Is Process Loss,Ist Prozessverlust,
Is Finished Item,Ist fertiger Artikel,
Is Scrap Item,Ist Schrott,
Issue a debit note with 0 qty against an existing Sales Invoice,Lastschrift mit Menge 0 gegen eine bestehende Ausgangsrechnung ausstellen,
Show Remarks,Bemerkungen anzeigen,
Website Item,Webseiten-Artikel,
Update Property,Eigenschaft aktualisieren,
Recurring Sales Invoice,Wiederkehrende Ausgangsrechnung,
Total Asset,Aktiva,
Total Liability,Verbindlichkeiten,
Total Equity,Eigenkapital,
Warehouse wise Stock Value,Warenwert nach Lager,
Can't render this file because it is too large.