Merge branch 'develop' of https://github.com/aerele/erpnext into ledger-summary-report

This commit is contained in:
Sugesh393
2024-12-05 21:34:36 +05:30
56 changed files with 111494 additions and 97 deletions

View File

@@ -0,0 +1,34 @@
import json
from pathlib import Path
syscohada_countries = [
"bj", # Bénin
"bf", # Burkina-Faso
"cm", # Cameroun
"cf", # Centrafrique
"ci", # Côte d'Ivoire
"cg", # Congo
"km", # Comores
"ga", # Gabon
"gn", # Guinée
"gw", # Guinée-Bissau
"gq", # Guinée Equatoriale
"ml", # Mali
"ne", # Niger
"cd", # République Démocratique du Congo
"sn", # Sénégal
"td", # Tchad
"tg", # Togo
]
folder = Path(__file__).parent
generic_charts = Path(folder).glob("syscohada*.json")
for file in generic_charts:
with open(file) as f:
chart = json.load(f)
for country in syscohada_countries:
chart["country_code"] = country
json_object = json.dumps(chart, indent=4)
with open(Path(folder, file.name.replace("syscohada", country)), "w") as outfile:
outfile.write(json_object)

View File

@@ -127,9 +127,6 @@ class JournalEntry(AccountsController):
self.set_amounts_in_company_currency()
self.validate_debit_credit_amount()
self.set_total_debit_credit()
# Do not validate while importing via data import
if not frappe.flags.in_import:
self.validate_total_debit_and_credit()
if not frappe.flags.is_reverse_depr_entry:
self.validate_against_jv()
@@ -184,6 +181,11 @@ class JournalEntry(AccountsController):
else:
return self._cancel()
def before_submit(self):
# Do not validate while importing via data import
if not frappe.flags.in_import:
self.validate_total_debit_and_credit()
def on_submit(self):
self.validate_cheque_info()
self.check_credit_limit()

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: info@erpnext.com\n"
"POT-Creation-Date: 2024-12-01 09:35+0000\n"
"PO-Revision-Date: 2024-12-02 11:56\n"
"PO-Revision-Date: 2024-12-04 14:18\n"
"Last-Translator: info@erpnext.com\n"
"Language-Team: Persian\n"
"MIME-Version: 1.0\n"
@@ -3331,7 +3331,7 @@ msgstr "پیش پرداخت"
#. Name of a DocType
#: erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.json
msgid "Advance Payment Ledger Entry"
msgstr ""
msgstr "ثبت دفتر پیش پرداخت"
#. Label of the advance_payment_status (Select) field in DocType 'Purchase
#. Order'
@@ -3811,7 +3811,7 @@ msgstr "همه سرنخ (باز)"
#: erpnext/accounts/report/general_ledger/general_ledger.html:68
msgid "All Parties "
msgstr ""
msgstr "همه طرف‌ها "
#. Option for the 'Send To' (Select) field in DocType 'SMS Center'
#: erpnext/selling/doctype/sms_center/sms_center.json
@@ -4259,7 +4259,7 @@ msgstr "اجازه نرخ صفر"
#: erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
#: erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
msgid "Allow Zero Valuation Rate"
msgstr "نرخ ارزش گذاری صفر را مجاز کنید"
msgstr "نرخ ارزش گذاری صفر مجاز است"
#. Description of the 'Allow Continuous Material Consumption' (Check) field in
#. DocType 'Manufacturing Settings'
@@ -12503,7 +12503,7 @@ msgstr "هزینه شرکت (CTC)"
#. Title of an incoterm
#: erpnext/setup/doctype/incoterm/incoterms.csv:9
msgid "Cost, Insurance and Freight"
msgstr ""
msgstr "هزینه، بیمه و حمل و نقل"
#. Label of the costing (Tab Break) field in DocType 'BOM'
#. Label of the currency_detail (Section Break) field in DocType 'BOM Creator'
@@ -12870,7 +12870,7 @@ msgstr "ایجاد کارت کار بر اساس اندازه دسته ای"
#: erpnext/accounts/doctype/payment_order/payment_order.js:39
msgid "Create Journal Entries"
msgstr ""
msgstr "ایجاد ثبت دفتر روزنامه"
#: erpnext/accounts/doctype/share_transfer/share_transfer.js:18
msgid "Create Journal Entry"
@@ -13040,7 +13040,7 @@ msgstr "یک دارایی ترکیبی جدید ایجاد کنید"
#: erpnext/stock/doctype/item/item.js:611
#: erpnext/stock/doctype/item/item.js:765
msgid "Create a variant with the template image."
msgstr ""
msgstr "ایجاد یک گونه با تصویر قالب."
#: erpnext/stock/stock_ledger.py:1831
msgid "Create an incoming stock transaction for the Item."
@@ -13054,7 +13054,7 @@ msgstr "ایجاد پیش فاکتور های مشتری"
#. Settings'
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
msgid "Create in Draft Status"
msgstr ""
msgstr "ایجاد در وضعیت پیش نویس"
#. Description of the 'Create Missing Party' (Check) field in DocType 'Opening
#. Invoice Creation Tool'
@@ -13092,7 +13092,7 @@ msgstr "ایجاد ابعاد..."
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js:92
msgid "Creating Journal Entries..."
msgstr ""
msgstr "در حال ایجاد ثبت دفتر روزنامه..."
#: erpnext/stock/doctype/packing_slip/packing_slip.js:42
msgid "Creating Packing Slip ..."
@@ -17421,7 +17421,7 @@ msgstr "آیا واقعاً می خواهید این دارایی از بین ر
#: erpnext/stock/doctype/stock_settings/stock_settings.js:44
msgid "Do you still want to enable negative inventory?"
msgstr ""
msgstr "آیا همچنان می خواهید موجودی منفی را فعال کنید؟"
#: erpnext/public/js/controllers/transaction.js:1040
msgid "Do you want to clear the selected {0}?"
@@ -17625,7 +17625,7 @@ msgstr "دانلود PDF"
#: erpnext/buying/doctype/request_for_quotation/request_for_quotation.js:149
msgid "Download PDF for Supplier"
msgstr ""
msgstr "دانلود PDF برای تامین کننده"
#. Label of the download_template (Button) field in DocType 'Bank Statement
#. Import'
@@ -19534,11 +19534,11 @@ msgstr "حساب هزینه برای مورد {0} اجباری است"
#: erpnext/assets/doctype/asset_repair/asset_repair.py:98
msgid "Expense account not present in Purchase Invoice {0}"
msgstr ""
msgstr "حساب هزینه در فاکتور خرید {0} وجود ندارد"
#: erpnext/assets/doctype/asset_repair/asset_repair.py:83
msgid "Expense item not present in Purchase Invoice"
msgstr ""
msgstr "آیتم هزینه در فاکتور خرید وجود ندارد"
#: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py:42
#: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:61
@@ -20562,7 +20562,7 @@ msgstr "فوت"
#. Name of a UOM
#: erpnext/setup/setup_wizard/data/uom_data.json
msgid "Foot Of Water"
msgstr ""
msgstr "فوت آب"
#. Name of a UOM
#: erpnext/setup/setup_wizard/data/uom_data.json
@@ -24186,7 +24186,7 @@ msgstr "نوع پرداخت نادرست"
#: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py:93
msgid "Incorrect Reference Document (Purchase Receipt Item)"
msgstr ""
msgstr "سند مرجع نادرست (آیتم رسید خرید)"
#. Name of a report
#: erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.json
@@ -24701,7 +24701,7 @@ msgstr ""
#: erpnext/accounts/doctype/payment_request/payment_request.py:121
msgid "Invalid Amount"
msgstr ""
msgstr "مبلغ نامعتبر"
#: erpnext/controllers/item_variant.py:128
msgid "Invalid Attribute"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: info@erpnext.com\n"
"POT-Creation-Date: 2024-12-01 09:35+0000\n"
"PO-Revision-Date: 2024-12-02 11:56\n"
"PO-Revision-Date: 2024-12-04 14:18\n"
"Last-Translator: info@erpnext.com\n"
"Language-Team: Swedish\n"
"MIME-Version: 1.0\n"
@@ -4162,7 +4162,7 @@ msgstr "Tillåt Retur"
#. DocType 'Stock Settings'
#: erpnext/stock/doctype/stock_settings/stock_settings.json
msgid "Allow Internal Transfers at Arm's Length Price"
msgstr "Tillåt Interna Överföringar till Marknad Pris"
msgstr "Tillåt Interna Överföringar till Marknadsmässig Pris"
#. Label of the allow_multiple_items (Check) field in DocType 'Buying Settings'
#: erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -5495,7 +5495,7 @@ msgstr "Eftersom det finns reserverat lager kan du inte inaktivera {0}."
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:949
msgid "As there are sufficient Sub Assembly Items, Work Order is not required for Warehouse {0}."
msgstr "Eftersom det finns tillräckligt med Undermontering Artiklar erfordras inte Arbetsorder för Lager {0}."
msgstr "Eftersom det finns tillräckligt med Underenhet Artiklar erfordras inte Arbetsorder för Lager {0}."
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:1647
msgid "As there are sufficient raw materials, Material Request is not required for Warehouse {0}."
@@ -14314,7 +14314,7 @@ msgstr "Kund Lokal Inköp Order Nummer"
#: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.json
#: erpnext/accounts/workspace/financial_reports/financial_reports.json
msgid "Customer Ledger Summary"
msgstr "Kund Register Översikt"
msgstr "Kund Register"
#. Label of the customer_contact_mobile (Small Text) field in DocType 'Purchase
#. Order'
@@ -23267,7 +23267,7 @@ msgstr "Om vald delas betalt belopp och fördelas enligt belopp i betalning sche
#. DocType 'Production Plan'
#: erpnext/manufacturing/doctype/production_plan/production_plan.json
msgid "If this checkbox is enabled, then the system wont run the MRP for the available sub-assembly items."
msgstr "Om vald kommer systemet inte att köra Material Resurs Planering för tillgängliga undermontering artiklar."
msgstr "Om vald kommer systemet inte att köra Material Resurs Planering för tillgängliga underenhet artiklar."
#. Description of the 'Follow Calendar Months' (Check) field in DocType
#. 'Subscription'
@@ -23334,7 +23334,7 @@ msgstr "Om man behöver stämma av specifika transaktioner mot varandra, välj d
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:954
msgid "If you still want to proceed, please disable 'Skip Available Sub Assembly Items' checkbox."
msgstr "Om du fortfarande vill fortsätta, avmarkera \"Hoppa över tillgängliga undermontering artiklar\"."
msgstr "Om du fortfarande vill fortsätta, avmarkera \"Hoppa över tillgängliga underenhet artiklar\"."
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:1652
msgid "If you still want to proceed, please enable {0}."
@@ -23944,7 +23944,7 @@ msgstr "I Lager"
#. (Check) field in DocType 'Manufacturing Settings'
#: erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
msgid "In the case of 'Use Multi-Level BOM' in a work order, if the user wishes to add sub-assembly costs to Finished Goods items without using a job card as well the scrap items, then this option needs to be enable."
msgstr "I fall att 'Använd Flernivå Stycklista' används i arbetsorder, om användare vill lägga till undermontering kostnader till färdiga artiklar utan att använda jobbkort samt rest artiklar, måste detta alternativ vara aktiverad."
msgstr "I fall att 'Använd Flernivå Stycklista' används i arbetsorder, om användare vill lägga till underenhet kostnader till färdiga artiklar utan att använda jobbkort samt rest artiklar, måste detta alternativ vara aktiverad."
#: erpnext/accounts/doctype/loyalty_program/loyalty_program.js:12
msgid "In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent"
@@ -24127,7 +24127,7 @@ msgstr "Inkludera Säkerhet Lager i Begärd Kvantitet Beräkning"
#: erpnext/manufacturing/report/production_planning_report/production_planning_report.js:87
msgid "Include Sub-assembly Raw Materials"
msgstr "Inkludera Undermontering Råmaterial"
msgstr "Inkludera Underenhet Råmaterial"
#. Label of the include_subcontracted_items (Check) field in DocType
#. 'Production Plan'
@@ -24165,7 +24165,7 @@ msgstr "Inkluderad i Brutto Resultat"
#. Entry'
#: erpnext/stock/doctype/stock_entry/stock_entry.json
msgid "Including items for sub assemblies"
msgstr "Inklusive Artiklar för Undermontering"
msgstr "Inklusive artiklar för underenhet"
#. Option for the 'Root Type' (Select) field in DocType 'Account'
#. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge'
@@ -35916,7 +35916,7 @@ msgstr "Kontinuerlig Lager Hantering erfordras för bolag {0} om man ska kunna s
#. Label of the personal_details (Tab Break) field in DocType 'Employee'
#: erpnext/setup/doctype/employee/employee.json
msgid "Personal"
msgstr "Personal"
msgstr "Personligt"
#. Option for the 'Preferred Contact Email' (Select) field in DocType
#. 'Employee'
@@ -44461,7 +44461,7 @@ msgstr "Rad # {0}: Välj Stycklista Nummer för Montering Artiklar"
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:932
msgid "Row #{0}: Please select the Sub Assembly Warehouse"
msgstr "Rad # {0}: Välj Undermontering Lager"
msgstr "Rad #{0}: Välj Underenhet Lager"
#: erpnext/stock/doctype/item/item.py:500
msgid "Row #{0}: Please set reorder quantity"
@@ -50390,7 +50390,7 @@ msgstr "Underenhet Artikel Kod"
#: erpnext/public/js/bom_configurator/bom_configurator.bundle.js:403
msgid "Sub Assembly Item is mandatory"
msgstr "Undermontering artikel erfordras"
msgstr "Underenhet artikel erfordras"
#. Label of the section_break_24 (Section Break) field in DocType 'Production
#. Plan'
@@ -54403,7 +54403,7 @@ msgstr "Att använda annan finans register, inaktivera \"Inkludera Standard Fina
#: erpnext/selling/page/point_of_sale/pos_controller.js:192
msgid "Toggle Recent Orders"
msgstr "Växla Senaste Ordrar"
msgstr "Ändra Senaste Ordrar"
#. Label of the token_endpoint (Data) field in DocType 'QuickBooks Migrator'
#: erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: info@erpnext.com\n"
"POT-Creation-Date: 2024-12-01 09:35+0000\n"
"PO-Revision-Date: 2024-12-01 11:47\n"
"PO-Revision-Date: 2024-12-04 14:18\n"
"Last-Translator: info@erpnext.com\n"
"Language-Team: Turkish\n"
"MIME-Version: 1.0\n"
@@ -833,7 +833,7 @@ msgid "<span class=\"h4\"><b>Your Shortcuts\n"
"\t\t\n"
"\t\t\t\n"
"\t\t</b></span>"
msgstr "<span class=\"h4\"><b>Kısayollarınız\n"
msgstr "<span class=\"h4\"><b>Kısayollar\n"
"\t\t\t\n"
"\t\t\n"
"\t\t\t\n"
@@ -858,7 +858,7 @@ msgstr "<span class=\"h4\"><b>Kısayollarınız\n"
#: erpnext/setup/workspace/home/home.json
#: erpnext/support/workspace/support/support.json
msgid "<span class=\"h4\"><b>Your Shortcuts</b></span>"
msgstr "<span class=\"h4\"><b>Kısayollarınız</b></span>"
msgstr "<span class=\"h4\"><b>Kısayollar</b></span>"
#: erpnext/accounts/doctype/payment_request/payment_request.py:998
msgid "<strong>Grand Total:</strong> {0}"
@@ -3903,7 +3903,7 @@ msgstr "Tüm Müşteri Adayları (Açık)"
#: erpnext/accounts/report/general_ledger/general_ledger.html:68
msgid "All Parties "
msgstr ""
msgstr "Tüm Partiler "
#. Option for the 'Send To' (Select) field in DocType 'SMS Center'
#: erpnext/selling/doctype/sms_center/sms_center.json
@@ -17641,7 +17641,7 @@ msgstr "Etki Alanı Ayarları"
#. Invoice'
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.json
msgid "Don't Create Loyalty Points"
msgstr ""
msgstr "Sadakat Puanları Oluşturma"
#. Label of the dont_reserve_sales_order_qty_on_sales_return (Check) field in
#. DocType 'Selling Settings'
@@ -34467,7 +34467,7 @@ msgstr "Ana Depo"
#: erpnext/edi/doctype/code_list/code_list_import.py:39
msgid "Parsing Error"
msgstr ""
msgstr "Birleştirme Hatası"
#. Option for the 'Status' (Select) field in DocType 'Subcontracting Order'
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json
@@ -39432,7 +39432,7 @@ msgstr "Yayınlanma Tarihi"
#. Label of the publisher (Data) field in DocType 'Code List'
#: erpnext/edi/doctype/code_list/code_list.json
msgid "Publisher"
msgstr ""
msgstr "Yayınlayan"
#. Label of the publisher_id (Data) field in DocType 'Code List'
#: erpnext/edi/doctype/code_list/code_list.json
@@ -40175,7 +40175,7 @@ msgstr "Miktar "
#: erpnext/selling/doctype/sales_order_item/sales_order_item.json
#: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
msgid "Qty (Company)"
msgstr ""
msgstr "Miktar (Şirket)"
#. Label of the actual_qty (Float) field in DocType 'Sales Invoice Item'
#. Label of the actual_qty (Float) field in DocType 'Quotation Item'
@@ -40186,7 +40186,7 @@ msgstr ""
#: erpnext/selling/doctype/sales_order_item/sales_order_item.json
#: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
msgid "Qty (Warehouse)"
msgstr ""
msgstr "Miktar (Depo)"
#. Label of the qty_after_transaction (Float) field in DocType 'Stock Ledger
#. Entry'

View File

@@ -264,6 +264,24 @@ class BOM(WebsiteGenerator):
self.update_cost(update_parent=False, from_child_bom=True, update_hour_rate=False, save=False)
self.set_process_loss_qty()
self.validate_scrap_items()
self.set_default_uom()
def set_default_uom(self):
if not self.get("items"):
return
item_wise_uom = frappe._dict(
frappe.get_all(
"Item",
filters={"name": ("in", [item.item_code for item in self.items])},
fields=["name", "stock_uom"],
as_list=1,
)
)
for row in self.get("items"):
if row.stock_uom != item_wise_uom.get(row.item_code):
row.stock_uom = item_wise_uom.get(row.item_code)
def get_context(self, context):
context.parents = [{"name": "boms", "title": _("All BOMs")}]

View File

@@ -763,6 +763,26 @@ class TestBOM(IntegrationTestCase):
self.assertTrue("_Test RM Item 2 Fixed Asset Item" not in items)
self.assertTrue("_Test RM Item 3 Manufacture Item" in items)
def test_bom_raw_materials_stock_uom(self):
rm_item = make_item(
properties={"is_stock_item": 1, "valuation_rate": 1000.0, "stock_uom": "Nos"}
).name
fg_item = make_item(properties={"is_stock_item": 1}).name
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
bom = make_bom(item=fg_item, raw_materials=[rm_item], do_not_submit=True)
for row in bom.items:
self.assertEqual(row.stock_uom, "Nos")
frappe.db.set_value("Item", rm_item, "stock_uom", "Kg")
bom.items[0].qty = 2
bom.save()
for row in bom.items:
self.assertEqual(row.stock_uom, "Kg")
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})

View File

@@ -243,7 +243,7 @@
"depends_on": "eval:!doc.__islocal",
"fieldname": "download_materials_required",
"fieldtype": "Button",
"label": "Download Materials Request Plan"
"label": "Download Required Materials"
},
{
"fieldname": "get_items_for_mr",
@@ -398,7 +398,7 @@
"collapsible": 1,
"fieldname": "download_materials_request_plan_section_section",
"fieldtype": "Section Break",
"label": "Download Materials Request Plan Section"
"label": "Preview Required Materials"
},
{
"default": "0",
@@ -439,7 +439,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-03-27 13:10:19.928403",
"modified": "2024-12-04 11:55:03.108971",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Plan",

View File

@@ -44,9 +44,7 @@ class ProductionPlan(Document):
from erpnext.manufacturing.doctype.material_request_plan_item.material_request_plan_item import (
MaterialRequestPlanItem,
)
from erpnext.manufacturing.doctype.production_plan_item.production_plan_item import (
ProductionPlanItem,
)
from erpnext.manufacturing.doctype.production_plan_item.production_plan_item import ProductionPlanItem
from erpnext.manufacturing.doctype.production_plan_item_reference.production_plan_item_reference import (
ProductionPlanItemReference,
)
@@ -1085,24 +1083,33 @@ def download_raw_materials(doc, warehouses=None):
frappe.flags.show_qty_in_stock_uom = 1
items = get_items_for_material_requests(doc, warehouses=warehouses, get_parent_warehouse_data=True)
duplicate_item_wh_list = frappe._dict()
for d in items:
item_list.append(
[
d.get("item_code"),
d.get("item_name"),
d.get("description"),
d.get("stock_uom"),
d.get("warehouse"),
d.get("required_bom_qty"),
d.get("projected_qty"),
d.get("actual_qty"),
d.get("ordered_qty"),
d.get("planned_qty"),
d.get("reserved_qty_for_production"),
d.get("safety_stock"),
d.get("quantity"),
]
)
key = (d.get("item_code"), d.get("warehouse"))
if key in duplicate_item_wh_list:
rm_data = duplicate_item_wh_list[key]
rm_data[12] += d.get("quantity")
continue
rm_data = [
d.get("item_code"),
d.get("item_name"),
d.get("description"),
d.get("stock_uom"),
d.get("warehouse"),
d.get("required_bom_qty"),
d.get("projected_qty"),
d.get("actual_qty"),
d.get("ordered_qty"),
d.get("planned_qty"),
d.get("reserved_qty_for_production"),
d.get("safety_stock"),
d.get("quantity"),
]
duplicate_item_wh_list[key] = rm_data
item_list.append(rm_data)
if not doc.get("for_warehouse"):
row = {"item_code": d.get("item_code")}

View File

@@ -58,10 +58,10 @@ frappe.ui.form.on("Timesheet", {
}
if (frm.doc.docstatus < 1) {
let button = "Start Timer";
let button = __("Start Timer");
$.each(frm.doc.time_logs || [], function (i, row) {
if (row.from_time <= frappe.datetime.now_datetime() && !row.completed) {
button = "Resume Timer";
button = __("Resume Timer");
}
});

View File

@@ -448,6 +448,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
get_current_tax_amount(item, tax, item_tax_map) {
var tax_rate = this._get_tax_rate(tax, item_tax_map);
var current_tax_amount = 0.0;
var current_net_amount = 0.0;
// To set row_id by default as previous row.
if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) {
@@ -460,21 +461,27 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
}
}
if(tax.charge_type == "Actual") {
current_net_amount = item.net_amount
// distribute the tax amount proportionally to each item row
var actual = flt(tax.tax_amount, precision("tax_amount", tax));
current_tax_amount = this.frm.doc.net_total ?
((item.net_amount / this.frm.doc.net_total) * actual) : 0.0;
} else if(tax.charge_type == "On Net Total") {
if (tax.account_head in item_tax_map) {
current_net_amount = item.net_amount
};
current_tax_amount = (tax_rate / 100.0) * item.net_amount;
} else if(tax.charge_type == "On Previous Row Amount") {
current_net_amount = this.frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount_for_current_item
current_tax_amount = (tax_rate / 100.0) *
this.frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount_for_current_item;
} else if(tax.charge_type == "On Previous Row Total") {
current_net_amount = this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item
current_tax_amount = (tax_rate / 100.0) *
this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
} else if (tax.charge_type == "On Item Quantity") {
// don't sum current net amount due to the field being a currency field
current_tax_amount = tax_rate * item.qty;
}
@@ -504,17 +511,16 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
item_wise_tax_amount += flt(tax_detail[key].tax_amount, precision("tax_amount", tax));
item_wise_net_amount += flt(tax_detail[key].net_amount, precision("net_amount", tax));
}
} else {
if (tax_detail && tax_detail[key])
item_wise_tax_amount += tax_detail[key].tax_amount;
item_wise_net_amount += tax_detail[key].net_amount;
} else if (tax_detail && tax_detail[key]) {
item_wise_tax_amount += tax_detail[key].tax_amount;
item_wise_net_amount += tax_detail[key].net_amount;
}
tax_detail[key] = {
tax_rate: tax_rate,
tax_amount: flt(item_wise_tax_amount, precision("base_tax_amount", tax)),
net_amount: flt(item_wise_net_amount, precision("base_net_amount", tax)),
};
tax_detail[key] = {
tax_rate: tax_rate,
tax_amount: flt(item_wise_tax_amount, precision("base_tax_amount", tax)),
net_amount: flt(item_wise_net_amount, precision("base_net_amount", tax)),
};
}
round_off_totals(tax) {

View File

@@ -146,7 +146,7 @@ frappe.ui.form.on("Sales Order", {
target: frm,
setters: [
{
label: "Supplier",
label: __("Supplier"),
fieldname: "supplier",
fieldtype: "Link",
options: "Supplier",
@@ -783,7 +783,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
target: me.frm,
setters: [
{
label: "Customer",
label: __("Customer"),
fieldname: "party_name",
fieldtype: "Link",
options: "Customer",
@@ -830,7 +830,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
} else {
const fields = [
{
label: "Items",
label: __("Items"),
fieldtype: "Table",
fieldname: "items",
description: __("Select BOM and Qty for Production"),
@@ -1191,7 +1191,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
{
fieldname: "items_for_po",
fieldtype: "Table",
label: "Select Items",
label: __("Select Items"),
fields: [
{
fieldtype: "Data",

View File

@@ -30,7 +30,7 @@ erpnext.PointOfSale.Controller = class {
fieldname: "mode_of_payment",
fieldtype: "Link",
in_list_view: 1,
label: "Mode of Payment",
label: __("Mode of Payment"),
options: "Mode of Payment",
reqd: 1,
},
@@ -38,7 +38,7 @@ erpnext.PointOfSale.Controller = class {
fieldname: "opening_amount",
fieldtype: "Currency",
in_list_view: 1,
label: "Opening Amount",
label: __("Opening Amount"),
options: "company:company_currency",
change: function () {
dialog.fields_dict.balance_details.df.data.some((d) => {
@@ -87,7 +87,7 @@ erpnext.PointOfSale.Controller = class {
{
fieldname: "balance_details",
fieldtype: "Table",
label: "Opening Balance Details",
label: __("Opening Balance Details"),
cannot_add_rows: false,
in_place_edit: true,
reqd: 1,

View File

@@ -966,13 +966,15 @@ erpnext.PointOfSale.ItemCart = class {
if (!res.length) {
transaction_container.html(
`<div class="no-transactions-placeholder">No recent transactions found</div>`
`<div class="no-transactions-placeholder">${__("No recent transactions found")}</div>`
);
return;
}
const elapsed_time = moment(res[0].posting_date + " " + res[0].posting_time).fromNow();
this.$customer_section.find(".customer-desc").html(`Last transacted ${elapsed_time}`);
this.$customer_section
.find(".customer-desc")
.html(`${__("Last transacted")} ${__(elapsed_time)}`);
res.forEach((invoice) => {
const posting_datetime = moment(invoice.posting_date + " " + invoice.posting_time).format(
@@ -997,7 +999,7 @@ erpnext.PointOfSale.ItemCart = class {
</div>
<div class="invoice-status">
<span class="indicator-pill whitespace-nowrap ${indicator_color[invoice.status]}">
<span>${invoice.status}</span>
<span>${__(invoice.status)}</span>
</span>
</div>
</div>

View File

@@ -46,7 +46,7 @@ erpnext.PointOfSale.PastOrderSummary = class {
init_email_print_dialog() {
const email_dialog = new frappe.ui.Dialog({
title: "Email Receipt",
title: __("Email Receipt"),
fields: [
{ fieldname: "email_id", fieldtype: "Data", options: "Email", label: "Email ID", reqd: 1 },
{ fieldname: "content", fieldtype: "Small Text", label: "Message (if any)" },
@@ -59,7 +59,7 @@ erpnext.PointOfSale.PastOrderSummary = class {
this.email_dialog = email_dialog;
const print_dialog = new frappe.ui.Dialog({
title: "Print Receipt",
title: __("Print Receipt"),
fields: [{ fieldname: "print", fieldtype: "Data", label: "Print Preview" }],
primary_action: () => {
this.print_receipt();
@@ -112,7 +112,7 @@ erpnext.PointOfSale.PastOrderSummary = class {
get_discount_html(doc) {
if (doc.discount_amount) {
return `<div class="summary-row-wrapper">
<div>Discount (${doc.additional_discount_percentage} %)</div>
<div>${__("Discount")} (${doc.additional_discount_percentage} %)</div>
<div>${format_currency(doc.discount_amount, doc.currency)}</div>
</div>`;
} else {

View File

@@ -589,7 +589,7 @@ erpnext.PointOfSale.Payment = class {
const remaining = grand_total - doc.paid_amount;
const change = doc.change_amount || remaining <= 0 ? -1 * remaining : undefined;
const currency = doc.currency;
const label = change ? __("Change") : __("To Be Paid");
const label = __("Change Amount");
this.$totals.html(
`<div class="col">

View File

@@ -214,13 +214,10 @@ class InventoryDimension(Document):
dimension_fields = []
if self.apply_to_all_doctypes:
for doctype in get_inventory_documents():
if field_exists(doctype[0], self.source_fieldname):
continue
dimension_fields = self.get_dimension_fields(doctype[0])
self.add_transfer_field(doctype[0], dimension_fields)
custom_fields.setdefault(doctype[0], dimension_fields)
elif not field_exists(self.document_type, self.source_fieldname):
else:
dimension_fields = self.get_dimension_fields()
self.add_transfer_field(self.document_type, dimension_fields)
@@ -239,8 +236,17 @@ class InventoryDimension(Document):
dimension_field["fieldname"] = self.target_fieldname
custom_fields["Stock Ledger Entry"] = dimension_field
filter_custom_fields = {}
if custom_fields:
create_custom_fields(custom_fields)
for doctype, fields in custom_fields.items():
if isinstance(fields, dict):
fields = [fields]
for field in fields:
if not field_exists(doctype, field["fieldname"]):
filter_custom_fields.setdefault(doctype, []).append(field)
create_custom_fields(filter_custom_fields)
def add_transfer_field(self, doctype, dimension_fields):
if doctype not in [

View File

@@ -1663,6 +1663,46 @@ class TestStockEntry(IntegrationTestCase):
mr.cancel()
mr.delete()
def test_auto_reorder_level_with_lead_time_days(self):
from erpnext.stock.reorder_item import reorder_item
item_doc = make_item(
"Test Auto Reorder Item - 002",
properties={"stock_uom": "Kg", "purchase_uom": "Nos", "is_stock_item": 1, "lead_time_days": 2},
uoms=[{"uom": "Nos", "conversion_factor": 5}],
)
if not frappe.db.exists("Item Reorder", {"parent": item_doc.name}):
item_doc.append(
"reorder_levels",
{
"warehouse_reorder_level": 0,
"warehouse_reorder_qty": 10,
"warehouse": "_Test Warehouse - _TC",
"material_request_type": "Purchase",
},
)
item_doc.save(ignore_permissions=True)
frappe.db.set_single_value("Stock Settings", "auto_indent", 1)
mr_list = reorder_item()
frappe.db.set_single_value("Stock Settings", "auto_indent", 0)
mrs = frappe.get_all(
"Material Request Item",
fields=["schedule_date"],
filters={"item_code": item_doc.name, "uom": "Nos"},
)
for mri in mrs:
self.assertEqual(getdate(mri.schedule_date), getdate(add_days(today(), 2)))
for mr in mr_list:
mr.cancel()
mr.delete()
def test_use_serial_and_batch_fields(self):
item = make_item(
"Test Use Serial and Batch Item SN Item",

View File

@@ -690,8 +690,8 @@ def is_within_valid_range(ctx: ItemDetailsCtx, tax) -> bool:
def get_item_tax_map(*, doc: str | dict | Document, tax_template: str | None = None, as_json=True):
doc = parse_json(doc)
item_tax_map = {}
for t in (t for t in (doc.get("taxes") or []) if not t.set_by_item_tax_template):
item_tax_map[t.account_head] = t.rate
for t in (t for t in (doc.get("taxes") or []) if not t.get("set_by_item_tax_template")):
item_tax_map[t.get("account_head")] = t.get("rate")
if tax_template:
template = frappe.get_cached_doc("Item Tax Template", tax_template)

View File

@@ -98,6 +98,7 @@ def _reorder_item():
"description": d.description,
"stock_uom": d.stock_uom,
"purchase_uom": d.purchase_uom,
"lead_time_days": d.lead_time_days,
}
),
)
@@ -129,6 +130,7 @@ def get_items_for_reorder() -> dict[str, list]:
item_table.brand,
item_table.variant_of,
item_table.has_variants,
item_table.lead_time_days,
)
.where(
(item_table.disabled == 0)