Try ERPNext Buy Support Partners Foundation

Journal Entry through custom script error

Hi there,
I am trying to create a basic Journal entry through a custom script but I am getting an error. Could someone kindly guide me on what did I do wrong. All I am trying to accomplish is debit account “Special Salaries” and credit account “Special Salaries Payable”

Regards,
Dave

frappe.ui.form.on("sandbox Doc", {
    refresh: (frm, cdt, cdn) => {
        frm.add_custom_button("Create Journal Entry", () => {
                frappe.db.insert(make_je_doc(frm))
                    .then(function (doc) {
                        console.log(`${doc.doctype} ${doc.name} created on ${doc.creation}`);
                        frappe.set_route('Form', doc.doctype, doc.name);
                    }
                );
        });
    }
});

function make_je_doc(frm) {
    let je = {};
    let accounts= [
        [
            {'account':'Special Salaries - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
            {'debit_in_account_currency':25},
        ],
        [
            {'account':'Special Salaries Payable - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
            {'credit_in_account_currency':25},
        ]

    ];
    je["doctype"] = "Journal Entry";
    je["posting_date"]= frappe.datetime.add_days(frappe.datetime.nowdate(), 0),
    je["accounts"] = accounts;
    je["user_remark"] = "testing JE";
    return je;
}
Traceback (most recent call last):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 61, in application
    response = frappe.handler.handle()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/handler.py", line 21, in handle
    data = execute_cmd(cmd)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/handler.py", line 56, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1036, in call
    return fn(*args, **newargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/client.py", line 155, in insert
    doc = frappe.get_doc(doc).insert()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 734, in get_doc
    doc = frappe.model.document.get_doc(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 69, in get_doc
    return controller(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py", line 18, in __init__
    super(JournalEntry, self).__init__(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/accounts_controller.py", line 23, in __init__
    super(AccountsController, self).__init__(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 113, in __init__
    super(Document, self).__init__(kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 54, in __init__
    self.update(d)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 77, in update
    self.set(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 124, in set
    self.extend(key, value)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 161, in extend
    self.append(key, v)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py", line 155, in append
    self.name, str(type(value))[1:-1], value)
ValueError: Document for field "accounts" attached to child table of "None" must be a dict or BaseDocument, not class 'list' ([{'account': 'Special Salaries - C'}, {'debit_in_account_currency': 25}])

Why dont you try it on .py side?
E.g.

jv_doc = frappe.new_doc(“Journal Entry”)
jv_doc.posting_date = Nowdate()
jv_doc.user_remark = “testing je”
je_doc.append(‘accounts’, {
‘account’: debit_account,
‘debit_in_account_currency’: 25,
‘cost_center’:’ your_cost_center’
})
je_doc.append(‘accounts’, {
‘account’: credit_account,
‘credit_in_account_currency’: 25,
‘cost_center’: ‘your_cost_center’
})
jv_doc.save()
jv_doc.submit()

Many thanks for your response @lokesh
I was able to do it in JavaScript the way I wanted. The issue was due to assigning arrays instead of objects to the accounts variable array. In addition, I had to set the args to “doc”: doc instead of doctype while submitting.

function create_je(frm) {
    frappe.call({
        method: 'frappe.client.get_value',
        args: {
            'doctype': 'Custom Employee Salary Component',
            'filters': {
                'name': frm.doc.salary_component
            },
            'fieldname': ['component_name', 'expense_account', 'payable_account']
        },
        callback: function (data) {
            ccco_params.je = populate_je_obj(frm, data);
        }
    });
}

function populate_je_obj(frm, data) {
    let je = {};
    let accounts = [
        {
            "doctype": "Journal Entry Account",
            "account": data.message.payable_account,
            "party": frm.doc.employee,
            "party_type": "Employee",
            "debit": 0,
            "credit": frm.doc.gross_pay,
            "credit_in_account_currency": frm.doc.gross_pay,
            "user_remark": cur_frm.docname
        },

        {
            "doctype": "Journal Entry Account",
            "account": data.message.expense_account,
            "debit": frm.doc.gross_pay,
            "credit": 0,
            "debit_in_account_currency": frm.doc.gross_pay,
            "user_remark": cur_frm.docname
        }
    ];
    je["doctype"] = "Journal Entry";
    je["posting_date"] = frappe.datetime.add_days(frm.doc.process_date, 0),
    je["accounts"] = accounts;
    return je;
}

function submit_je(frm) {
    ccco_params.je["remark"] = cur_frm.docname;
    frappe.db.insert(ccco_params.je)
        .then(function (doc) {
            frappe.call({
                "method": "frappe.client.submit",
                "args": {
                    "doc": doc
                },
                "callback": (r) => {
                    console.log(r);
                }
            });
        });
}