New doctype "Sales invoice summary" with naming series

Hello everyone, I would really appreciate some help with this.

I would like to fetch outstanding invoices from customers in a new doctype with naming series and print them out so we can send them to customers as a summary every month.

The report “Accounts Receivable Summary” does the job perfectly, it’s just that we would like to have naming series for each print out, so that we can keep track of the summaries sent to customers.

If someone could guide me through the steps, I would be very thankful.
Mo

Use the same function which is used in “Accounts Receivable Summary” report. And render the results in your child table.

1 Like

@nabinhait thank you very much. I will set it up now and share the result with you in a bit.

@nabinhait Hi again, I have tried all day to get it to work, but it is unfortunately not successful.
I have copied the function into the new doctype and created a child table for it, but nothing happens, just got a blank screen. Would you be so kind to push in the right direction, I really appreciate that. thanks

@mrmo share you code. Hard to guess!

@nabinhait @rmehta Sorry was being too fast in reply. Below my findings.
I have checked with the report functions, and found that the problem was with the invoices vouchers not being shown. So I have digged deeper and found the “Payment Tool” to be the best alternative for using with “Billing”. Now let’s go into details.

  1. I have duplicated the “Payment Tool” doctype to “Billing”.
  2. Duplicated the “Payment Tool Detail” child table to “Billing Detail”.
  3. For the “Billing” doctype I have checked ‘custom’, and for the “Billing Details” I have kept it as is.
  4. I have copied the js file in the “Payment Tool” folder and pasted it after editing the content, as I think would be correct into the custom script for “Billing” like this;
frm.set_query("party_type", function() {
    return {
        filters: {"name": ["in", ["Customer", "Supplier"]]}
    };
});

frm.set_query("payment_account", function() {
    return {
        filters: {
            "account_type": ["in", ["Bank", "Cash"]],
            "is_group": 0,
            "company": frm.doc.company
        }
    }
});

frm.set_query("against_voucher_type", "vouchers", function() {
    if (frm.doc.party_type=="Customer") {
        var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
    } else {
        var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
    }

    return {
        filters: { "name": ["in", doctypes] }
    };
});

});

frappe.ui.form.on(“Billing”, “refresh”, function(frm) {
frm.disable_save();
frappe.ui.form.trigger(“Billing”, “party_type”);
});

frappe.ui.form.on(“Billing”, “party”, function(frm) {
if(frm.doc.party_type && frm.doc.party) {
return frappe.call({
method: “erpnext.accounts.party.get_party_account”,
args: {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party
},
callback: function(r) {
if(!r.exc && r.message) {
frm.set_value(“party_account”, r.message);
erpnext.payment_tool.check_mandatory_to_set_button(frm);
}
}
});
}
})

frappe.ui.form.on(“Billing”, “party_account”, function(frm) {
if(frm.doc.party_account) {
frm.call({
method: “frappe.client.get_value”,
args: {
doctype: “Account”,
fieldname: “account_currency”,
filters: { name: frm.doc.party_account },
},
callback: function(r, rt) {
if(r.message) {
frm.set_value(“party_account_currency”, r.message.account_currency);
erpnext.payment_tool.check_mandatory_to_set_button(frm);
}
}
});
}
})

frappe.ui.form.on(“Billing”, “company”, function(frm) {
erpnext.payment_tool.check_mandatory_to_set_button(frm);
});

frappe.ui.form.on(“Billing”, “received_or_paid”, function(frm) {
erpnext.payment_tool.check_mandatory_to_set_button(frm);
});

erpnext.payment_tool.check_mandatory_to_set_button = function(frm) {
if (frm.doc.company && frm.doc.party_type && frm.doc.party && frm.doc.received_or_paid && frm.doc.party_account) {
frm.fields_dict.get_outstanding_vouchers.$input.addClass(“btn-primary”);
}
}

// Get outstanding vouchers
frappe.ui.form.on(“Billing”, “get_outstanding_vouchers”, function(frm) {
erpnext.payment_tool.check_mandatory_to_fetch(frm.doc);

frm.set_value("vouchers", []);

return  frappe.call({
    method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_outstanding_vouchers',
    args: {
        args: {
            "company": frm.doc.company,
            "party_type": frm.doc.party_type,
            "received_or_paid": frm.doc.received_or_paid,
            "party": frm.doc.party,
            "party_account": frm.doc.party_account
        }
    },
    callback: function(r, rt) {
        if(r.message) {
            frm.fields_dict.get_outstanding_vouchers.$input.removeClass("btn-primary");
            frm.fields_dict.make_journal_entry.$input.addClass("btn-primary");

            frm.clear_table("vouchers");

            $.each(r.message, function(i, d) {
                var c = frm.add_child("vouchers");
                c.against_voucher_type = d.voucher_type;
                c.against_voucher_no = d.voucher_no;
                c.total_amount = d.invoice_amount;
                c.outstanding_amount = d.outstanding_amount;

                if (frm.doc.set_payment_amount) {
                    c.payment_amount = d.outstanding_amount;
                }
            });
        }
        refresh_field("vouchers");
        frm.layout.refresh_sections();
        erpnext.payment_tool.set_total_payment_amount(frm);
    }
});

});

// validate against_voucher_type
frappe.ui.form.on(“Billing Detail”, “against_voucher_type”, function(frm, cdt, cdn) {
var row = frappe.model.get_doc(cdt, cdn);
erpnext.payment_tool.validate_against_voucher(frm, row);
});

erpnext.payment_tool.validate_against_voucher = function(frm, row) {
var _validate = function(i, row) {
if (!row.against_voucher_type) {
return;
}

    if(frm.doc.party_type=="Customer"
        && !in_list(["Sales Order", "Sales Invoice", "Journal Entry"], row.against_voucher_type)) {
            frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
            frappe.msgprint(__("Against Voucher Type must be one of Sales Order, Sales Invoice or Journal Entry"));
            return false;
        }

    if(frm.doc.party_type=="Supplier"
        && !in_list(["Purchase Order", "Purchase Invoice", "Journal Entry"], row.against_voucher_type)) {
            frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
            frappe.msgprint(__("Against Voucher Type must be one of Purchase Order, Purchase Invoice or Journal Entry"));
            return false;
        }

}

if (row) {
    _validate(0, row);
} else {
    $.each(frm.doc.vouchers || [], _validate);
}

}

// validate against_voucher_type
frappe.ui.form.on(“Billing Detail”, “against_voucher_no”, function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (!row.against_voucher_no) {
return;
}

frappe.call({
    method: 'erpnext.accounts.doctype.billing.billing.get_against_voucher_amount',
    args: {
        "against_voucher_type": row.against_voucher_type,
        "against_voucher_no": row.against_voucher_no,
        "party_account": frm.doc.party_account,
        "company": frm.doc.company
    },
    callback: function(r) {
        if(!r.exc) {
            $.each(r.message, function(k, v) {
                frappe.model.set_value(cdt, cdn, k, v);
            });

            frappe.model.set_value(cdt, cdn, "payment_amount", r.message.outstanding_amount);
        }
    }
});

});

// Set total payment amount
frappe.ui.form.on(“Billing Detail”, “payment_amount”, function(frm) {
erpnext.payment_tool.set_total_payment_amount(frm);
});

frappe.ui.form.on(“Billing Detail”, “vouchers_remove”, function(frm) {
erpnext.payment_tool.set_total_payment_amount(frm);
});

erpnext.billing.set_total_payment_amount = function(frm) {
var total_amount = 0.00;
$.each(frm.doc.vouchers || , function(i, row) {
if (row.payment_amount && (row.payment_amount <= row.outstanding_amount)) {
total_amount = total_amount + row.payment_amount;
} else {
if(row.payment_amount < 0)
msgprint((“Row {0}: Payment amount can not be negative”, [row.idx]));
else if(row.payment_amount > row.outstanding_amount)
msgprint(
(“Row {0}: Payment Amount cannot be greater than Outstanding Amount”, [__(row.idx)]));

        frappe.model.set_value(row.doctype, row.name, "payment_amount", 0.0);
    }
});
frm.set_value("total_payment_amount", total_amount);

}

Here is where I got stuck, I checked the page and it says the following in the debugger:

SyntaxError: expected expression, got ‘}’

Any help, would be appreciated, thanks.

Seems like you have missed first line, refer payment_tool.js file

frappe.ui.form.on("Billing", "onload", function(frm) {