Merge branch 'develop' into fix/quality-inspection/status

This commit is contained in:
Sagar Sharma 2022-10-08 13:34:21 +05:30 committed by GitHub
commit 60befcd8a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 810 additions and 369 deletions

View File

@ -173,8 +173,8 @@ frappe.ui.form.on("Journal Entry", {
var update_jv_details = function(doc, r) { var update_jv_details = function(doc, r) {
$.each(r, function(i, d) { $.each(r, function(i, d) {
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts"); var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
row.account = d.account; frappe.model.set_value(row.doctype, row.name, "account", d.account)
row.balance = d.balance; frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
}); });
refresh_field("accounts"); refresh_field("accounts");
} }

View File

@ -186,8 +186,10 @@
{ {
"fetch_from": "bank_account.bank", "fetch_from": "bank_account.bank",
"fieldname": "bank", "fieldname": "bank",
"fieldtype": "Read Only", "fieldtype": "Link",
"label": "Bank" "label": "Bank",
"options": "Bank",
"read_only": 1
}, },
{ {
"fetch_from": "bank_account.bank_account_no", "fetch_from": "bank_account.bank_account_no",
@ -366,10 +368,11 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2020-09-18 12:24:14.178853", "modified": "2022-09-30 16:19:43.680025",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Payment Request", "name": "Payment Request",
"naming_rule": "By \"Naming Series\" field",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {
@ -401,5 +404,6 @@
} }
], ],
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC" "sort_order": "DESC",
"states": []
} }

View File

@ -343,7 +343,8 @@
"no_copy": 1, "no_copy": 1,
"options": "POS Invoice", "options": "POS Invoice",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"search_index": 1
}, },
{ {
"default": "0", "default": "0",
@ -1553,7 +1554,7 @@
"icon": "fa fa-file-text", "icon": "fa fa-file-text",
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-09-27 13:00:24.166684", "modified": "2022-09-30 03:49:50.455199",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "POS Invoice", "name": "POS Invoice",

View File

@ -743,7 +743,3 @@ def add_return_modes(doc, pos_profile):
]: ]:
payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company) payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company)
append_payment(payment_mode[0]) append_payment(payment_mode[0])
def on_doctype_update():
frappe.db.add_index("POS Invoice", ["return_against"])

View File

@ -1430,6 +1430,7 @@
"fieldname": "tax_withheld_vouchers", "fieldname": "tax_withheld_vouchers",
"fieldtype": "Table", "fieldtype": "Table",
"label": "Tax Withheld Vouchers", "label": "Tax Withheld Vouchers",
"no_copy": 1,
"options": "Tax Withheld Vouchers", "options": "Tax Withheld Vouchers",
"read_only": 1 "read_only": 1
} }
@ -1438,7 +1439,7 @@
"idx": 204, "idx": 204,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-09-27 11:07:55.766844", "modified": "2022-10-07 14:19:14.214157",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice", "name": "Purchase Invoice",

View File

@ -8,7 +8,7 @@ import frappe
from frappe.model.dynamic_links import get_dynamic_link_map from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.model.naming import make_autoname from frappe.model.naming import make_autoname
from frappe.tests.utils import change_settings from frappe.tests.utils import change_settings
from frappe.utils import add_days, flt, getdate, nowdate from frappe.utils import add_days, flt, getdate, nowdate, today
import erpnext import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@ -3196,6 +3196,37 @@ class TestSalesInvoice(unittest.TestCase):
"Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled "Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled
) )
def test_batch_expiry_for_sales_invoice_return(self):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
from erpnext.stock.doctype.item.test_item import make_item
item = make_item(
"_Test Batch Item For Return Check",
{
"is_purchase_item": 1,
"is_stock_item": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "TBIRC.#####",
},
)
pr = make_purchase_receipt(qty=1, item_code=item.name)
batch_no = pr.items[0].batch_no
si = create_sales_invoice(qty=1, item_code=item.name, update_stock=1, batch_no=batch_no)
si.load_from_db()
batch_no = si.items[0].batch_no
self.assertTrue(batch_no)
frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
return_si = make_return_doc(si.doctype, si.name)
return_si.save().submit()
self.assertTrue(return_si.docstatus == 1)
def get_sales_invoice_for_e_invoice(): def get_sales_invoice_for_e_invoice():
si = make_sales_invoice_for_ewaybill() si = make_sales_invoice_for_ewaybill()
@ -3289,6 +3320,7 @@ def create_sales_invoice(**args):
"serial_no": args.serial_no, "serial_no": args.serial_no,
"conversion_factor": 1, "conversion_factor": 1,
"incoming_rate": args.incoming_rate or 0, "incoming_rate": args.incoming_rate or 0,
"batch_no": args.batch_no or None,
}, },
) )

View File

@ -249,6 +249,9 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
) )
else: else:
tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0 tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0
# once tds is deducted, not need to add vouchers in the invoice
voucher_wise_amount = {}
else: else:
tax_amount = get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers) tax_amount = get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers)
@ -425,7 +428,10 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
): ):
# Get net total again as TDS is calculated on net total # Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach # Grand is used to just check for threshold breach
net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") or 0.0 net_total = 0
if vouchers:
net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)")
net_total += inv.net_total net_total += inv.net_total
supp_credit_amt = net_total - cumulative_threshold supp_credit_amt = net_total - cumulative_threshold

View File

@ -188,7 +188,8 @@
"in_list_view": 1, "in_list_view": 1,
"label": "Item Group", "label": "Item Group",
"options": "Item Group", "options": "Item Group",
"read_only": 1 "read_only": 1,
"search_index": 1
}, },
{ {
"default": "1", "default": "1",
@ -234,7 +235,8 @@
"fieldname": "brand", "fieldname": "brand",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Brand", "label": "Brand",
"options": "Brand" "options": "Brand",
"search_index": 1
}, },
{ {
"collapsible": 1, "collapsible": 1,
@ -346,7 +348,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"make_attachments_public": 1, "make_attachments_public": 1,
"modified": "2022-09-13 04:05:11.614087", "modified": "2022-09-30 04:01:52.090732",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "E-commerce", "module": "E-commerce",
"name": "Website Item", "name": "Website Item",

View File

@ -403,9 +403,6 @@ def on_doctype_update():
# since route is a Text column, it needs a length for indexing # since route is a Text column, it needs a length for indexing
frappe.db.add_index("Website Item", ["route(500)"]) frappe.db.add_index("Website Item", ["route(500)"])
frappe.db.add_index("Website Item", ["item_group"])
frappe.db.add_index("Website Item", ["brand"])
def check_if_user_is_customer(user=None): def check_if_user_is_customer(user=None):
from frappe.contacts.doctype.contact.contact import get_contact_name from frappe.contacts.doctype.contact.contact import get_contact_name

View File

@ -17,6 +17,7 @@ from erpnext.manufacturing.doctype.work_order.work_order import (
close_work_order, close_work_order,
make_job_card, make_job_card,
make_stock_entry, make_stock_entry,
make_stock_return_entry,
stop_unstop, stop_unstop,
) )
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
@ -1408,6 +1409,77 @@ class TestWorkOrder(FrappeTestCase):
) )
self.assertEqual(manufacture_ste_doc2.items[1].qty, 1) self.assertEqual(manufacture_ste_doc2.items[1].qty, 1)
def test_non_consumed_material_return_against_work_order(self):
frappe.db.set_value(
"Manufacturing Settings",
None,
"backflush_raw_materials_based_on",
"Material Transferred for Manufacture",
)
item = make_item(
"Test FG Item To Test Return Case",
{
"is_stock_item": 1,
},
)
item_code = item.name
bom_doc = make_bom(
item=item_code,
source_warehouse="Stores - _TC",
raw_materials=["Test Batch MCC Keyboard", "Test Serial No BTT Headphone"],
)
# Create a work order
wo_doc = make_wo_order_test_record(production_item=item_code, qty=5)
wo_doc.save()
self.assertEqual(wo_doc.bom_no, bom_doc.name)
# Transfer material for manufacture
ste_doc = frappe.get_doc(make_stock_entry(wo_doc.name, "Material Transfer for Manufacture", 5))
for row in ste_doc.items:
row.qty += 2
row.transfer_qty += 2
nste_doc = test_stock_entry.make_stock_entry(
item_code=row.item_code, target="Stores - _TC", qty=row.qty, basic_rate=100
)
row.batch_no = nste_doc.items[0].batch_no
row.serial_no = nste_doc.items[0].serial_no
ste_doc.save()
ste_doc.submit()
ste_doc.load_from_db()
# Create a stock entry to manufacture the item
ste_doc = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 5))
for row in ste_doc.items:
if row.s_warehouse and not row.t_warehouse:
row.qty -= 2
row.transfer_qty -= 2
if row.serial_no:
serial_nos = get_serial_nos(row.serial_no)
row.serial_no = "\n".join(serial_nos[0:5])
ste_doc.save()
ste_doc.submit()
wo_doc.load_from_db()
for row in wo_doc.required_items:
self.assertEqual(row.transferred_qty, 7)
self.assertEqual(row.consumed_qty, 5)
self.assertEqual(wo_doc.status, "Completed")
return_ste_doc = make_stock_return_entry(wo_doc.name)
return_ste_doc.save()
self.assertTrue(return_ste_doc.is_return)
for row in return_ste_doc.items:
self.assertEqual(row.qty, 2)
def prepare_data_for_backflush_based_on_materials_transferred(): def prepare_data_for_backflush_based_on_materials_transferred():
batch_item_doc = make_item( batch_item_doc = make_item(

View File

@ -180,6 +180,37 @@ frappe.ui.form.on("Work Order", {
frm.trigger("make_bom"); frm.trigger("make_bom");
}); });
} }
frm.trigger("add_custom_button_to_return_components");
},
add_custom_button_to_return_components: function(frm) {
if (frm.doc.docstatus === 1 && in_list(["Closed", "Completed"], frm.doc.status)) {
let non_consumed_items = frm.doc.required_items.filter(d =>{
return flt(d.consumed_qty) < flt(d.transferred_qty - d.returned_qty)
});
if (non_consumed_items && non_consumed_items.length) {
frm.add_custom_button(__("Return Components"), function() {
frm.trigger("create_stock_return_entry");
}).addClass("btn-primary");
}
}
},
create_stock_return_entry: function(frm) {
frappe.call({
method: "erpnext.manufacturing.doctype.work_order.work_order.make_stock_return_entry",
args: {
"work_order": frm.doc.name,
},
callback: function(r) {
if(!r.exc) {
let doc = frappe.model.sync(r.message);
frappe.set_route("Form", doc[0].doctype, doc[0].name);
}
}
});
}, },
make_job_card: function(frm) { make_job_card: function(frm) {
@ -517,7 +548,8 @@ frappe.ui.form.on("Work Order Operation", {
erpnext.work_order = { erpnext.work_order = {
set_custom_buttons: function(frm) { set_custom_buttons: function(frm) {
var doc = frm.doc; var doc = frm.doc;
if (doc.docstatus === 1 && doc.status != "Closed") {
if (doc.status !== "Closed") {
frm.add_custom_button(__('Close'), function() { frm.add_custom_button(__('Close'), function() {
frappe.confirm(__("Once the Work Order is Closed. It can't be resumed."), frappe.confirm(__("Once the Work Order is Closed. It can't be resumed."),
() => { () => {
@ -525,7 +557,9 @@ erpnext.work_order = {
} }
); );
}, __("Status")); }, __("Status"));
}
if (doc.docstatus === 1 && !in_list(["Closed", "Completed"], doc.status)) {
if (doc.status != 'Stopped' && doc.status != 'Completed') { if (doc.status != 'Stopped' && doc.status != 'Completed') {
frm.add_custom_button(__('Stop'), function() { frm.add_custom_button(__('Stop'), function() {
erpnext.work_order.change_work_order_status(frm, "Stopped"); erpnext.work_order.change_work_order_status(frm, "Stopped");

View File

@ -20,6 +20,7 @@ from frappe.utils import (
nowdate, nowdate,
time_diff_in_hours, time_diff_in_hours,
) )
from pypika import functions as fn
from erpnext.manufacturing.doctype.bom.bom import ( from erpnext.manufacturing.doctype.bom.bom import (
get_bom_item_rate, get_bom_item_rate,
@ -859,6 +860,7 @@ class WorkOrder(Document):
if self.docstatus == 1: if self.docstatus == 1:
# calculate transferred qty based on submitted stock entries # calculate transferred qty based on submitted stock entries
self.update_transferred_qty_for_required_items() self.update_transferred_qty_for_required_items()
self.update_returned_qty()
# update in bin # update in bin
self.update_reserved_qty_for_production() self.update_reserved_qty_for_production()
@ -930,23 +932,62 @@ class WorkOrder(Document):
self.set_available_qty() self.set_available_qty()
def update_transferred_qty_for_required_items(self): def update_transferred_qty_for_required_items(self):
"""update transferred qty from submitted stock entries for that item against ste = frappe.qb.DocType("Stock Entry")
the work order""" ste_child = frappe.qb.DocType("Stock Entry Detail")
for d in self.required_items: query = (
transferred_qty = frappe.db.sql( frappe.qb.from_(ste)
"""select sum(qty) .inner_join(ste_child)
from `tabStock Entry` entry, `tabStock Entry Detail` detail .on((ste_child.parent == ste.name))
where .select(
entry.work_order = %(name)s ste_child.item_code,
and entry.purpose = 'Material Transfer for Manufacture' ste_child.original_item,
and entry.docstatus = 1 fn.Sum(ste_child.qty).as_("qty"),
and detail.parent = entry.name )
and (detail.item_code = %(item)s or detail.original_item = %(item)s)""", .where(
{"name": self.name, "item": d.item_code}, (ste.docstatus == 1)
)[0][0] & (ste.work_order == self.name)
& (ste.purpose == "Material Transfer for Manufacture")
& (ste.is_return == 0)
)
.groupby(ste_child.item_code)
)
d.db_set("transferred_qty", flt(transferred_qty), update_modified=False) data = query.run(as_dict=1) or []
transferred_items = frappe._dict({d.original_item or d.item_code: d.qty for d in data})
for row in self.required_items:
row.db_set(
"transferred_qty", (transferred_items.get(row.item_code) or 0.0), update_modified=False
)
def update_returned_qty(self):
ste = frappe.qb.DocType("Stock Entry")
ste_child = frappe.qb.DocType("Stock Entry Detail")
query = (
frappe.qb.from_(ste)
.inner_join(ste_child)
.on((ste_child.parent == ste.name))
.select(
ste_child.item_code,
ste_child.original_item,
fn.Sum(ste_child.qty).as_("qty"),
)
.where(
(ste.docstatus == 1)
& (ste.work_order == self.name)
& (ste.purpose == "Material Transfer for Manufacture")
& (ste.is_return == 1)
)
.groupby(ste_child.item_code)
)
data = query.run(as_dict=1) or []
returned_dict = frappe._dict({d.original_item or d.item_code: d.qty for d in data})
for row in self.required_items:
row.db_set("returned_qty", (returned_dict.get(row.item_code) or 0.0), update_modified=False)
def update_consumed_qty_for_required_items(self): def update_consumed_qty_for_required_items(self):
""" """
@ -1470,3 +1511,25 @@ def get_reserved_qty_for_production(item_code: str, warehouse: str) -> float:
) )
) )
).run()[0][0] or 0.0 ).run()[0][0] or 0.0
@frappe.whitelist()
def make_stock_return_entry(work_order):
from erpnext.stock.doctype.stock_entry.stock_entry import get_available_materials
non_consumed_items = get_available_materials(work_order)
if not non_consumed_items:
return
wo_doc = frappe.get_cached_doc("Work Order", work_order)
stock_entry = frappe.new_doc("Stock Entry")
stock_entry.from_bom = 1
stock_entry.is_return = 1
stock_entry.work_order = work_order
stock_entry.purpose = "Material Transfer for Manufacture"
stock_entry.bom_no = wo_doc.bom_no
stock_entry.add_transfered_raw_materials_in_items()
stock_entry.set_stock_entry_type()
return stock_entry

View File

@ -20,6 +20,7 @@
"column_break_11", "column_break_11",
"transferred_qty", "transferred_qty",
"consumed_qty", "consumed_qty",
"returned_qty",
"available_qty_at_source_warehouse", "available_qty_at_source_warehouse",
"available_qty_at_wip_warehouse" "available_qty_at_wip_warehouse"
], ],
@ -97,6 +98,7 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"columns": 1,
"depends_on": "eval:!parent.skip_transfer", "depends_on": "eval:!parent.skip_transfer",
"fieldname": "consumed_qty", "fieldname": "consumed_qty",
"fieldtype": "Float", "fieldtype": "Float",
@ -127,11 +129,19 @@
"fieldtype": "Currency", "fieldtype": "Currency",
"label": "Amount", "label": "Amount",
"read_only": 1 "read_only": 1
},
{
"columns": 1,
"fieldname": "returned_qty",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Returned Qty ",
"read_only": 1
} }
], ],
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2020-04-13 18:46:32.966416", "modified": "2022-09-28 10:50:43.512562",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Work Order Item", "name": "Work Order Item",
@ -140,5 +150,6 @@
"quick_entry": 1, "quick_entry": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"states": [],
"track_changes": 1 "track_changes": 1
} }

View File

@ -50,7 +50,7 @@ frappe.query_reports["Work Order Consumed Materials"] = {
label: __("Status"), label: __("Status"),
fieldname: "status", fieldname: "status",
fieldtype: "Select", fieldtype: "Select",
options: ["In Process", "Completed", "Stopped"] options: ["", "In Process", "Completed", "Stopped"]
}, },
{ {
label: __("Excess Materials Consumed"), label: __("Excess Materials Consumed"),

View File

@ -1,6 +1,8 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt # For license information, please see license.txt
from collections import defaultdict
import frappe import frappe
from frappe import _ from frappe import _
@ -18,7 +20,11 @@ def get_data(report_filters):
filters = get_filter_condition(report_filters) filters = get_filter_condition(report_filters)
wo_items = {} wo_items = {}
for d in frappe.get_all("Work Order", filters=filters, fields=fields):
work_orders = frappe.get_all("Work Order", filters=filters, fields=fields)
returned_materials = get_returned_materials(work_orders)
for d in work_orders:
d.extra_consumed_qty = 0.0 d.extra_consumed_qty = 0.0
if d.consumed_qty and d.consumed_qty > d.required_qty: if d.consumed_qty and d.consumed_qty > d.required_qty:
d.extra_consumed_qty = d.consumed_qty - d.required_qty d.extra_consumed_qty = d.consumed_qty - d.required_qty
@ -39,6 +45,28 @@ def get_data(report_filters):
return data return data
def get_returned_materials(work_orders):
raw_materials_qty = defaultdict(float)
raw_materials = frappe.get_all(
"Stock Entry",
fields=["`tabStock Entry Detail`.`item_code`", "`tabStock Entry Detail`.`qty`"],
filters=[
["Stock Entry", "is_return", "=", 1],
["Stock Entry Detail", "docstatus", "=", 1],
["Stock Entry", "work_order", "in", [d.name for d in work_orders]],
],
)
for d in raw_materials:
raw_materials_qty[d.item_code] += d.qty
for row in work_orders:
row.returned_qty = 0.0
if raw_materials_qty.get(row.raw_material_item_code):
row.returned_qty = raw_materials_qty.get(row.raw_material_item_code)
def get_fields(): def get_fields():
return [ return [
"`tabWork Order Item`.`parent`", "`tabWork Order Item`.`parent`",
@ -65,7 +93,7 @@ def get_filter_condition(report_filters):
for field in ["name", "production_item", "company", "status"]: for field in ["name", "production_item", "company", "status"]:
value = report_filters.get(field) value = report_filters.get(field)
if value: if value:
key = f"`{field}`" key = f"{field}"
filters.update({key: value}) filters.update({key: value})
return filters return filters
@ -112,4 +140,10 @@ def get_columns():
"fieldtype": "Float", "fieldtype": "Float",
"width": 100, "width": 100,
}, },
{
"label": _("Returned Qty"),
"fieldname": "returned_qty",
"fieldtype": "Float",
"width": 100,
},
] ]

View File

@ -3,6 +3,29 @@ from frappe import qb
from frappe.utils import create_batch from frappe.utils import create_batch
def remove_duplicate_entries(pl_entries):
unique_vouchers = set()
for x in pl_entries:
unique_vouchers.add(
(x.company, x.account, x.party_type, x.party, x.voucher_type, x.voucher_no, x.gle_remarks)
)
entries = []
for x in unique_vouchers:
entries.append(
frappe._dict(
company=x[0],
account=x[1],
party_type=x[2],
party=x[3],
voucher_type=x[4],
voucher_no=x[5],
gle_remarks=x[6],
)
)
return entries
def execute(): def execute():
if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"): if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"):
@ -34,6 +57,8 @@ def execute():
.run(as_dict=True) .run(as_dict=True)
) )
pl_entries = remove_duplicate_entries(pl_entries)
if pl_entries: if pl_entries:
# split into multiple batches, update and commit for each batch # split into multiple batches, update and commit for each batch
batch_size = 1000 batch_size = 1000

View File

@ -0,0 +1,115 @@
#page-order {
.main-column {
.page-content-wrapper {
.breadcrumb-container {
@media screen and (min-width: 567px) {
padding-left: var(--padding-sm);
}
}
.container.my-4 {
background-color: var(--fg-color);
@media screen and (min-width: 567px) {
padding: 1.25rem 1.5rem;
border-radius: var(--border-radius-md);
box-shadow: var(--card-shadow);
}
}
}
}
}
.indicator-container {
@media screen and (max-width: 567px) {
padding-bottom: 0.8rem;
}
}
.order-items {
padding: 1.5rem 0;
border-bottom: 1px solid var(--border-color);
color: var(--gray-700);
@media screen and (max-width: 567px) {
align-items: flex-start !important;
}
.col-2 {
@media screen and (max-width: 567px) {
flex: auto;
max-width: 28%;
}
}
.order-item-name {
font-size: var(--text-base);
font-weight: 500;
}
.btn:focus,
.btn:hover {
background-color: var(--control-bg);
}
.col-6 {
@media screen and (max-width: 567px) {
max-width: 100%;
}
&.order-item-name {
font-size: var(--text-base);
}
}
}
.item-grand-total {
font-size: var(--text-base);
}
.list-item-name,
.item-total,
.order-container,
.order-qty {
font-size: var(--text-md);
}
.d-s-n {
@media screen and (max-width: 567px) {
display: none;
}
}
.d-l-n {
@media screen and (min-width: 567px) {
display: none;
}
}
.border-btm {
border-bottom: 1px solid var(--border-color);
}
.order-taxes {
display: flex;
@media screen and (min-width: 567px) {
justify-content: flex-end;
}
.col-4 {
padding-right: 0;
.col-8 {
padding-left: 0;
padding-right: 0;
}
@media screen and (max-width: 567px) {
padding-left: 0;
flex: auto;
max-width: 100%;
}
}
}

View File

@ -1,3 +1,4 @@
@import './order-page';
.filter-options { .filter-options {
max-height: 300px; max-height: 300px;
@ -32,19 +33,29 @@
height: 24px; height: 24px;
} }
.website-list .result { .website-list {
margin-top: 2rem; background-color: var(--fg-color);
} padding: 0 var(--padding-lg);
border-radius: var(--border-radius-md);
.result { @media screen and (max-width: 567px) {
border-bottom: 1px solid var(--border-color); margin-left: -2rem;
}
&.result {
border-bottom: 1px solid var(--border-color);
}
} }
.transaction-list-item { .transaction-list-item {
padding: 1rem 0; padding: 1rem 0;
border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
position: relative; position: relative;
&:only-child, &:last-child {
border: 0;
}
a.transaction-item-link { a.transaction-item-link {
position: absolute; position: absolute;
top: 0; top: 0;
@ -68,3 +79,13 @@
line-height: 1.3; line-height: 1.3;
} }
} }
.list-item-name, .item-total {
font-size: var(--font-size-sm);
}
.items-preview {
@media screen and (max-width: 567px) {
margin-top: 1rem;
}
}

View File

@ -37,8 +37,10 @@ class Bin(Document):
self.set_projected_qty() self.set_projected_qty()
self.db_set("reserved_qty_for_production", flt(self.reserved_qty_for_production)) self.db_set(
self.db_set("projected_qty", self.projected_qty) "reserved_qty_for_production", flt(self.reserved_qty_for_production), update_modified=True
)
self.db_set("projected_qty", self.projected_qty, update_modified=True)
def update_reserved_qty_for_sub_contracting(self, subcontract_doctype="Subcontracting Order"): def update_reserved_qty_for_sub_contracting(self, subcontract_doctype="Subcontracting Order"):
# reserved qty # reserved qty
@ -118,9 +120,9 @@ class Bin(Document):
else: else:
reserved_qty_for_sub_contract = 0 reserved_qty_for_sub_contract = 0
self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract) self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract, update_modified=True)
self.set_projected_qty() self.set_projected_qty()
self.db_set("projected_qty", self.projected_qty) self.db_set("projected_qty", self.projected_qty, update_modified=True)
def on_doctype_update(): def on_doctype_update():
@ -193,4 +195,5 @@ def update_qty(bin_name, args):
"planned_qty": planned_qty, "planned_qty": planned_qty,
"projected_qty": projected_qty, "projected_qty": projected_qty,
}, },
update_modified=True,
) )

View File

@ -6,7 +6,7 @@ import json
import frappe import frappe
from frappe.tests.utils import FrappeTestCase from frappe.tests.utils import FrappeTestCase
from frappe.utils import cstr, flt, nowdate, nowtime from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today
from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.utils import get_balance_on from erpnext.accounts.utils import get_balance_on
@ -1091,6 +1091,36 @@ class TestDeliveryNote(FrappeTestCase):
frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype}) frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype})
) )
def test_batch_expiry_for_delivery_note(self):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
item = make_item(
"_Test Batch Item For Return Check",
{
"is_purchase_item": 1,
"is_stock_item": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "TBIRC.#####",
},
)
pi = make_purchase_receipt(qty=1, item_code=item.name)
dn = create_delivery_note(qty=1, item_code=item.name, batch_no=pi.items[0].batch_no)
dn.load_from_db()
batch_no = dn.items[0].batch_no
self.assertTrue(batch_no)
frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
return_dn = make_return_doc(dn.doctype, dn.name)
return_dn.save().submit()
self.assertTrue(return_dn.docstatus == 1)
def create_delivery_note(**args): def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note") dn = frappe.new_doc("Delivery Note")
@ -1117,6 +1147,7 @@ def create_delivery_note(**args):
"expense_account": args.expense_account or "Cost of Goods Sold - _TC", "expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no, "serial_no": args.serial_no,
"batch_no": args.batch_no or None,
"target_warehouse": args.target_warehouse, "target_warehouse": args.target_warehouse,
}, },
) )

View File

@ -183,7 +183,7 @@ class PickList(Document):
frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx)) frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx))
item_code = item.item_code item_code = item.item_code
reference = item.sales_order_item or item.material_request_item reference = item.sales_order_item or item.material_request_item
key = (item_code, item.uom, item.warehouse, reference) key = (item_code, item.uom, item.warehouse, item.batch_no, reference)
item.idx = None item.idx = None
item.name = None item.name = None

View File

@ -128,6 +128,9 @@ def repost(doc):
if not frappe.db.exists("Repost Item Valuation", doc.name): if not frappe.db.exists("Repost Item Valuation", doc.name):
return return
# This is to avoid TooManyWritesError in case of large reposts
frappe.db.MAX_WRITES_PER_TRANSACTION *= 4
doc.set_status("In Progress") doc.set_status("In Progress")
if not frappe.flags.in_test: if not frappe.flags.in_test:
frappe.db.commit() frappe.db.commit()

View File

@ -148,19 +148,19 @@
"search_index": 1 "search_index": 1
}, },
{ {
"depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"",
"fieldname": "purchase_order", "fieldname": "purchase_order",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Purchase Order", "label": "Purchase Order",
"options": "Purchase Order" "options": "Purchase Order"
}, },
{ {
"depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"",
"fieldname": "subcontracting_order", "fieldname": "subcontracting_order",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Subcontracting Order", "label": "Subcontracting Order",
"options": "Subcontracting Order" "options": "Subcontracting Order"
}, },
{ {
"depends_on": "eval:doc.purpose==\"Sales Return\"", "depends_on": "eval:doc.purpose==\"Sales Return\"",
"fieldname": "delivery_note_no", "fieldname": "delivery_note_no",
@ -616,6 +616,7 @@
"fieldname": "is_return", "fieldname": "is_return",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 1, "hidden": 1,
"in_list_view": 1,
"label": "Is Return", "label": "Is Return",
"no_copy": 1, "no_copy": 1,
"print_hide": 1, "print_hide": 1,
@ -627,7 +628,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-05-02 05:21:39.060501", "modified": "2022-10-07 14:39:51.943770",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock Entry", "name": "Stock Entry",

View File

@ -1212,13 +1212,19 @@ class StockEntry(StockController):
def update_work_order(self): def update_work_order(self):
def _validate_work_order(pro_doc): def _validate_work_order(pro_doc):
msg, title = "", ""
if flt(pro_doc.docstatus) != 1: if flt(pro_doc.docstatus) != 1:
frappe.throw(_("Work Order {0} must be submitted").format(self.work_order)) msg = f"Work Order {self.work_order} must be submitted"
if pro_doc.status == "Stopped": if pro_doc.status == "Stopped":
frappe.throw( msg = f"Transaction not allowed against stopped Work Order {self.work_order}"
_("Transaction not allowed against stopped Work Order {0}").format(self.work_order)
) if self.is_return and pro_doc.status not in ["Completed", "Closed"]:
title = _("Stock Return")
msg = f"Work Order {self.work_order} must be completed or closed"
if msg:
frappe.throw(_(msg), title=title)
if self.job_card: if self.job_card:
job_doc = frappe.get_doc("Job Card", self.job_card) job_doc = frappe.get_doc("Job Card", self.job_card)
@ -1754,10 +1760,12 @@ class StockEntry(StockController):
for key, row in available_materials.items(): for key, row in available_materials.items():
remaining_qty_to_produce = flt(wo_data.trans_qty) - flt(wo_data.produced_qty) remaining_qty_to_produce = flt(wo_data.trans_qty) - flt(wo_data.produced_qty)
if remaining_qty_to_produce <= 0: if remaining_qty_to_produce <= 0 and not self.is_return:
continue continue
qty = (flt(row.qty) * flt(self.fg_completed_qty)) / remaining_qty_to_produce qty = flt(row.qty)
if not self.is_return:
qty = (flt(row.qty) * flt(self.fg_completed_qty)) / remaining_qty_to_produce
item = row.item_details item = row.item_details
if cint(frappe.get_cached_value("UOM", item.stock_uom, "must_be_whole_number")): if cint(frappe.get_cached_value("UOM", item.stock_uom, "must_be_whole_number")):
@ -1781,6 +1789,9 @@ class StockEntry(StockController):
self.update_item_in_stock_entry_detail(row, item, qty) self.update_item_in_stock_entry_detail(row, item, qty)
def update_item_in_stock_entry_detail(self, row, item, qty) -> None: def update_item_in_stock_entry_detail(self, row, item, qty) -> None:
if not qty:
return
ste_item_details = { ste_item_details = {
"from_warehouse": item.warehouse, "from_warehouse": item.warehouse,
"to_warehouse": "", "to_warehouse": "",
@ -1794,6 +1805,9 @@ class StockEntry(StockController):
"original_item": item.original_item, "original_item": item.original_item,
} }
if self.is_return:
ste_item_details["to_warehouse"] = item.s_warehouse
if row.serial_nos: if row.serial_nos:
serial_nos = row.serial_nos serial_nos = row.serial_nos
if item.batch_no: if item.batch_no:

View File

@ -1,8 +1,13 @@
frappe.listview_settings['Stock Entry'] = { frappe.listview_settings['Stock Entry'] = {
add_fields: ["`tabStock Entry`.`from_warehouse`", "`tabStock Entry`.`to_warehouse`", add_fields: ["`tabStock Entry`.`from_warehouse`", "`tabStock Entry`.`to_warehouse`",
"`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`"], "`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`",
"`tabStock Entry`.`is_return`"],
get_indicator: function (doc) { get_indicator: function (doc) {
if (doc.docstatus === 0) { debugger
if(doc.is_return===1 && doc.purpose === "Material Transfer for Manufacture") {
return [__("Material Returned from WIP"), "orange",
"is_return,=,1|purpose,=,Material Transfer for Manufacture|docstatus,<,2"];
} else if (doc.docstatus === 0) {
return [__("Draft"), "red", "docstatus,=,0"]; return [__("Draft"), "red", "docstatus,=,0"];
} else if (doc.purpose === 'Send to Warehouse' && doc.per_transferred < 100) { } else if (doc.purpose === 'Send to Warehouse' && doc.per_transferred < 100) {

View File

@ -153,7 +153,9 @@ class StockLedgerEntry(Document):
def validate_batch(self): def validate_batch(self):
if self.batch_no and self.voucher_type != "Stock Entry": if self.batch_no and self.voucher_type != "Stock Entry":
if self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0: if (self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0) or (
self.voucher_type in ["Delivery Note", "Sales Invoice"] and self.actual_qty > 0
):
return return
expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date") expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date")

View File

@ -1053,7 +1053,7 @@ class update_entries_after(object):
updated_values = {"actual_qty": data.qty_after_transaction, "stock_value": data.stock_value} updated_values = {"actual_qty": data.qty_after_transaction, "stock_value": data.stock_value}
if data.valuation_rate is not None: if data.valuation_rate is not None:
updated_values["valuation_rate"] = data.valuation_rate updated_values["valuation_rate"] = data.valuation_rate
frappe.db.set_value("Bin", bin_name, updated_values) frappe.db.set_value("Bin", bin_name, updated_values, update_modified=True)
def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False): def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False):

View File

@ -6,7 +6,7 @@
aria-label="{{ _('Your email address...') }}" aria-label="{{ _('Your email address...') }}"
aria-describedby="footer-subscribe-button"> aria-describedby="footer-subscribe-button">
<div class="input-group-append"> <div class="input-group-append">
<button class="btn btn-sm btn-default" <button class="btn btn-sm btn-secondary pl-3 pr-3 ml-2"
type="button" id="footer-subscribe-button">{{ _("Get Updates") }}</button> type="button" id="footer-subscribe-button">{{ _("Get Updates") }}</button>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
{% macro product_image_square(website_image, css_class="") %} {% macro product_image_square(website_image, css_class="") %}
<div class="product-image product-image-square <div class="product-image product-image-square h-100 rounded
{% if not website_image -%} missing-image {%- endif %} {{ css_class }}" {% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
{% if website_image -%} {% if website_image -%}
style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');" style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');"

View File

@ -3,7 +3,7 @@
{% macro item_name_and_description(d) %} {% macro item_name_and_description(d) %}
<div class="row item_name_and_description"> <div class="row item_name_and_description">
<div class="col-xs-4 col-sm-2 order-image-col"> <div class="col-xs-4 col-sm-2 order-image-col">
<div class="order-image"> <div class="order-image h-100">
{% if d.thumbnail or d.image %} {% if d.thumbnail or d.image %}
{{ product_image(d.thumbnail or d.image, no_border=True) }} {{ product_image(d.thumbnail or d.image, no_border=True) }}
{% else %} {% else %}
@ -18,6 +18,9 @@
<div class="text-muted small item-description"> <div class="text-muted small item-description">
{{ html2text(d.description) | truncate(140) }} {{ html2text(d.description) | truncate(140) }}
</div> </div>
<span class="text-muted mt-2 d-l-n order-qty">
{{ _("Qty ") }}({{ d.get_formatted("qty") }})
</span>
</div> </div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@ -1,84 +1,111 @@
{% if doc.taxes %} {% if doc.taxes %}
<tr> <div class="w-100 order-taxes mt-5">
<td class="text-left" colspan="1"> <div class="col-4 d-flex border-btm pb-5">
{{ _("Net Total") }} <div class="item-grand-total col-8">
</td> {{ _("Net Total") }}
<td class="text-right totals" colspan="3"> </div>
{{ doc.get_formatted("net_total") }} <div class="item-grand-total col-4 text-right pr-0">
</td> {{ doc.get_formatted("net_total") }}
</tr> </div>
</div>
</div>
{% endif %} {% endif %}
{% for d in doc.taxes %} {% for d in doc.taxes %}
{% if d.base_tax_amount %} {% if d.base_tax_amount %}
<tr> <div class="order-taxes w-100 mt-5">
<td class="text-left" colspan="1"> <div class="col-4 d-flex border-btm pb-5">
{{ d.description }} <div class="item-grand-total col-8">
</td> {{ d.description }}
<td class="text-right totals" colspan="3"> </div>
{{ d.get_formatted("base_tax_amount") }} <div class="item-grand-total col-4 text-right pr-0">
</td> {{ doc.get_formatted("net_total") }}
</tr> </div>
</div>
</div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if doc.doctype == 'Quotation' %} {% if doc.doctype == 'Quotation' %}
{% if doc.coupon_code %} {% if doc.coupon_code %}
<tr> <div class="w-100 mt-5 order-taxes font-weight-bold">
<td class="text-left total-discount" colspan="1"> <div class="col-4 d-flex border-btm pb-5">
{{ _("Savings") }} <div class="item-grand-total col-8">
</td> {{ _("Savings") }}
<td class="text-right tot_quotation_discount total-discount totals" colspan="3"> </div>
{% set tot_quotation_discount = [] %} <div class="item-grand-total col-4 text-right pr-0">
{%- for item in doc.items -%} {% set tot_quotation_discount = [] %}
{% if tot_quotation_discount.append((((item.price_list_rate * item.qty) {%- for item in doc.items -%}
* item.discount_percentage) / 100)) %} {% if tot_quotation_discount.append((((item.price_list_rate * item.qty)
{% endif %} * item.discount_percentage) / 100)) %}
{% endfor %} {% endif %}
{{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} {% endfor %}
</td> {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} </div>
</tr> </div>
</div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if doc.doctype == 'Sales Order' %} {% if doc.doctype == 'Sales Order' %}
{% if doc.coupon_code %} {% if doc.coupon_code %}
<tr> <div class="w-100 order-taxes mt-5">
<td class="text-left total-discount" colspan="2" style="padding-right: 2rem;"> <div class="col-4 d-flex border-btm pb-5">
{{ _("Applied Coupon Code") }} <div class="item-grand-total col-8">
</td> {{ _("Total Amount") }}
<td class="text-right total-discount"> </div>
<span> <div class="item-grand-total col-4 text-right pr-0">
{%- for row in frappe.get_all(doctype="Coupon Code", <span>
fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%} {% set total_amount = [] %}
<span>{{ row.coupon_code }}</span> {%- for item in doc.items -%}
{% endfor %} {% if total_amount.append((item.price_list_rate * item.qty)) %}{% endif %}
</span> {% endfor %}
</td> {{ frappe.utils.fmt_money((total_amount | sum),currency=doc.currency) }}
</tr> </span>
<tr> </div>
<td class="text-left total-discount" colspan="2"> </div>
{{ _("Savings") }} </div>
</td> <div class="order-taxes w-100 mt-5">
<td class="text-right total-discount"> <div class="col-4 d-flex">
<span> <div class="item-grand-total col-8">
{% set tot_SO_discount = [] %} {{ _("Applied Coupon Code") }}
{%- for item in doc.items -%} </div>
{% if tot_SO_discount.append((((item.price_list_rate * item.qty) <div class="item-grand-total col-4 text-right pr-0">
* item.discount_percentage) / 100)) %}{% endif %} <span>
{% endfor %} {%- for row in frappe.get_all(doctype="Coupon Code",
{{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }} fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%}
</span> <span>{{ row.coupon_code }}</span>
</td> {% endfor %}
</tr> </span>
</div>
</div>
</div>
<div class="order-taxes mt-5">
<div class="col-4 d-flex border-btm pb-5">
<div class="item-grand-total col-8">
{{ _("Savings") }}
</div>
<div class="item-grand-total col-4 text-right pr-0">
<span>
{% set tot_SO_discount = [] %}
{%- for item in doc.items -%}
{% if tot_SO_discount.append((((item.price_list_rate * item.qty)
* item.discount_percentage) / 100)) %}{% endif %}
{% endfor %}
{{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }}
</span>
</div>
</div>
</div>
{% endif %} {% endif %}
{% endif %} {% endif %}
<tr> <div class="w-100 mt-5 order-taxes font-weight-bold">
<th class="text-left item-grand-total" colspan="1"> <div class="col-4 d-flex">
{{ _("Grand Total") }} <div class="item-grand-total col-8">
</th> {{ _("Grand Total") }}
<th class="text-right item-grand-total totals" colspan="3"> </div>
{{ doc.get_formatted("grand_total") }} <div class="item-grand-total col-4 text-right pr-0">
</th> {{ doc.get_formatted("grand_total") }}
</tr> </div>
</div>
</div>

View File

@ -1,20 +1,22 @@
<div class="web-list-item transaction-list-item"> <div class="web-list-item transaction-list-item">
<div class="row"> <div class="row align-items-center">
<div class="col-sm-4"> <div class="col-sm-4">
<span class="indicator small {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }}"> <span class="list-item-name font-weight-bold">{{ doc.name }}</span>
{{ doc.name }}</span>
<div class="small text-muted transaction-time" <div class="small text-muted transaction-time"
title="{{ frappe.utils.format_datetime(doc.modified, "medium") }}"> title="{{ frappe.utils.format_datetime(doc.modified, "medium") }}">
{{ frappe.utils.global_date_format(doc.modified) }} {{ frappe.utils.global_date_format(doc.modified) }}
</div> </div>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-3">
<span class="indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }} list-item-status">{{doc.status}}</span>
</div>
<div class="col-sm-2">
<div class="small text-muted items-preview ellipsis ellipsis-width"> <div class="small text-muted items-preview ellipsis ellipsis-width">
{{ doc.items_preview }} {{ doc.items_preview }}
</div> </div>
</div> </div>
{% if doc.get('grand_total') %} {% if doc.get('grand_total') %}
<div class="col-sm-3 text-right bold"> <div class="col-sm-3 text-right font-weight-bold item-total">
{{ doc.get_formatted("grand_total") }} {{ doc.get_formatted("grand_total") }}
</div> </div>
{% endif %} {% endif %}

View File

@ -1,77 +0,0 @@
{% extends "templates/web.html" %}
{% block script %}
<script>
$(document).ready(function() {
$("#login_btn").click(function() {
var me = this;
$(this).html("Logging In...").prop("disabled", true);
frappe.call({
"method": "login",
args: {
usr: "demo@erpnext.com",
pwd: "Demo1234567!!!",
lead_email: $("#lead-email").val(),
},
callback: function(r) {
$(me).prop("disabled", false);
if(r.exc) {
alert("Error, please contact support@erpnext.com");
} else {
console.log("Logged In");
window.location.href = "desk";
}
}
})
return false;
})
.prop("disabled", false);
})
</script>
{% endblock %}
{% block style %}
<style>
footer, .navbar {
display: none;
}
.page-content {
right: 0%;
width: 100%;
}
{% include "templates/styles/card_style.css" %}
header, footer {
display: none;
}
html, body {
background-color: #f5f7fa;
}
</style>
{% endblock %}
{% block title %}
{{ _("ERPNext Demo") }}
{% endblock %}
{% block page_content %}
<div class='page-card'>
<div class='page-card-head'>
<span class='indicator blue'>
{{ _("ERPNext Demo") }}</span>
</div>
<!-- <img src="/assets/erpnext/images/erp-icon.svg" style="max-width: 40px; max-height: 40px;"> -->
<p>Some functionality is disabled for the demo and the data will be cleared regularly.</p>
<div><button type="submit" id="login_btn" class="btn btn-primary btn-sm">Launch Demo</button></div>
</div>
<p class='text-muted text-center small' style='margin-top: -20px;'><a href="https://erpnext.com/pricing">Start a free 14-day trial </a>
</p>
<style>
html, body {
background-color: #f5f7fa;
}
</style>
{% endblock %}

View File

@ -5,149 +5,159 @@
{% include "templates/includes/breadcrumbs.html" %} {% include "templates/includes/breadcrumbs.html" %}
{% endblock %} {% endblock %}
{% block title %}{{ doc.name }}{% endblock %} {% block title %}
{{ doc.name }}
{% endblock %}
{% block header %} {% block header %}
<h2 class="m-0">{{ doc.name }}</h2> <h3 class="m-0">{{ doc.name }}</h3>
{% endblock %} {% endblock %}
{% block header_actions %} {% block header_actions %}
<div class="dropdown"> <div class="row">
<button class="btn btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> <div class="dropdown">
<span class="font-md">{{ _('Actions') }}</span> <button class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<b class="caret"></b> <span class="font-md">{{ _('Actions') }}</span>
</button> <b class="caret"></b>
<ul class="dropdown-menu dropdown-menu-right" role="menu"> </button>
{% if doc.doctype == 'Purchase Order' and show_make_pi_button %} <ul class="dropdown-menu dropdown-menu-right" role="menu">
<a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a> {% if doc.doctype == 'Purchase Order' and show_make_pi_button %}
{% endif %} <a class="dropdown-item"
<a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}' href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}"
target="_blank" rel="noopener noreferrer"> data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}
{{ _("Print") }} </a>
</a> {% endif %}
</ul> <a class="dropdown-item"
href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}' target="_blank"
rel="noopener noreferrer">
{{ _("Print") }}
</a>
</ul>
</div>
<div class="form-column col-sm-6">
<div class="page-header-actions-block" data-html-block="header-actions">
<p>
<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
class="btn btn-primary btn-sm" id="pay-for-order">
{{ _("Pay") }} {{doc.get_formatted("grand_total") }}
</a>
</p>
</div>
</div>
</div> </div>
{% endblock %} {% endblock %}
{% block page_content %} {% block page_content %}
<div class="row transaction-subheading"> <div>
<div class="col-6"> <div class="row transaction-subheading mt-1">
<span class="font-md indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "darkgrey") }}"> <div class="col-6 text-muted small mt-1">
{% if doc.doctype == "Quotation" and not doc.docstatus %} {{ frappe.utils.format_date(doc.transaction_date, 'medium') }}
{{ _("Pending") }} {% if doc.valid_till %}
{% else %} <p>
{{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }} {{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }}
</p>
{% endif %} {% endif %}
</span> </div>
</div> </div>
<div class="col-6 text-muted text-right small pt-3"> <div class="row indicator-container mt-2">
{{ frappe.utils.format_date(doc.transaction_date, 'medium') }} <div class="col-10">
{% if doc.valid_till %} <span class="indicator-pill {{ doc.indicator_color or (" blue" if doc.docstatus==1 else "darkgrey" ) }}">
<p> {% if doc.doctype == "Quotation" and not doc.docstatus %}
{{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }} {{ _("Pending") }}
</p> {% else %}
{% endif %} {{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
</div>
</div>
<p class="small my-3">
{%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase Order'] else doc.customer_name %}
<b>{{ party_name }}</b>
{% if doc.contact_display and doc.contact_display != party_name %}
<br>
{{ doc.contact_display }}
{% endif %}
</p>
{% if doc._header %}
{{ doc._header }}
{% endif %}
<div class="order-container">
<!-- items -->
<table class="order-item-table w-100 table">
<thead class="order-items order-item-header">
<th width="60%">
{{ _("Item") }}
</th>
<th width="20%" class="text-right">
{{ _("Quantity") }}
</th>
<th width="20%" class="text-right">
{{ _("Amount") }}
</th>
</thead>
<tbody>
{% for d in doc.items %}
<tr class="order-items">
<td>
{{ item_name_and_description(d) }}
</td>
<td class="text-right">
{{ d.qty }}
{% if d.delivered_qty is defined and d.delivered_qty != None %}
<p class="text-muted small">{{ _("Delivered") }}&nbsp;{{ d.delivered_qty }}</p>
{% endif %} {% endif %}
</td> </span>
<td class="text-right"> </div>
{{ d.get_formatted("amount") }} <div class="text-right col-2">
<p class="text-muted small">{{ _("Rate:") }}&nbsp;{{ d.get_formatted("rate") }}</p> {%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase
</td> Order'] else doc.customer_name %}
</tr> <b>{{ party_name }}</b>
{% endfor %}
</tbody> {% if doc.contact_display and doc.contact_display != party_name %}
</table> <br>
<!-- taxes --> {{ doc.contact_display }}
<div class="order-taxes d-flex justify-content-end"> {% endif %}
<table> </div>
</div>
{% if doc._header %}
{{ doc._header }}
{% endif %}
<div class="order-container mt-4">
<!-- items -->
<div class="w-100">
<div class="order-items order-item-header mb-1 row text-muted">
<span class="col-5">
{{ _("Item") }}
</span>
<span class="d-s-n col-3">
{{ _("Quantity") }}
</span>
<span class="col-2 pl-10">
{{ _("Rate") }}
</span>
<span class="col-2 text-right">
{{ _("Amount") }}
</span>
</div>
{% for d in doc.items %}
<div class="order-items row align-items-center">
<span class="order-item-name col-5 pr-0">
{{ item_name_and_description(d) }}
</span>
<span class="d-s-n col-3 pl-10">
{{ d.get_formatted("qty") }}
</span>
<span class="order-rate pl-4 col-2">
{{ d.get_formatted("rate") }}
</span>
<span class="col-2 text-right">
{{ d.get_formatted("amount") }}
</span>
</div>
{% endfor %}
</div>
<!-- taxes -->
<div class="">
{% include "erpnext/templates/includes/order/order_taxes.html" %} {% include "erpnext/templates/includes/order/order_taxes.html" %}
</table> </div>
</div> </div>
</div> </div>
{% if enabled_checkout and ((doc.doctype=="Sales Order" and doc.per_billed <= 0) {% if enabled_checkout and ((doc.doctype=="Sales Order" and doc.per_billed <= 0)
or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0)) %} or (doc.doctype=="Sales Invoice" and doc.outstanding_amount> 0)) %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<div class="form-column col-sm-6 address-title">
<strong>Payment</strong>
</div>
</div>
</div>
<div class="panel-collapse"> <div class="panel-collapse">
<div class="panel-body text-muted small"> <div class="panel-body text-muted small">
<div class="row"> <div class="row">
<div class="form-column col-sm-6"> <div class="form-column col-sm-6">
{% if available_loyalty_points %} {% if available_loyalty_points %}
<div class="panel-heading">
<div class="row">
<div class="form-column col-sm-6 address-title">
<strong>Loyalty Points</strong>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="h6">Enter Loyalty Points</div> <div class="h6">Enter Loyalty Points</div>
<div class="control-input-wrapper"> <div class="control-input-wrapper">
<div class="control-input"> <div class="control-input">
<input class="form-control" type="number" min="0" max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem"> <input class="form-control" type="number" min="0"
max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem">
</div> </div>
<p class="help-box small text-muted d-none d-sm-block"> Available Points: {{ available_loyalty_points }} </p> <p class="help-box small text-muted d-none d-sm-block"> Available Points: {{
available_loyalty_points }} </p>
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="form-column col-sm-6">
<div id="loyalty-points-status" style="text-align: right"></div>
<div class="page-header-actions-block" data-html-block="header-actions">
<p class="mt-2" style="float: right;">
<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
class="btn btn-primary btn-sm"
id="pay-for-order">
{{ _("Pay") }} {{ doc.get_formatted("grand_total") }}
</a>
</p>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -172,17 +182,17 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div>
{% if doc.terms %} {% if doc.terms %}
<div class="terms-and-condition text-muted small"> <div class="terms-and-condition text-muted small">
<hr><p>{{ doc.terms }}</p> <hr>
<p>{{ doc.terms }}</p>
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script> {% include "templates/pages/order.js" %} </script> <script> {% include "templates/pages/order.js" %}</script>
<script> <script>
window.doc_info = { window.doc_info = {
customer: '{{doc.customer}}', customer: '{{doc.customer}}',
@ -192,4 +202,4 @@
currency: '{{ doc.currency }}' currency: '{{ doc.currency }}'
} }
</script> </script>
{% endblock %} {% endblock %}

View File

@ -785,7 +785,7 @@ Default BOM for {0} not found,Nomenclature par défaut {0} introuvable,
Default BOM not found for Item {0} and Project {1},La nomenclature par défaut n'a pas été trouvée pour l'Article {0} et le Projet {1}, Default BOM not found for Item {0} and Project {1},La nomenclature par défaut n'a pas été trouvée pour l'Article {0} et le Projet {1},
Default Letter Head,En-Tête de Courrier par Défaut, Default Letter Head,En-Tête de Courrier par Défaut,
Default Tax Template,Modèle de Taxes par Défaut, Default Tax Template,Modèle de Taxes par Défaut,
Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,LUnité de Mesure par Défaut pour lArticle {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UDM par défaut différente., Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,LUnité de Mesure par Défaut pour lArticle {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UdM par défaut différente.,
Default Unit of Measure for Variant '{0}' must be same as in Template '{1}',LUnité de mesure par défaut pour la variante '{0}' doit être la même que dans le Modèle '{1}', Default Unit of Measure for Variant '{0}' must be same as in Template '{1}',LUnité de mesure par défaut pour la variante '{0}' doit être la même que dans le Modèle '{1}',
Default settings for buying transactions.,Paramètres par défaut pour les transactions d'achat., Default settings for buying transactions.,Paramètres par défaut pour les transactions d'achat.,
Default settings for selling transactions.,Paramètres par défaut pour les transactions de vente., Default settings for selling transactions.,Paramètres par défaut pour les transactions de vente.,
@ -838,7 +838,7 @@ Difference Account,Compte dÉcart,
"Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry","Le Compte dÉcart doit être un compte de type Actif / Passif, puisque cette Réconciliation de Stock est une écriture d'à-nouveau", "Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry","Le Compte dÉcart doit être un compte de type Actif / Passif, puisque cette Réconciliation de Stock est une écriture d'à-nouveau",
Difference Amount,Écart de Montant, Difference Amount,Écart de Montant,
Difference Amount must be zero,LÉcart de Montant doit être égal à zéro, Difference Amount must be zero,LÉcart de Montant doit être égal à zéro,
Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UDM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure ., Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UdM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure .,
Direct Expenses,Charges Directes, Direct Expenses,Charges Directes,
Direct Income,Revenu direct, Direct Income,Revenu direct,
Disable,Désactiver, Disable,Désactiver,
@ -1409,7 +1409,7 @@ Lab Test,Test de laboratoire,
Lab Test Report,Rapport de test de laboratoire, Lab Test Report,Rapport de test de laboratoire,
Lab Test Sample,Échantillon de test de laboratoire, Lab Test Sample,Échantillon de test de laboratoire,
Lab Test Template,Modèle de test de laboratoire, Lab Test Template,Modèle de test de laboratoire,
Lab Test UOM,UDM de test de laboratoire, Lab Test UOM,UdM de test de laboratoire,
Lab Tests and Vital Signs,Tests de laboratoire et signes vitaux, Lab Tests and Vital Signs,Tests de laboratoire et signes vitaux,
Lab result datetime cannot be before testing datetime,La date et l'heure du résultat de laboratoire ne peuvent pas être avant la date et l'heure du test, Lab result datetime cannot be before testing datetime,La date et l'heure du résultat de laboratoire ne peuvent pas être avant la date et l'heure du test,
Lab testing datetime cannot be before collection datetime,La date et l'heure du test de laboratoire ne peuvent pas être avant la date et l'heure de collecte, Lab testing datetime cannot be before collection datetime,La date et l'heure du test de laboratoire ne peuvent pas être avant la date et l'heure de collecte,
@ -2806,7 +2806,7 @@ Stock Received But Not Billed,Stock Reçus Mais Non Facturés,
Stock Reports,Rapports de stock, Stock Reports,Rapports de stock,
Stock Summary,Résumé du Stock, Stock Summary,Résumé du Stock,
Stock Transactions,Transactions du Stock, Stock Transactions,Transactions du Stock,
Stock UOM,UDM du Stock, Stock UOM,UdM du Stock,
Stock Value,Valeur du Stock, Stock Value,Valeur du Stock,
Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3},Solde du stock dans le Lot {0} deviendra négatif {1} pour l'Article {2} à l'Entrepôt {3}, Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3},Solde du stock dans le Lot {0} deviendra négatif {1} pour l'Article {2} à l'Entrepôt {3},
Stock cannot be updated against Delivery Note {0},Stock ne peut pas être mis à jour pour le Bon de Livraison {0}, Stock cannot be updated against Delivery Note {0},Stock ne peut pas être mis à jour pour le Bon de Livraison {0},
@ -3161,9 +3161,9 @@ Trial Period End Date Cannot be before Trial Period Start Date,La date de fin de
Trialling,Essai, Trialling,Essai,
Type of Business,Type de commerce, Type of Business,Type de commerce,
Types of activities for Time Logs,Types d'activités pour Journaux de Temps, Types of activities for Time Logs,Types d'activités pour Journaux de Temps,
UOM,UDM, UOM,UdM,
UOM Conversion factor is required in row {0},Facteur de conversion de l'UDM est obligatoire dans la ligne {0}, UOM Conversion factor is required in row {0},Facteur de conversion de l'UdM est obligatoire dans la ligne {0},
UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UDM requis pour l'UDM : {0} dans l'Article : {1}, UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UdM requis pour l'UdM : {0} dans l'Article : {1},
URL,URL, URL,URL,
Unable to find DocType {0},Impossible de trouver le DocType {0}, Unable to find DocType {0},Impossible de trouver le DocType {0},
Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually,Impossible de trouver le taux de change pour {0} à {1} pour la date clé {2}. Veuillez créer une entrée de taux de change manuellement, Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually,Impossible de trouver le taux de change pour {0} à {1} pour la date clé {2}. Veuillez créer une entrée de taux de change manuellement,
@ -3294,7 +3294,7 @@ Wednesday,Mercredi,
Week,Semaine, Week,Semaine,
Weekdays,Jours de la semaine, Weekdays,Jours de la semaine,
Weekly,Hebdomadaire, Weekly,Hebdomadaire,
"Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UDM de Poids""", "Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UdM de Poids""",
Welcome email sent,Email de bienvenue envoyé, Welcome email sent,Email de bienvenue envoyé,
Welcome to ERPNext,Bienvenue sur ERPNext, Welcome to ERPNext,Bienvenue sur ERPNext,
What do you need help with?,Avec quoi avez vous besoin d'aide ?, What do you need help with?,Avec quoi avez vous besoin d'aide ?,
@ -4938,12 +4938,15 @@ Is Cumulative,Est cumulatif,
Coupon Code Based,Code de coupon basé, Coupon Code Based,Code de coupon basé,
Discount on Other Item,Remise sur un autre article, Discount on Other Item,Remise sur un autre article,
Apply Rule On Other,Appliquer la règle sur autre, Apply Rule On Other,Appliquer la règle sur autre,
Party Information,Informations sur la fête, Party Information,Informations sur le tier,
Quantity and Amount,Quantité et montant, Quantity and Amount,Quantité et montant,
Min Qty,Qté Min, Min Qty,Qté Min,
Max Qty,Qté Max, Max Qty,Qté Max,
Min Amt,Min Amt, Min Amt,Montant Min,
Max Amt,Max Amt, Max Amt,Montant Max,
"If rate is zero them item will be treated as ""Free Item""",Si le prix est à 0 alors l'article sera traité comme article gratuit
Is Recursive,Est récursif
"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on","La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc..."
Period Settings,Paramètres de période, Period Settings,Paramètres de période,
Margin,Marge, Margin,Marge,
Margin Type,Type de Marge, Margin Type,Type de Marge,
@ -5053,7 +5056,7 @@ Quantity and Rate,Quantité et Prix,
Received Qty,Qté Reçue, Received Qty,Qté Reçue,
Accepted Qty,Quantité acceptée, Accepted Qty,Quantité acceptée,
Rejected Qty,Qté Rejetée, Rejected Qty,Qté Rejetée,
UOM Conversion Factor,Facteur de Conversion de l'UDM, UOM Conversion Factor,Facteur de Conversion de l'UdM,
Discount on Price List Rate (%),Remise sur la Liste des Prix (%), Discount on Price List Rate (%),Remise sur la Liste des Prix (%),
Price List Rate (Company Currency),Taux de la Liste de Prix (Devise Société), Price List Rate (Company Currency),Taux de la Liste de Prix (Devise Société),
Rate (Company Currency),Prix (Devise Société), Rate (Company Currency),Prix (Devise Société),
@ -5085,7 +5088,7 @@ Purchase Receipt Detail,Détail du reçu d'achat,
Item Weight Details,Détails du poids de l'article, Item Weight Details,Détails du poids de l'article,
Weight Per Unit,Poids par unité, Weight Per Unit,Poids par unité,
Total Weight,Poids total, Total Weight,Poids total,
Weight UOM,UDM de Poids, Weight UOM,UdM de Poids,
Page Break,Saut de Page, Page Break,Saut de Page,
Consider Tax or Charge for,Tenir Compte de la Taxe et des Frais pour, Consider Tax or Charge for,Tenir Compte de la Taxe et des Frais pour,
Valuation and Total,Valorisation et Total, Valuation and Total,Valorisation et Total,
@ -5153,7 +5156,7 @@ Advance amount,Montant de l'Avance,
Sales Invoice Item,Article de la Facture de Vente, Sales Invoice Item,Article de la Facture de Vente,
Customer's Item Code,Code de l'Article du Client, Customer's Item Code,Code de l'Article du Client,
Brand Name,Nom de la Marque, Brand Name,Nom de la Marque,
Qty as per Stock UOM,Qté par UDM du Stock, Qty as per Stock UOM,Qté par UdM du Stock,
Discount and Margin,Remise et Marge, Discount and Margin,Remise et Marge,
Rate With Margin,Prix Avec Marge, Rate With Margin,Prix Avec Marge,
Discount (%) on Price List Rate with Margin,Remise (%) sur le prix de la Liste de Prix avec la Marge, Discount (%) on Price List Rate with Margin,Remise (%) sur le prix de la Liste de Prix avec la Marge,
@ -5501,7 +5504,7 @@ Blanket Order Rate,Prix unitaire de commande avec limites,
Returned Qty,Qté Retournée, Returned Qty,Qté Retournée,
Purchase Order Item Supplied,Article Fourni depuis la Commande d'Achat, Purchase Order Item Supplied,Article Fourni depuis la Commande d'Achat,
BOM Detail No,N° de Détail de la nomenclature, BOM Detail No,N° de Détail de la nomenclature,
Stock Uom,UDM du Stock, Stock Uom,UdM du Stock,
Raw Material Item Code,Code dArticle de Matière Première, Raw Material Item Code,Code dArticle de Matière Première,
Supplied Qty,Qté Fournie, Supplied Qty,Qté Fournie,
Purchase Receipt Item Supplied,Articles Fournis du Reçus dAchat, Purchase Receipt Item Supplied,Articles Fournis du Reçus dAchat,
@ -6149,7 +6152,7 @@ Drug Name / Description,Nom / description du médicament,
Dosage,Dosage, Dosage,Dosage,
Dosage by Time Interval,Dosage par intervalle de temps, Dosage by Time Interval,Dosage par intervalle de temps,
Interval,Intervalle, Interval,Intervalle,
Interval UOM,UDM d'Intervalle, Interval UOM,UdM d'Intervalle,
Hour,Heure, Hour,Heure,
Update Schedule,Mettre à Jour le Calendrier, Update Schedule,Mettre à Jour le Calendrier,
Exercise,Exercice, Exercise,Exercice,
@ -7023,7 +7026,7 @@ Petrol,Essence,
Diesel,Diesel, Diesel,Diesel,
Natural Gas,Gaz Naturel, Natural Gas,Gaz Naturel,
Electric,Électrique, Electric,Électrique,
Fuel UOM,UDM Carburant, Fuel UOM,UdM Carburant,
Last Carbon Check,Dernière Vérification Carbone, Last Carbon Check,Dernière Vérification Carbone,
Wheels,Roues, Wheels,Roues,
Doors,Portes, Doors,Portes,
@ -7182,7 +7185,7 @@ Item to be manufactured or repacked,Article à produire ou à réemballer,
Quantity of item obtained after manufacturing / repacking from given quantities of raw materials,Quantité d'article obtenue après production / reconditionnement des quantités données de matières premières, Quantity of item obtained after manufacturing / repacking from given quantities of raw materials,Quantité d'article obtenue après production / reconditionnement des quantités données de matières premières,
Set rate of sub-assembly item based on BOM,Définir le prix des articles de sous-assemblage en fonction de la nomenclature, Set rate of sub-assembly item based on BOM,Définir le prix des articles de sous-assemblage en fonction de la nomenclature,
Allow Alternative Item,Autoriser un article alternatif, Allow Alternative Item,Autoriser un article alternatif,
Item UOM,UDM de l'Article, Item UOM,UdM de l'Article,
Conversion Rate,Taux de Conversion, Conversion Rate,Taux de Conversion,
Rate Of Materials Based On,Prix des Matériaux Basé sur, Rate Of Materials Based On,Prix des Matériaux Basé sur,
With Operations,Avec des Opérations, With Operations,Avec des Opérations,
@ -7926,7 +7929,7 @@ Territory Manager,Responsable Régional,
For reference,Pour référence, For reference,Pour référence,
Territory Targets,Objectifs Régionaux, Territory Targets,Objectifs Régionaux,
Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.,Définir des budgets par Groupes d'Articles sur ce Territoire. Vous pouvez également inclure de la saisonnalité en définissant la Répartition., Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.,Définir des budgets par Groupes d'Articles sur ce Territoire. Vous pouvez également inclure de la saisonnalité en définissant la Répartition.,
UOM Name,Nom UDM, UOM Name,Nom UdM,
Check this to disallow fractions. (for Nos),Cochez cette case pour interdire les fractions. (Pour les numéros), Check this to disallow fractions. (for Nos),Cochez cette case pour interdire les fractions. (Pour les numéros),
Website Item Group,Groupe d'Articles du Site Web, Website Item Group,Groupe d'Articles du Site Web,
Cross Listing of Item in multiple groups,Liste Croisée d'Articles dans plusieurs groupes, Cross Listing of Item in multiple groups,Liste Croisée d'Articles dans plusieurs groupes,
@ -8198,10 +8201,10 @@ To Package No.,Au N° de Paquet,
If more than one package of the same type (for print),Si plus d'un paquet du même type (pour l'impression), If more than one package of the same type (for print),Si plus d'un paquet du même type (pour l'impression),
Package Weight Details,Détails du Poids du Paquet, Package Weight Details,Détails du Poids du Paquet,
The net weight of this package. (calculated automatically as sum of net weight of items),Le poids net de ce paquet. (Calculé automatiquement comme la somme du poids net des articles), The net weight of this package. (calculated automatically as sum of net weight of items),Le poids net de ce paquet. (Calculé automatiquement comme la somme du poids net des articles),
Net Weight UOM,UDM Poids Net, Net Weight UOM,UdM Poids Net,
Gross Weight,Poids Brut, Gross Weight,Poids Brut,
The gross weight of the package. Usually net weight + packaging material weight. (for print),Le poids brut du colis. Habituellement poids net + poids du matériau d'emballage. (Pour l'impression), The gross weight of the package. Usually net weight + packaging material weight. (for print),Le poids brut du colis. Habituellement poids net + poids du matériau d'emballage. (Pour l'impression),
Gross Weight UOM,UDM du Poids Brut, Gross Weight UOM,UdM du Poids Brut,
Packing Slip Item,Article Emballé, Packing Slip Item,Article Emballé,
DN Detail,Détail du Bon de Livraison, DN Detail,Détail du Bon de Livraison,
STO-PICK-.YYYY.-,STO-PICK-.YYYY.-, STO-PICK-.YYYY.-,STO-PICK-.YYYY.-,
@ -8215,7 +8218,7 @@ Pick List Item,Élément de la liste de choix,
Picked Qty,Quantité choisie, Picked Qty,Quantité choisie,
Price List Master,Données de Base des Listes de Prix, Price List Master,Données de Base des Listes de Prix,
Price List Name,Nom de la Liste de Prix, Price List Name,Nom de la Liste de Prix,
Price Not UOM Dependent,Prix non dépendant de l'UOM, Price Not UOM Dependent,Prix non dépendant de l'UdM,
Applicable for Countries,Applicable pour les Pays, Applicable for Countries,Applicable pour les Pays,
Price List Country,Pays de la Liste des Prix, Price List Country,Pays de la Liste des Prix,
MAT-PRE-.YYYY.-,MAT-PRE-YYYY.-, MAT-PRE-.YYYY.-,MAT-PRE-YYYY.-,
@ -8294,7 +8297,7 @@ Purchase Receipt No,N° du Reçu d'Achat,
Inspection Required,Inspection obligatoire, Inspection Required,Inspection obligatoire,
From BOM,Depuis la nomenclature, From BOM,Depuis la nomenclature,
For Quantity,Pour la Quantité, For Quantity,Pour la Quantité,
As per Stock UOM,Selon UDM du Stock, As per Stock UOM,Selon UdM du Stock,
Including items for sub assemblies,Incluant les articles pour des sous-ensembles, Including items for sub assemblies,Incluant les articles pour des sous-ensembles,
Default Source Warehouse,Entrepôt Source par Défaut, Default Source Warehouse,Entrepôt Source par Défaut,
Source Warehouse Address,Adresse de l'entrepôt source, Source Warehouse Address,Adresse de l'entrepôt source,
@ -8309,7 +8312,7 @@ Total Additional Costs,Total des Coûts Additionnels,
Customer or Supplier Details,Détails du Client ou du Fournisseur, Customer or Supplier Details,Détails du Client ou du Fournisseur,
Per Transferred,Par transféré, Per Transferred,Par transféré,
Stock Entry Detail,Détails de l'Écriture de Stock, Stock Entry Detail,Détails de l'Écriture de Stock,
Basic Rate (as per Stock UOM),Prix de base (comme lUDM du Stock), Basic Rate (as per Stock UOM),Prix de base (comme lUdM du Stock),
Basic Amount,Montant de Base, Basic Amount,Montant de Base,
Additional Cost,Frais Supplémentaire, Additional Cost,Frais Supplémentaire,
Serial No / Batch,N° de Série / Lot, Serial No / Batch,N° de Série / Lot,
@ -8339,7 +8342,7 @@ Quantity Difference,Différence de Quantité,
Amount Difference,Différence de Montant, Amount Difference,Différence de Montant,
Item Naming By,Nomenclature d'Article Par, Item Naming By,Nomenclature d'Article Par,
Default Item Group,Groupe d'Éléments par Défaut, Default Item Group,Groupe d'Éléments par Défaut,
Default Stock UOM,UDM par Défaut des Articles, Default Stock UOM,UdM par Défaut des Articles,
Sample Retention Warehouse,Entrepôt de stockage des échantillons, Sample Retention Warehouse,Entrepôt de stockage des échantillons,
Default Valuation Method,Méthode de Valorisation par Défaut, Default Valuation Method,Méthode de Valorisation par Défaut,
Show Barcode Field,Afficher Champ Code Barre, Show Barcode Field,Afficher Champ Code Barre,
@ -8353,8 +8356,8 @@ Stock Frozen Upto,Stock Gelé Jusqu'au,
Batch Identification,Identification par lots, Batch Identification,Identification par lots,
Use Naming Series,Utiliser la série de noms, Use Naming Series,Utiliser la série de noms,
Naming Series Prefix,Préfix du nom de série, Naming Series Prefix,Préfix du nom de série,
UOM Category,Catégorie d'unité de mesure (UDM), UOM Category,Catégorie d'unité de mesure (UdM),
UOM Conversion Detail,Détails de Conversion de l'UDM, UOM Conversion Detail,Détails de Conversion de l'UdM,
Variant Field,Champ de Variante, Variant Field,Champ de Variante,
A logical Warehouse against which stock entries are made.,Un Entrepôt logique dans lequel les entrées en stock sont faites., A logical Warehouse against which stock entries are made.,Un Entrepôt logique dans lequel les entrées en stock sont faites.,
Warehouse Detail,Détail de l'Entrepôt, Warehouse Detail,Détail de l'Entrepôt,
@ -9869,8 +9872,8 @@ Allowed Items,Articles autorisés
Party Specific Item,Restriction d'article disponible Party Specific Item,Restriction d'article disponible
Restrict Items Based On,Type de critére de restriction Restrict Items Based On,Type de critére de restriction
Based On Value,critére de restriction Based On Value,critére de restriction
Unit of Measure (UOM),Unité de mesure (UDM), Unit of Measure (UOM),Unité de mesure (UdM),
Unit Of Measure (UOM),Unité de mesure (UDM), Unit Of Measure (UOM),Unité de mesure (UdM),
CRM Settings,Paramètres CRM CRM Settings,Paramètres CRM
Do Not Explode,Ne pas décomposer Do Not Explode,Ne pas décomposer
Quick Access, Accés rapides Quick Access, Accés rapides

Can't render this file because it is too large.