Merge branch 'master' of github.com:webnotes/erpnext

This commit is contained in:
Rushabh Mehta 2012-10-19 08:49:33 +02:00
commit 140bbca1fe
6 changed files with 116 additions and 84 deletions

View File

@ -18,7 +18,7 @@ report.customize_filters = function() {
this.hide_all_filters(); this.hide_all_filters();
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df.filter_hide = 0;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df.filter_hide = 1;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Account'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Account'].df.filter_hide = 0;
@ -28,7 +28,6 @@ report.customize_filters = function() {
this.add_filter({fieldname:'range_3', label:'Range 3', fieldtype:'Data', ignore : 1, parent:'GL Entry', report_default:60}); this.add_filter({fieldname:'range_3', label:'Range 3', fieldtype:'Data', ignore : 1, parent:'GL Entry', report_default:60});
this.add_filter({fieldname:'range_4', label:'Range 4', fieldtype:'Data', ignore : 1, parent:'GL Entry', report_default:90}); this.add_filter({fieldname:'range_4', label:'Range 4', fieldtype:'Data', ignore : 1, parent:'GL Entry', report_default:90});
this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df['report_default']=sys_defaults.year_start_date;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df['report_default']=dateutil.obj_to_str(new Date()); this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df['report_default']=dateutil.obj_to_str(new Date());
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df['report_default']=sys_defaults.company; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df['report_default']=sys_defaults.company;

View File

@ -18,14 +18,14 @@
# ------------------------------------------------------------------ # ------------------------------------------------------------------
from __future__ import unicode_literals from __future__ import unicode_literals
if not filter_values.get('posting_date') or not filter_values.get('posting_date1'): if not filter_values.get('posting_date1'):
msgprint("Please select From Posting Date and To Posting Date ") msgprint("Please select To Posting Date ")
raise Exception raise Exception
else: else:
from_date = filter_values.get('posting_date')
to_date = filter_values.get('posting_date1') to_date = filter_values.get('posting_date1')
if not filter_values['range_1'] or not filter_values['range_2'] or not filter_values['range_3'] or not filter_values['range_4']: if not filter_values['range_1'] or not filter_values['range_2'] \
or not filter_values['range_3'] or not filter_values['range_4']:
msgprint("Please select aging ranges in no of days in 'More Filters' ") msgprint("Please select aging ranges in no of days in 'More Filters' ")
raise Exception raise Exception
@ -74,26 +74,25 @@ if filter_values.has_key('aging_based_on') and filter_values['aging_based_on']:
aging_based_on = filter_values['aging_based_on'].split(NEWLINE)[-1] aging_based_on = filter_values['aging_based_on'].split(NEWLINE)[-1]
if len(res) > 2000 and from_export == 0: if len(res) > 2000 and from_export == 0:
msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.Please select Account or click on 'Export' to open in excel") msgprint("""This is a very large report and cannot be shown in the browser
raise Exception as it is likely to make your browser very slow.
Please select Account or click on 'Export' to open in excel""", raise_exception=1)
# ------------------------------------------------------------------
# main loop starts here
# ------------------------------------------------------------------
# get supplier type # get supplier type
supp_type_dict = {} supp_type_dict = {}
for each in sql("select t2.name, t1.supplier_type from tabSupplier t1, tabAccount t2 where t1.name = t2.account_name group by t2.name"): for each in sql("""select t2.name, t1.supplier_type from tabSupplier t1, tabAccount t2
where t1.name = t2.account_name group by t2.name"""):
supp_type_dict[each[0]] = each[1] supp_type_dict[each[0]] = each[1]
# get due_date, bill_no, bill_date from PV # get due_date, bill_no, bill_date from PV
pv_dict = {} pv_dict = {}
for t in sql("select name, due_date, bill_no, bill_date from `tabPurchase Invoice` group by name"): for t in sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` group by name"""):
pv_dict[t[0]] = [cstr(t[1]), t[2], cstr(t[3])] pv_dict[t[0]] = [cstr(t[1]), t[2], cstr(t[3])]
# pv outside this period # pv after to-date
pv_outside_period = [d[0] for d in sql("select distinct name from `tabPurchase Invoice` where (posting_date < '%s' or posting_date > '%s') and docstatus = 1" % (from_date, to_date))] pv_after_to_date = [d[0] for d in sql("""select distinct name from `tabPurchase Invoice`
where posting_date > %s and docstatus = 1""", (to_date,))]
from webnotes.utils import nowdate from webnotes.utils import nowdate
@ -118,23 +117,31 @@ for r in res:
cond = " and ifnull(against_voucher, '') = '%s'" % r[col_idx['Against Voucher']] cond = " and ifnull(against_voucher, '') = '%s'" % r[col_idx['Against Voucher']]
# if entry against JV & and not adjusted within period # if entry against JV & and not adjusted within period
elif r[col_idx['Against Voucher Type']] == 'Purchase Invoice' and r[col_idx['Against Voucher']] in pv_outside_period: elif r[col_idx['Against Voucher Type']] == 'Purchase Invoice' \
and r[col_idx['Against Voucher']] in pv_after_to_date:
booking_amt = 0 booking_amt = 0
cond = " and voucher_no = '%s' and ifnull(against_voucher, '') = '%s'" % (r[col_idx['Voucher No']], r[col_idx['Against Voucher']]) cond = """ and voucher_no = '%s' and ifnull(against_voucher, '') = '%s'""" \
% (r[col_idx['Voucher No']], r[col_idx['Against Voucher']])
# if un-adjusted # if un-adjusted
elif not r[col_idx['Against Voucher']]: elif not r[col_idx['Against Voucher']]:
booking_amt = 0 booking_amt = 0
cond = " and ((voucher_no = '%s' and ifnull(against_voucher, '') = '') or (ifnull(against_voucher, '') = '%s' and voucher_type = 'Journal Voucher'))" % (r[col_idx['Voucher No']], r[col_idx['Voucher No']]) cond = """ and ((voucher_no = '%s' and ifnull(against_voucher, '') = '')
or (ifnull(against_voucher, '') = '%s' and voucher_type = 'Journal Voucher'))""" \
% (r[col_idx['Voucher No']], r[col_idx['Voucher No']])
if cond: if cond:
outstanding_amt = flt(sql("select sum(ifnull(credit, 0))-sum(ifnull(debit, 0)) from `tabGL Entry` where account = '%s' and ifnull(is_cancelled, 'No') = 'No' and posting_date <= '%s' %s" % (r[col_idx['Account']], to_date, cond))[0][0] or 0) outstanding_amt = flt(sql("""select sum(ifnull(credit, 0))-sum(ifnull(debit, 0))
from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'No'
and posting_date <= %s %s"""
% ('%s', '%s', cond), (r[col_idx['Account']], to_date,))[0][0] or 0)
# add to total outstanding # add to total outstanding
total_outstanding_amt += flt(outstanding_amt) total_outstanding_amt += flt(outstanding_amt)
# add to total booking amount # add to total booking amount
if outstanding_amt and r[col_idx['Voucher Type']] == 'Purchase Invoice' and r[col_idx['Against Voucher']]: if outstanding_amt and r[col_idx['Voucher Type']] == 'Purchase Invoice' \
and r[col_idx['Against Voucher']]:
total_booking_amt += flt(booking_amt) total_booking_amt += flt(booking_amt)
r += [booking_amt, outstanding_amt] r += [booking_amt, outstanding_amt]

View File

@ -1,11 +1,16 @@
SELECT DISTINCT `tabGL Entry`.`Aging_date`,`tabGL Entry`.`account`, `tabGL Entry`.`against_voucher_type`, `tabGL Entry`.`against_voucher`,`tabGL Entry`.`voucher_type`,`tabGL Entry`.`voucher_no`, `tabGL Entry`.`remarks`, `tabGL Entry`.`credit` SELECT DISTINCT
FROM `tabGL Entry`,`tabAccount` `tabGL Entry`.`Aging_date`,`tabGL Entry`.`account`, `tabGL Entry`.`against_voucher_type`,
WHERE `tabGL Entry`.`posting_date`>= '%(posting_date)s' `tabGL Entry`.`against_voucher`,`tabGL Entry`.`voucher_type`,`tabGL Entry`.`voucher_no`,
AND `tabGL Entry`.`posting_date`<= '%(posting_date1)s' `tabGL Entry`.`remarks`, `tabGL Entry`.`credit`
FROM
`tabGL Entry`,`tabAccount`
WHERE
`tabGL Entry`.`posting_date`<= '%(posting_date1)s'
AND `tabGL Entry`.`account` LIKE '%(account)s%%' AND `tabGL Entry`.`account` LIKE '%(account)s%%'
AND `tabGL Entry`.`company` LIKE '%(company)s%%' AND `tabGL Entry`.`company` LIKE '%(company)s%%'
AND ((ifnull(`tabGL Entry`.voucher_type,'') = 'Purchase Invoice' and `tabGL Entry`.credit>0) OR `tabGL Entry`.voucher_type = 'Journal Voucher') AND ((ifnull(`tabGL Entry`.`voucher_type`,'') = 'Purchase Invoice'
AND `tabGL Entry`.`credit`>0) OR `tabGL Entry`.voucher_type = 'Journal Voucher')
AND `tabGL Entry`.`is_cancelled` = 'No' AND `tabGL Entry`.`is_cancelled` = 'No'
AND `tabAccount`.master_type = 'Supplier' AND `tabAccount`.master_type = 'Supplier'
AND `tabAccount`.name = `tabGL Entry`.account AND `tabAccount`.name = `tabGL Entry`.account
ORDER BY `tabGL Entry`.`posting_date` ORDER BY `tabGL Entry`.`posting_date`

View File

@ -18,7 +18,7 @@ report.customize_filters = function() {
this.hide_all_filters(); this.hide_all_filters();
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df.filter_hide = 0;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df.filter_hide = 1;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Account'].df.filter_hide = 0; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Account'].df.filter_hide = 0;
@ -28,7 +28,6 @@ report.customize_filters = function() {
this.add_filter({fieldname:'range_3', label:'Range 3', fieldtype:'Data', ignore : 1, parent:'GL Entry'}); this.add_filter({fieldname:'range_3', label:'Range 3', fieldtype:'Data', ignore : 1, parent:'GL Entry'});
this.add_filter({fieldname:'range_4', label:'Range 4', fieldtype:'Data', ignore : 1, parent:'GL Entry'}); this.add_filter({fieldname:'range_4', label:'Range 4', fieldtype:'Data', ignore : 1, parent:'GL Entry'});
this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Posting Date'].df['report_default']=sys_defaults.year_start_date;
this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df['report_default']=dateutil.obj_to_str(new Date()); this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Posting Date'].df['report_default']=dateutil.obj_to_str(new Date());
this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df['report_default']=sys_defaults.company; this.filter_fields_dict['GL Entry'+FILTER_SEP +'Company'].df['report_default']=sys_defaults.company;

View File

@ -18,15 +18,14 @@
# Check mandatory filters # Check mandatory filters
#------------------------------ #------------------------------
from __future__ import unicode_literals from __future__ import unicode_literals
if not filter_values.get('posting_date') or not filter_values.get('posting_date1'): if not filter_values.get('posting_date1'):
msgprint("Please select From Posting Date and To Posting Date in 'Set Filters' section") msgprint("Please select To Posting Date", raise_exception=1)
raise Exception
else: else:
from_date = filter_values.get('posting_date')
to_date = filter_values.get('posting_date1') to_date = filter_values.get('posting_date1')
if not filter_values['range_1'] or not filter_values['range_2'] or not filter_values['range_3'] or not filter_values['range_4']: if not filter_values['range_1'] or not filter_values['range_2'] or \
msgprint("Please select aging ranges in no of days in 'Set Filters' section") not filter_values['range_3'] or not filter_values['range_4']:
msgprint("Please select aging ranges in no of days in 'More Filters' section")
raise Exception raise Exception
# validate Range # validate Range
@ -72,47 +71,66 @@ if len(res) > 2000 and from_export == 0:
msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.Please select Account or click on 'Export' to open in excel") msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.Please select Account or click on 'Export' to open in excel")
raise Exception raise Exception
# ------------------------------------------------------------------
# main loop starts here # get supplier type
# ------------------------------------------------------------------ territory_dict = {}
for each in sql("""select t2.name, t1.territory from `tabCustomer` t1, `tabAccount` t2
where t1.name = t2.master_name group by t2.name"""):
territory_dict[each[0]] = each[1]
# get due_date from sales invoice
si_dict = {}
for t in sql("""select name, due_date from `tabSales Invoice` group by name"""):
si_dict[t[0]] = t[1]
# sales invoice after to-date
si_after_to_date = [d[0] for d in sql("""select distinct name from `tabSales Invoice`
where posting_date > %s and docstatus = 1""", (to_date,))]
from webnotes.utils import nowdate from webnotes.utils import nowdate
out = [] out = []
total_opening_amt,total_outstanding_amt = 0,0 total_booking_amt, total_outstanding_amt = 0,0
for r in res: for r in res:
# get customer territory outstanding_amt = 0
terr = sql("select t1.territory from `tabCustomer` t1, `tabAccount` t2 where t1.name = t2.master_name and t2.name = '%s'" % r[col_idx['Account']]) cond = due_date = ''
r.append(terr and terr[0][0] or '') booking_amt = r.pop(7)
# get customer territory
r.append(territory_dict.get(r[col_idx['Account']], ''))
outstanding_amt, opening_amt, cond, due_date = 0,0, '', ''
# if entry against Sales Invoice # if entry against Sales Invoice
if r[col_idx['Against Voucher']] and r[col_idx['Voucher Type']] == 'Sales Invoice': if r[col_idx['Against Voucher']] and r[col_idx['Voucher Type']] == 'Sales Invoice':
# get due date # get due date
due_date = sql("select due_date from `tabSales Invoice` where name = '%s'" % r[col_idx['Against Voucher']]) due_date = si_dict.get(r[col_idx['Voucher No']], '')
due_date = due_date and cstr(due_date[0][0]) or '' cond = """ and ifnull(against_voucher, '') = '%s'""" % r[col_idx['Against Voucher']]
# get booking amt
opening_amt = sql("select debit from `tabGL Entry` where account = '%s' and voucher_no = '%s' and is_cancelled = 'No'" % (r[col_idx['Account']], r[col_idx['Voucher No']]))
opening_amt = opening_amt and flt(opening_amt[0][0]) or 0
cond = "and against_voucher = '%s' and against_voucher is not null" % r[col_idx['Against Voucher']]
# if entry against JV & and not adjusted within period # if entry against JV & and not adjusted within period
elif r[col_idx['Against Voucher Type']] == 'Sales Invoice' and sql("select name from `tabSales Invoice` where name = '%s' and (posting_date < '%s' or posting_date > '%s') and docstatus = 1" % (r[col_idx['Against Voucher']], from_date, to_date)): elif r[col_idx['Against Voucher Type']] == 'Sales Invoice' \
cond = " and voucher_no = '%s' and ifnull(against_voucher, '') = '%s'" % (r[col_idx['Voucher No']], r[col_idx['Against Voucher']]) and r[col_idx['Against Voucher']] in si_after_to_date:
booking_amt = 0
cond = """ and voucher_no = '%s' and ifnull(against_voucher, '') = '%s'""" \
% (r[col_idx['Voucher No']], r[col_idx['Against Voucher']])
# if entry against JV and unadjusted # if entry against JV and unadjusted
elif not r[col_idx['Against Voucher']]: elif not r[col_idx['Against Voucher']]:
cond = " and ((voucher_no = '%s' and ifnull(against_voucher, '') = '') or (ifnull(against_voucher, '') = '%s' and voucher_type = 'Journal Voucher'))" % (r[col_idx['Voucher No']], r[col_idx['Voucher No']]) booking_amt = 0
cond = """ and ((voucher_no = '%s' and ifnull(against_voucher, '') = '')
or (ifnull(against_voucher, '') = '%s' and voucher_type = 'Journal Voucher'))""" \
% (r[col_idx['Voucher No']], r[col_idx['Voucher No']])
if cond: if cond:
outstanding_amt = flt(sql("select ifnull(sum(debit),0) - ifnull(sum(credit),0) from `tabGL Entry` where account = '%s' and ifnull(is_cancelled, 'No') = 'No' and posting_date <= '%s' %s" % (r[col_idx['Account']], to_date, cond))[0][0] or 0) outstanding_amt = flt(sql("""select ifnull(sum(debit),0) - ifnull(sum(credit),0)
from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'No'
and posting_date <= %s %s"""
% ('%s', '%s', cond), (r[col_idx['Account']], to_date,))[0][0] or 0)
# add to total outstanding # add to total outstanding
total_outstanding_amt += flt(outstanding_amt) total_outstanding_amt += flt(outstanding_amt)
# add to total booking amount # add to total booking amount
if outstanding_amt and r[col_idx['Voucher Type']] == 'Sales Invoice' and r[col_idx['Against Voucher']]: if outstanding_amt and r[col_idx['Voucher Type']] == 'Sales Invoice' and r[col_idx['Against Voucher']]:
total_opening_amt += flt(opening_amt) total_booking_amt += flt(booking_amt)
r += [due_date, opening_amt, outstanding_amt] r += [due_date, booking_amt, outstanding_amt]
#Ageing Outstanding #Ageing Outstanding
val_l1 = val_l2 = val_l3 = val_l4 = val_l5_above = 0 val_l1 = val_l2 = val_l3 = val_l4 = val_l5_above = 0
@ -121,31 +139,30 @@ for r in res:
if getdate(to_date) > getdate(nowdate()): if getdate(to_date) > getdate(nowdate()):
to_date = nowdate() to_date = nowdate()
diff = (getdate(to_date) - getdate(r[col_idx[aging_based_on]])).days diff = (getdate(to_date) - getdate(r[col_idx[aging_based_on]])).days
if diff < cint(filter_values['range_1']): if diff <= cint(filter_values['range_1']):
val_l1 = outstanding_amt val_l1 = outstanding_amt
if diff >= cint(filter_values['range_1']) and diff < cint(filter_values['range_2']): if diff > cint(filter_values['range_1']) and diff <= cint(filter_values['range_2']):
val_l2 = outstanding_amt val_l2 = outstanding_amt
if diff >= cint(filter_values['range_2']) and diff < cint(filter_values['range_3']): if diff > cint(filter_values['range_2']) and diff <= cint(filter_values['range_3']):
val_l3 = outstanding_amt val_l3 = outstanding_amt
if diff >= cint(filter_values['range_3']) and diff < cint(filter_values['range_4']): if diff > cint(filter_values['range_3']) and diff <= cint(filter_values['range_4']):
val_l4 = outstanding_amt val_l4 = outstanding_amt
if diff >= cint(filter_values['range_4']): if diff > cint(filter_values['range_4']):
val_l5_above = outstanding_amt val_l5_above = outstanding_amt
r += [diff, val_l1, val_l2, val_l3, val_l4, val_l5_above] r += [diff, val_l1, val_l2, val_l3, val_l4, val_l5_above]
# Only show that entry which has outstanding # Only show that entry which has outstanding
if abs(flt(outstanding_amt)) > 0.001: if abs(flt(outstanding_amt)) > 0.001:
out.append(r) out.append(r)
if len(out) > 300 and from_export == 0: if len(out) > 500 and from_export == 0:
msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.Please select Account or click on 'Export' to open in excel") msgprint("This is a very large report and cannot be shown in the browser as it is likely to make your browser very slow.Please select Account or click on 'Export' to open in excel")
raise Exception raise Exception
# Append Extra rows to RES # Append Extra rows to res
if len(out) > 0: if len(out) > 0:
t_row = ['' for i in range(len(colnames))] t_row = ['' for i in range(len(colnames))]
t_row[col_idx['Voucher No']] = 'Total' t_row[col_idx['Voucher No']] = 'Total'
t_row[col_idx['Opening Amt']] = total_opening_amt t_row[col_idx['Opening Amt']] = total_booking_amt
t_row[col_idx['Outstanding Amt']] = total_outstanding_amt t_row[col_idx['Outstanding Amt']] = total_outstanding_amt
out.append(t_row) out.append(t_row)

View File

@ -1,11 +1,16 @@
SELECT `tabGL Entry`.`aging_date`,`tabGL Entry`.`account`, `tabGL Entry`.`against_voucher_type`, `tabGL Entry`.`against_voucher`,`tabGL Entry`.`voucher_type`,`tabGL Entry`.`voucher_no`, `tabGL Entry`.remarks SELECT
FROM `tabGL Entry`,`tabAccount` `tabGL Entry`.`aging_date`,`tabGL Entry`.`account`, `tabGL Entry`.`against_voucher_type`,
WHERE `tabGL Entry`.`posting_date`>= '%(posting_date)s' `tabGL Entry`.`against_voucher`,`tabGL Entry`.`voucher_type`,`tabGL Entry`.`voucher_no`,
AND `tabGL Entry`.`posting_date`<= '%(posting_date1)s' `tabGL Entry`.`remarks`, `tabGL Entry`.`debit`
FROM
`tabGL Entry`,`tabAccount`
WHERE
`tabGL Entry`.`posting_date`<= '%(posting_date1)s'
AND `tabGL Entry`.`account` LIKE '%(account)s%%' AND `tabGL Entry`.`account` LIKE '%(account)s%%'
AND `tabGL Entry`.`company` LIKE '%(company)s%%' AND `tabGL Entry`.`company` LIKE '%(company)s%%'
AND ((`tabGL Entry`.voucher_type = 'Sales Invoice' and `tabGL Entry`.debit>0) OR `tabGL Entry`.voucher_type = 'Journal Voucher') AND ((`tabGL Entry`.`voucher_type` = 'Sales Invoice' and `tabGL Entry`.`debit`>0)
OR `tabGL Entry`.`voucher_type` = 'Journal Voucher')
AND `tabGL Entry`.`is_cancelled` = 'No' AND `tabGL Entry`.`is_cancelled` = 'No'
AND `tabAccount`.master_type = 'Customer' AND `tabAccount`.`master_type` = 'Customer'
AND `tabAccount`.name = `tabGL Entry`.account AND `tabAccount`.`name` = `tabGL Entry`.`account`
ORDER BY `tabGL Entry`.`posting_date` ORDER BY `tabGL Entry`.`posting_date`