Generate in .XLS format, remove header border, exclude negative price line (discount), remove duplicate value in
This commit is contained in:
parent
8cf0a6c037
commit
5aa9c0f0f5
@ -12,6 +12,11 @@ try:
|
||||
except ImportError:
|
||||
xlsxwriter = None
|
||||
|
||||
try:
|
||||
import xlwt
|
||||
except ImportError:
|
||||
xlwt = None
|
||||
|
||||
class PosExportBcWizard(models.TransientModel):
|
||||
_name = 'pos.export.bc.wizard'
|
||||
_description = 'POS Export BC Format Wizard'
|
||||
@ -23,7 +28,7 @@ class PosExportBcWizard(models.TransientModel):
|
||||
return self._generate_export(old_format=False)
|
||||
|
||||
def action_export_old_popcorn(self):
|
||||
return self._generate_export(old_format=True)
|
||||
return self._generate_export_xls()
|
||||
|
||||
def _generate_export(self, old_format=False):
|
||||
self.ensure_one()
|
||||
@ -37,9 +42,10 @@ class PosExportBcWizard(models.TransientModel):
|
||||
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
|
||||
|
||||
# Define formats
|
||||
header_format = workbook.add_format({
|
||||
'bold': True, 'align': 'center', 'valign': 'vcenter', 'border': 1
|
||||
})
|
||||
header_kwargs = {'bold': True, 'align': 'center', 'valign': 'vcenter'}
|
||||
if not old_format:
|
||||
header_kwargs['border'] = 1
|
||||
header_format = workbook.add_format(header_kwargs)
|
||||
title_format = workbook.add_format({
|
||||
'bold': True, 'align': 'center', 'valign': 'vcenter', 'font_color': 'red', 'size': 14
|
||||
})
|
||||
@ -129,14 +135,26 @@ class PosExportBcWizard(models.TransientModel):
|
||||
|
||||
is_first_line = True
|
||||
for line in order.lines:
|
||||
sheet.write(row_num, 0, order_no)
|
||||
if local_date:
|
||||
date_str = local_date.strftime('%d-%m-%Y %H:%M:%S')
|
||||
sheet.write_string(row_num, 1, date_str)
|
||||
if old_format and line.price_unit < 0:
|
||||
continue
|
||||
|
||||
sheet.write(row_num, 2, outlet)
|
||||
sheet.write(row_num, 3, table_customer)
|
||||
sheet.write(row_num, 4, invoice)
|
||||
if old_format and not is_first_line:
|
||||
sheet.write_string(row_num, 0, "")
|
||||
sheet.write_string(row_num, 1, "")
|
||||
sheet.write_string(row_num, 2, "")
|
||||
sheet.write_string(row_num, 3, "")
|
||||
sheet.write_string(row_num, 4, "")
|
||||
else:
|
||||
sheet.write(row_num, 0, order_no)
|
||||
if local_date:
|
||||
date_str = local_date.strftime('%d-%m-%Y %H:%M:%S')
|
||||
sheet.write_string(row_num, 1, date_str)
|
||||
else:
|
||||
sheet.write_string(row_num, 1, "")
|
||||
|
||||
sheet.write(row_num, 2, outlet)
|
||||
sheet.write(row_num, 3, table_customer)
|
||||
sheet.write(row_num, 4, invoice)
|
||||
|
||||
category = line.product_id.pos_categ_ids[0].name if line.product_id.pos_categ_ids else ''
|
||||
sku = line.product_id.x_studio_bc_item_id if 'x_studio_bc_item_id' in line.product_id._fields and line.product_id.x_studio_bc_item_id else ''
|
||||
@ -235,3 +253,182 @@ class PosExportBcWizard(models.TransientModel):
|
||||
'url': f'/web/content/{attachment.id}?download=true',
|
||||
'target': 'self',
|
||||
}
|
||||
|
||||
def _generate_export_xls(self):
|
||||
self.ensure_one()
|
||||
if not xlwt:
|
||||
raise UserError(_("The Python library 'xlwt' is required. Please install it with 'pip install xlwt'."))
|
||||
|
||||
if self.start_date > self.end_date:
|
||||
raise UserError(_("Start Date must be earlier or equal to End Date."))
|
||||
|
||||
output = io.BytesIO()
|
||||
workbook = xlwt.Workbook(encoding='utf-8')
|
||||
|
||||
# Define formats for xlwt
|
||||
header_format = xlwt.easyxf('font: bold on; align: horiz center, vert center;')
|
||||
title_format = xlwt.easyxf('font: bold on, color red, height 280; align: horiz center, vert center;') # height is in twips (14 * 20)
|
||||
subtitle_format = xlwt.easyxf('font: bold on, color black, height 240; align: horiz center, vert center;') # 12 * 20
|
||||
date_time_format = xlwt.easyxf(num_format_str='DD-MM-YYYY HH:MM:SS')
|
||||
number_format = xlwt.easyxf(num_format_str='#,##0.00')
|
||||
|
||||
headers = [
|
||||
"No", "Date", "Outlet", "Table/Customer", "Invoice", "Category", "SKU", "Product", "Quantity",
|
||||
"Price Type", "Price", "Price Cut", "Subtotal", "Discount", "Tax", "Service", "Rounding",
|
||||
"Charge", "Paid", "Pax", "Return", "Refund", "Payment", "Note", "Dinein", "User"
|
||||
]
|
||||
|
||||
# Datetime timezone conversion
|
||||
user_tz_str = self.env.user.tz or 'UTC'
|
||||
user_tz = pytz.timezone(user_tz_str)
|
||||
|
||||
start_datetime = datetime.combine(self.start_date, datetime.min.time())
|
||||
end_datetime = datetime.combine(self.end_date, datetime.max.time())
|
||||
|
||||
start_utc = user_tz.localize(start_datetime).astimezone(pytz.UTC).replace(tzinfo=None)
|
||||
end_utc = user_tz.localize(end_datetime).astimezone(pytz.UTC).replace(tzinfo=None)
|
||||
|
||||
def write_sheet(sheet_name, domain):
|
||||
sheet = workbook.add_sheet(sheet_name)
|
||||
|
||||
# Title
|
||||
sheet.write_merge(0, 0, 0, 25, 'MIE MAPAN', title_format)
|
||||
sheet.write_merge(1, 1, 0, 25, 'INVOICES', subtitle_format)
|
||||
|
||||
# Period
|
||||
start_dt_str = start_datetime.strftime('%d-%m-%Y 00:00')
|
||||
end_dt_str = end_datetime.strftime('%d-%m-%Y 23:59')
|
||||
sheet.write(2, 0, 'Period')
|
||||
sheet.write(2, 1, ':')
|
||||
sheet.write(2, 2, f"{start_dt_str} - {end_dt_str}")
|
||||
|
||||
# Headers
|
||||
for col_num, header in enumerate(headers):
|
||||
sheet.write(4, col_num, header, header_format)
|
||||
|
||||
row_num = 5
|
||||
orders = self.env['pos.order'].search(domain, order='date_order asc')
|
||||
|
||||
order_no = 1
|
||||
for order in orders:
|
||||
if 'refund_orders_count' in order._fields and order.refund_orders_count > 0:
|
||||
continue
|
||||
|
||||
local_date = order.date_order.replace(tzinfo=pytz.UTC).astimezone(user_tz) if order.date_order else False
|
||||
|
||||
outlet = order.config_id.name or ''
|
||||
table = str(order.table_id.table_number) if 'table_id' in order._fields and order.table_id else ''
|
||||
customer = order.partner_id.name or ''
|
||||
floating_order_name = order.floating_order_name if 'floating_order_name' in order._fields and order.floating_order_name else ''
|
||||
table_customer = table or floating_order_name or customer
|
||||
invoice = order.pos_reference or order.name
|
||||
|
||||
subtotal = sum(l.price_subtotal for l in order.lines)
|
||||
discount_order = sum(abs(l.price_subtotal) for l in order.lines if l.price_unit < 0)
|
||||
tax = order.amount_tax
|
||||
charge = order.amount_total
|
||||
paid = sum(p.amount for p in order.payment_ids if p.amount > 0)
|
||||
pax = order.customer_count if 'customer_count' in order._fields else 1
|
||||
return_amt = order.amount_return if 'amount_return' in order._fields else (paid - charge if paid > charge else 0)
|
||||
|
||||
payment_methods = ', '.join(order.payment_ids.mapped('payment_method_id.name'))
|
||||
note = order.note if 'note' in order._fields else ''
|
||||
if 'table_id' in order._fields and order.table_id:
|
||||
dinein = "dinein"
|
||||
else:
|
||||
dinein = "takeaway"
|
||||
user = order.user_id.name or ''
|
||||
|
||||
is_first_line = True
|
||||
for line in order.lines:
|
||||
if line.price_unit < 0:
|
||||
continue
|
||||
|
||||
if not is_first_line:
|
||||
sheet.write(row_num, 0, "")
|
||||
sheet.write(row_num, 1, "")
|
||||
sheet.write(row_num, 2, "")
|
||||
sheet.write(row_num, 3, "")
|
||||
sheet.write(row_num, 4, "")
|
||||
else:
|
||||
sheet.write(row_num, 0, order_no)
|
||||
if local_date:
|
||||
date_str = local_date.strftime('%d-%m-%Y %H:%M:%S')
|
||||
sheet.write(row_num, 1, date_str)
|
||||
else:
|
||||
sheet.write(row_num, 1, "")
|
||||
|
||||
sheet.write(row_num, 2, outlet)
|
||||
sheet.write(row_num, 3, table_customer)
|
||||
sheet.write(row_num, 4, invoice)
|
||||
|
||||
category = line.product_id.pos_categ_ids[0].name if line.product_id.pos_categ_ids else ''
|
||||
sku = line.product_id.x_studio_bc_item_id if 'x_studio_bc_item_id' in line.product_id._fields and line.product_id.x_studio_bc_item_id else ''
|
||||
product_name = line.product_id.name or ''
|
||||
qty = line.qty
|
||||
|
||||
price_type = order.pricelist_id.name or 'DEFAULT'
|
||||
price = line.price_unit
|
||||
price_cut = (line.price_unit * line.discount / 100) if line.discount else 0.0
|
||||
|
||||
sheet.write(row_num, 5, category)
|
||||
sheet.write(row_num, 6, sku)
|
||||
sheet.write(row_num, 7, product_name)
|
||||
sheet.write(row_num, 8, qty)
|
||||
sheet.write(row_num, 9, price_type)
|
||||
sheet.write(row_num, 10, price, number_format)
|
||||
sheet.write(row_num, 11, price_cut, number_format)
|
||||
|
||||
if is_first_line:
|
||||
sheet.write(row_num, 12, subtotal, number_format)
|
||||
sheet.write(row_num, 13, discount_order, number_format)
|
||||
sheet.write(row_num, 14, tax, number_format)
|
||||
sheet.write(row_num, 15, 0, number_format) # Service
|
||||
sheet.write(row_num, 16, 0, number_format) # Rounding
|
||||
sheet.write(row_num, 17, charge, number_format)
|
||||
sheet.write(row_num, 18, paid, number_format)
|
||||
sheet.write(row_num, 19, pax)
|
||||
sheet.write(row_num, 20, return_amt, number_format)
|
||||
sheet.write(row_num, 21, 0, number_format) # Refund
|
||||
sheet.write(row_num, 22, payment_methods)
|
||||
sheet.write(row_num, 23, note)
|
||||
sheet.write(row_num, 24, dinein)
|
||||
sheet.write(row_num, 25, user)
|
||||
|
||||
is_first_line = False
|
||||
|
||||
row_num += 1
|
||||
order_no += 1
|
||||
|
||||
domain_base = [('date_order', '>=', start_utc), ('date_order', '<=', end_utc)]
|
||||
write_sheet('Invoice', domain_base + [('amount_total', '>=', 0)])
|
||||
write_sheet('Refund', domain_base + [('amount_total', '<', 0)])
|
||||
|
||||
workbook.save(output)
|
||||
output.seek(0)
|
||||
|
||||
company = self.env.company
|
||||
company_ident = (company.company_registry or company.name or '').upper().replace(' ', '')
|
||||
|
||||
# Max length logic
|
||||
company_len = 10
|
||||
company_ident = company_ident[:company_len]
|
||||
|
||||
start_str = self.start_date.strftime('%y%m%d')
|
||||
end_str = self.end_date.strftime('%y%m%d')
|
||||
|
||||
file_name = f"POS_{company_ident}_{start_str}_to_{end_str}_OLD.xls"
|
||||
|
||||
# Save as an ir.attachment and return action to download
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': file_name,
|
||||
'type': 'binary',
|
||||
'datas': base64.b64encode(output.read()),
|
||||
'mimetype': 'application/vnd.ms-excel'
|
||||
})
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': f'/web/content/{attachment.id}?download=true',
|
||||
'target': 'self',
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user