Merge pull request #38561 from blaggacao/feat/add-delivery-cutoff-date-on-so

feat(delivery): add cutoff item date for so delivery items
This commit is contained in:
ruthra kumar 2024-03-02 12:55:00 +05:30 committed by GitHub
commit e017421708
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 62 additions and 11 deletions

View File

@ -1,7 +1,7 @@
frappe.provide("erpnext.bulk_transaction_processing"); frappe.provide("erpnext.bulk_transaction_processing");
$.extend(erpnext.bulk_transaction_processing, { $.extend(erpnext.bulk_transaction_processing, {
create: function(listview, from_doctype, to_doctype) { create: function(listview, from_doctype, to_doctype, args) {
let checked_items = listview.get_checked_items(); let checked_items = listview.get_checked_items();
const doc_name = []; const doc_name = [];
checked_items.forEach((Item)=> { checked_items.forEach((Item)=> {
@ -15,7 +15,7 @@ $.extend(erpnext.bulk_transaction_processing, {
if (doc_name.length == 0) { if (doc_name.length == 0) {
frappe.call({ frappe.call({
method: "erpnext.utilities.bulk_transaction.transaction_processing", method: "erpnext.utilities.bulk_transaction.transaction_processing",
args: {data: checked_items, from_doctype: from_doctype, to_doctype: to_doctype} args: {data: checked_items, from_doctype: from_doctype, to_doctype: to_doctype, args: args}
}).then(()=> { }).then(()=> {
}); });

View File

@ -855,6 +855,8 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
var delivery_dates = this.frm.doc.items.map(i => i.delivery_date); var delivery_dates = this.frm.doc.items.map(i => i.delivery_date);
delivery_dates = [ ...new Set(delivery_dates) ]; delivery_dates = [ ...new Set(delivery_dates) ];
var today = new Date();
var item_grid = this.frm.fields_dict["items"].grid; var item_grid = this.frm.fields_dict["items"].grid;
if(!item_grid.get_selected().length && delivery_dates.length > 1) { if(!item_grid.get_selected().length && delivery_dates.length > 1) {
var dialog = new frappe.ui.Dialog({ var dialog = new frappe.ui.Dialog({
@ -873,7 +875,11 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
<div class="list-item"> <div class="list-item">
<div class="list-item__content list-item__content--flex-2"> <div class="list-item__content list-item__content--flex-2">
<label> <label>
<input type="checkbox" data-date="${date}" checked="checked"/> <input
type="checkbox"
data-date="${date}"
${frappe.datetime.get_day_diff(new Date(date), today) > 0 ? "" : 'checked="checked"'}
/>
${frappe.datetime.str_to_user(date)} ${frappe.datetime.str_to_user(date)}
</label> </label>
</div> </div>

View File

@ -937,6 +937,9 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None):
if frappe.flags.args and frappe.flags.args.delivery_dates: if frappe.flags.args and frappe.flags.args.delivery_dates:
if cstr(doc.delivery_date) not in frappe.flags.args.delivery_dates: if cstr(doc.delivery_date) not in frappe.flags.args.delivery_dates:
return False return False
if frappe.flags.args and frappe.flags.args.until_delivery_date:
if cstr(doc.delivery_date) > frappe.flags.args.until_delivery_date:
return False
return abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier != 1 return abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier != 1
@ -1012,6 +1015,11 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None):
for idx, item in enumerate(target_doc.items): for idx, item in enumerate(target_doc.items):
item.idx = idx + 1 item.idx = idx + 1
if not kwargs.skip_item_mapping and frappe.flags.bulk_transaction and not target_doc.items:
# the (date) condition filter resulted in an unintendedly created empty DN; remove it
del target_doc
return
# Should be called after mapping items. # Should be called after mapping items.
set_missing_values(so, target_doc) set_missing_values(so, target_doc)

View File

@ -55,7 +55,24 @@ frappe.listview_settings['Sales Order'] = {
}); });
listview.page.add_action_item(__("Delivery Note"), ()=>{ listview.page.add_action_item(__("Delivery Note"), ()=>{
erpnext.bulk_transaction_processing.create(listview, "Sales Order", "Delivery Note"); frappe.db.get_single_value("Selling Settings", "enable_cutoff_date_on_bulk_delivery_note_creation").then((value) => {
if (value) {
var dialog = new frappe.ui.Dialog({
title: __("Select Items up to Delivery Date"),
fields: [{fieldtype: "Date", fieldname: "delivery_date", default: frappe.datetime.add_days(frappe.datetime.nowdate(), 1)}]
});
dialog.set_primary_action(__("Select"), function(values) {
var until_delivery_date = values.delivery_date;
erpnext.bulk_transaction_processing.create(listview, "Sales Order", "Delivery Note", {
until_delivery_date
});
dialog.hide();
});
dialog.show();
} else {
erpnext.bulk_transaction_processing.create(listview, "Sales Order", "Delivery Note");
}
})
}); });
listview.page.add_action_item(__("Advance Payment"), ()=>{ listview.page.add_action_item(__("Advance Payment"), ()=>{

View File

@ -32,7 +32,8 @@
"allow_sales_order_creation_for_expired_quotation", "allow_sales_order_creation_for_expired_quotation",
"dont_reserve_sales_order_qty_on_sales_return", "dont_reserve_sales_order_qty_on_sales_return",
"hide_tax_id", "hide_tax_id",
"enable_discount_accounting" "enable_discount_accounting",
"enable_cutoff_date_on_bulk_delivery_note_creation"
], ],
"fields": [ "fields": [
{ {
@ -200,6 +201,12 @@
"fieldname": "blanket_order_allowance", "fieldname": "blanket_order_allowance",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Blanket Order Allowance (%)" "label": "Blanket Order Allowance (%)"
},
{
"default": "0",
"fieldname": "enable_cutoff_date_on_bulk_delivery_note_creation",
"fieldtype": "Check",
"label": "Enable Cut-Off Date on Bulk Delivery Note Creation"
} }
], ],
"icon": "fa fa-cog", "icon": "fa fa-cog",
@ -207,7 +214,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"issingle": 1, "issingle": 1,
"links": [], "links": [],
"modified": "2023-10-25 14:03:03.966701", "modified": "2024-03-01 12:07:39.994520",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Selling", "module": "Selling",
"name": "Selling Settings", "name": "Selling Settings",

View File

@ -30,6 +30,7 @@ class SellingSettings(Document):
dont_reserve_sales_order_qty_on_sales_return: DF.Check dont_reserve_sales_order_qty_on_sales_return: DF.Check
editable_bundle_item_rates: DF.Check editable_bundle_item_rates: DF.Check
editable_price_list_rate: DF.Check editable_price_list_rate: DF.Check
enable_cutoff_date_on_bulk_delivery_note_creation: DF.Check
enable_discount_accounting: DF.Check enable_discount_accounting: DF.Check
hide_tax_id: DF.Check hide_tax_id: DF.Check
maintain_same_rate_action: DF.Literal["Stop", "Warn"] maintain_same_rate_action: DF.Literal["Stop", "Warn"]

View File

@ -7,12 +7,15 @@ from frappe.utils import get_link_to_form, today
@frappe.whitelist() @frappe.whitelist()
def transaction_processing(data, from_doctype, to_doctype): def transaction_processing(data, from_doctype, to_doctype, args=None):
if isinstance(data, str): if isinstance(data, str):
deserialized_data = json.loads(data) deserialized_data = json.loads(data)
else: else:
deserialized_data = data deserialized_data = data
if isinstance(args, str):
args = frappe._dict(json.loads(args))
length_of_data = len(deserialized_data) length_of_data = len(deserialized_data)
frappe.msgprint( frappe.msgprint(
@ -23,6 +26,7 @@ def transaction_processing(data, from_doctype, to_doctype):
deserialized_data=deserialized_data, deserialized_data=deserialized_data,
from_doctype=from_doctype, from_doctype=from_doctype,
to_doctype=to_doctype, to_doctype=to_doctype,
args=args,
) )
@ -71,8 +75,13 @@ def update_log(log_name, status, retried, err=None):
frappe.db.set_value("Bulk Transaction Log Detail", log_name, "error_description", err) frappe.db.set_value("Bulk Transaction Log Detail", log_name, "error_description", err)
def job(deserialized_data, from_doctype, to_doctype): def job(deserialized_data, from_doctype, to_doctype, args):
fail_count = 0 fail_count = 0
if args:
# currently: flag-based transport to `task`
frappe.flags.args = args
for d in deserialized_data: for d in deserialized_data:
try: try:
doc_name = d.get("name") doc_name = d.get("name")
@ -147,9 +156,12 @@ def task(doc_name, from_doctype, to_doctype):
else: else:
obj = mapper[from_doctype][to_doctype](doc_name) obj = mapper[from_doctype][to_doctype](doc_name)
obj.flags.ignore_validate = True if obj:
obj.set_title_field() obj.flags.ignore_validate = True
obj.insert(ignore_mandatory=True) obj.set_title_field()
obj.insert(ignore_mandatory=True)
del obj
del frappe.flags.bulk_transaction del frappe.flags.bulk_transaction