[Enahance] Provision to select customer, item code while making an invoice from timesheet (#10616)
This commit is contained in:
parent
2e6db4d928
commit
fd39d6bd3c
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
@ -48,6 +48,8 @@ In the Timesheet, if "Is Billable" is checked, you will find option to create Sa
|
|||||||
|
|
||||||
<img class="screenshot" alt="Sales Invoice" src="/docs/assets/img/project/timesheet/timesheet-invoice-1.png">
|
<img class="screenshot" alt="Sales Invoice" src="/docs/assets/img/project/timesheet/timesheet-invoice-1.png">
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Sales Invoice timesheet" src="{{docs_base_url}}/assets/img/project/timesheet/make_invoice_from_timesheet.gif">
|
||||||
|
|
||||||
####Sales Invoice
|
####Sales Invoice
|
||||||
|
|
||||||
Sales Invoice has dedicated table for the Timesheet table where Timesheet details will be updated. You can select more Timesheets in this table.
|
Sales Invoice has dedicated table for the Timesheet table where Timesheet details will be updated. You can select more Timesheets in this table.
|
||||||
|
@ -54,19 +54,18 @@ class TestTimesheet(unittest.TestCase):
|
|||||||
|
|
||||||
def test_sales_invoice_from_timesheet(self):
|
def test_sales_invoice_from_timesheet(self):
|
||||||
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
|
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
|
||||||
sales_invoice = make_sales_invoice(timesheet.name)
|
sales_invoice = make_sales_invoice(timesheet.name, '_Test Item', '_Test Customer')
|
||||||
sales_invoice.customer = "_Test Customer"
|
|
||||||
sales_invoice.due_date = nowdate()
|
sales_invoice.due_date = nowdate()
|
||||||
|
|
||||||
item = sales_invoice.append('items', {})
|
|
||||||
item.item_code = '_Test Item'
|
|
||||||
item.qty = 2
|
|
||||||
item.rate = 100
|
|
||||||
|
|
||||||
sales_invoice.submit()
|
sales_invoice.submit()
|
||||||
timesheet = frappe.get_doc('Timesheet', timesheet.name)
|
timesheet = frappe.get_doc('Timesheet', timesheet.name)
|
||||||
self.assertEquals(sales_invoice.total_billing_amount, 100)
|
self.assertEquals(sales_invoice.total_billing_amount, 100)
|
||||||
self.assertEquals(timesheet.status, 'Billed')
|
self.assertEquals(timesheet.status, 'Billed')
|
||||||
|
self.assertEquals(sales_invoice.customer, '_Test Customer')
|
||||||
|
|
||||||
|
item = sales_invoice.items[0]
|
||||||
|
self.assertEquals(item.item_code, '_Test Item')
|
||||||
|
self.assertEquals(item.qty, 2.00)
|
||||||
|
self.assertEquals(item.rate, 50.00)
|
||||||
|
|
||||||
def test_timesheet_billing_based_on_project(self):
|
def test_timesheet_billing_based_on_project(self):
|
||||||
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1, project = '_Test Project', company='_Test Company')
|
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1, project = '_Test Project', company='_Test Company')
|
||||||
|
@ -57,10 +57,37 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
make_invoice: function(frm) {
|
make_invoice: function(frm) {
|
||||||
frappe.model.open_mapped_doc({
|
let dialog = new frappe.ui.Dialog({
|
||||||
method: "erpnext.projects.doctype.timesheet.timesheet.make_sales_invoice",
|
title: __("For Item"),
|
||||||
frm: frm
|
fields: [
|
||||||
|
{"fieldtype": "Link", "label": __("Item Code"), "fieldname": "item_code", "options":"Item"},
|
||||||
|
{"fieldtype": "Link", "label": __("Customer"), "fieldname": "customer", "options":"Customer"}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dialog.set_primary_action(__("Make Sales Invoice"), () => {
|
||||||
|
var args = dialog.get_values();
|
||||||
|
if(!args) return;
|
||||||
|
dialog.hide();
|
||||||
|
return frappe.call({
|
||||||
|
type: "GET",
|
||||||
|
method: "erpnext.projects.doctype.timesheet.timesheet.make_sales_invoice",
|
||||||
|
args: {
|
||||||
|
"source_name": frm.doc.name,
|
||||||
|
"item_code": args.item_code,
|
||||||
|
"customer": args.customer
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc) {
|
||||||
|
frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
make_salary_slip: function(frm) {
|
make_salary_slip: function(frm) {
|
||||||
|
@ -323,17 +323,32 @@ def get_timesheet_data(name, project):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_invoice(source_name, target=None):
|
def make_sales_invoice(source_name, item_code=None, customer=None):
|
||||||
target = frappe.new_doc("Sales Invoice")
|
target = frappe.new_doc("Sales Invoice")
|
||||||
timesheet = frappe.get_doc('Timesheet', source_name)
|
timesheet = frappe.get_doc('Timesheet', source_name)
|
||||||
|
|
||||||
|
hours = flt(timesheet.total_billable_hours) - flt(timesheet.total_billed_hours)
|
||||||
|
billing_amount = flt(timesheet.total_billable_amount) - flt(timesheet.total_billed_amount)
|
||||||
|
billing_rate = billing_amount / hours
|
||||||
|
|
||||||
|
if customer:
|
||||||
|
target.customer = customer
|
||||||
|
|
||||||
|
if item_code:
|
||||||
|
target.append('items', {
|
||||||
|
'item_code': item_code,
|
||||||
|
'qty': hours,
|
||||||
|
'rate': billing_rate
|
||||||
|
})
|
||||||
|
|
||||||
target.append('timesheets', {
|
target.append('timesheets', {
|
||||||
'time_sheet': timesheet.name,
|
'time_sheet': timesheet.name,
|
||||||
'billing_hours': flt(timesheet.total_billable_hours) - flt(timesheet.total_billed_hours),
|
'billing_hours': hours,
|
||||||
'billing_amount': flt(timesheet.total_billable_amount) - flt(timesheet.total_billed_amount)
|
'billing_amount': billing_amount
|
||||||
})
|
})
|
||||||
|
|
||||||
target.run_method("calculate_billing_amount_for_timesheet")
|
target.run_method("calculate_billing_amount_for_timesheet")
|
||||||
|
target.run_method("set_missing_values")
|
||||||
|
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user