Project

General

Profile

Task #2 » FINAL-.txt

Rajesh Gotur, 08/08/2026 01:34 PM

 
CLIENT-SCRIPT--
frappe.ui.form.on("Bill of Entry", {

after_save: async function (frm) {

// =====================================================
// Execute only for saved BOE in Ready for Lot Number Staging
// =====================================================

if (frm.is_new()) return;

if (frm.__lot_automation_running) return;

if (frm.doc.workflow_state !== "Ready for Lot Number Staging") return;

frm.__lot_automation_running = true;

try {

frappe.dom.freeze("Generating Lot Numbers. Please wait...");

// =================================================
// STEP 1
// Create Lot Number Staging
// =================================================

await frappe.call({
method: "canofy_ddit.canofy_ddit.doctype.lot_number_staging.lot_number_staging.create_lot_no_staging",
args: {
doc_name: frm.doc.name
}
});

// Wait for database commit

await new Promise(resolve => setTimeout(resolve, 2000));

// =================================================
// STEP 2
// Fetch Latest Lot Number Staging
// =================================================

const lns_list = await frappe.db.get_list(
"Lot Number Staging",
{
filters: {
linked_be_no: frm.doc.name
},
fields: ["name"],
order_by: "creation desc",
limit: 1
}
);

if (!lns_list.length) {
throw "Lot Number Staging document was not created.";
}

const lns_name = lns_list[0].name;

// =================================================
// STEP 3
// Load Lot Number Staging
// =================================================

let lns = await frappe.db.get_doc(
"Lot Number Staging",
lns_name
);

// =================================================
// STEP 4
// Header & Item Validations
// =================================================

let validation_errors = [];

// --------------------------------------------
// Validation 1
// BOE Number = LNS Transaction ID
// --------------------------------------------

if (
String(frm.doc.p_0_beno || "").trim() !==
String(lns.transaction_id || "").trim()
) {

validation_errors.push(
"BE Number and Transaction ID do not match."
);

}

// --------------------------------------------
// Validation 2
// BOE System Doc No = LNS Source EXIM Txn ID
// --------------------------------------------

if (
String(frm.doc.name || "").trim() !==
String(lns.linked_be_no || "").trim()
) {

validation_errors.push(
"System Doc. No. and Source EXIM Txn ID do not match."
);

}

// --------------------------------------------
// Validation 3
// Item Count
// --------------------------------------------

const boe_items = frm.doc.items || [];
const lns_items = lns.item_details || [];

if (!boe_items.length) {

validation_errors.push(
"Bill of Entry contains no items."
);

}

if (!lns_items.length) {

validation_errors.push(
"Lot Number Staging contains no items."
);

}

if (
boe_items.length &&
lns_items.length &&
boe_items.length !== lns_items.length
) {

validation_errors.push(
`Item count mismatch. BOE : ${boe_items.length}, LNS : ${lns_items.length}.`
);

}

// =================================================
// Stop if Validation Failed
// =================================================

if (validation_errors.length) {

throw validation_errors.join("<br>");

}

frappe.show_alert({
message: "Lot Number Staging validation completed successfully.",
indicator: "green"
});

// =================================================
// STEP 5
// Submit Lot Number Staging
// =================================================

await frappe.xcall(
"frappe.model.workflow.apply_workflow",
{
doc: lns,
action: "Submit"
}
);

// Reload latest document

lns = await frappe.db.get_doc(
"Lot Number Staging",
lns_name
);

// =================================================
// STEP 6
// Create Lot Numbers
// =================================================

const response = await frappe.call({

method: "run_doc_method",

args: {

docs: lns,

method: "create_lot_number",

args: {}

}

});

// =================================================
// STEP 7
// Verify API Execution
// =================================================

if (response.exc) {

throw "Lot Number creation process failed.";

}

// Wait for server commit

await new Promise(resolve => setTimeout(resolve, 2000));

frappe.show_alert({
message: "Lot Numbers created successfully.",
indicator: "green"
});

// =================================================
// SUCCESS
// =================================================

frappe.msgprint({

title: "Automation Completed",

indicator: "green",

message:
"<b>Bill of Entry Automation Completed Successfully</b><br><br>" +
"✓ Bill of Entry validated.<br>" +
"✓ Workflow moved to Ready for Lot Number Staging.<br>" +
"✓ Lot Number Staging created.<br>" +
"✓ Header validations passed.<br>" +
"✓ Item validations passed.<br>" +
"✓ Lot Number Staging submitted.<br>" +
"✓ Lot Numbers created successfully."

});

frm.reload_doc();

}

catch (e) {

console.error(e);

frappe.msgprint({

title: "Automation Failed",

indicator: "red",

message: e.message || e

});

}

finally {

frappe.dom.unfreeze();

frm.__lot_automation_running = false;

}

}

});
##------------------------------------------------------------------
SERVER-CLIENT--
# ==========================================================
# Bill of Entry Automation
# Trigger : After Save
# Purpose :
# 1. Validate Bill of Entry
# 2. Move Workflow
# Pending Review
# ↓
# Reviewed
# ↓
# Ready for Lot Number Staging
# ==========================================================

# Execute only for Draft Bill of Entry
if doc.docstatus == 0 and doc.workflow_state == "Pending Review":

validation_errors = []

# ======================================================
# Header Validations
# ======================================================

# BE Number
if not doc.p_0_beno:
validation_errors.append("• Bill of Entry Number is mandatory.")

# BE Type
if not doc.p_0_betype:
validation_errors.append("• Bill of Entry Type is mandatory.")

# Inventory Workflow
if doc.inventory_workflow_allowed != 1:
validation_errors.append(
"• Inventory Workflow Allowed must be enabled."
)

# ======================================================
# Item Validations
# ======================================================

if not doc.items:
validation_errors.append(
"• At least one item must be available in the Item table."
)

# ======================================================
# Stop Processing
# ======================================================

if validation_errors:

frappe.throw(
"<br><br><b>Bill of Entry Validation Failed</b><br><br>"
+ "<br>".join(validation_errors)
)

# ======================================================
# Workflow Transition
# ======================================================

# Stage 1
doc.workflow_state = "Reviewed"
doc.save(ignore_permissions=True)

# Reload latest values
doc.reload()

# Stage 2
doc.workflow_state = "Ready for Lot Number Staging"
doc.save(ignore_permissions=True)

# ======================================================
# Success Message
# ======================================================

frappe.msgprint(
"<b>Bill of Entry Validation Successful</b><br><br>"
"Workflow has been assigned to "
"<b>Ready for Lot Number Staging</b>."
)
(2-2/2)