diff --git a/__init__.py b/__init__.py index 8077079..d9abe71 100644 --- a/__init__.py +++ b/__init__.py @@ -29,6 +29,7 @@ def register(): product.Product, shop.SaleShop, shop.ShopDailySummaryStart, + shop.ShopDailyCategoryStart, sale.SaleUpdateDateStart, sale.SaleDetailedStart, sale.SaleIncomeDailyStart, @@ -50,6 +51,7 @@ def register(): Pool.register( account.SaleAccountMovesReport, shop.ShopDailySummaryReport, + shop.ShopDailyCategoryReport, sale.SaleDetailedReport, sale.SaleIncomeDailyReport, sale.SaleByKindReport, @@ -64,6 +66,7 @@ def register(): sale.SaleUpdateDate, sale.SalesCosts, shop.ShopDailySummary, + shop.ShopDailyCategory, sale.SaleIncomeDaily, sale.SaleByKind, sale.PortfolioPayments, diff --git a/locale/es.po b/locale/es.po index 4936361..6c62e9f 100644 --- a/locale/es.po +++ b/locale/es.po @@ -313,6 +313,11 @@ msgctxt "field:sale.shop,electronic_authorization:" msgid "Electronic Authorization" msgstr "Autorización Electrónica" +#, fuzzy +msgctxt "field:sale.shop,email_template:" +msgid "Template" +msgstr "Plantilla" + msgctxt "field:sale.shop,freight_product:" msgid "Freight Product" msgstr "Flete" @@ -570,6 +575,22 @@ msgctxt "field:sale_pos.sales_costs.start,start_date:" msgid "Start Date" msgstr "Fecha Inicial" +msgctxt "field:sale_pos.shop_daily_category.start,company:" +msgid "Company" +msgstr "Empresa" + +msgctxt "field:sale_pos.shop_daily_category.start,early_morning_included:" +msgid "Early Morning Included" +msgstr "Incluir Madrugada" + +msgctxt "field:sale_pos.shop_daily_category.start,sale_date:" +msgid "Sale Date" +msgstr "Fecha venta" + +msgctxt "field:sale_pos.shop_daily_category.start,shop:" +msgid "Shop" +msgstr "Tienda" + msgctxt "field:sale_pos.shop_daily_summary.start,company:" msgid "Company" msgstr "Compañia" @@ -678,6 +699,10 @@ msgctxt "model:ir.action,name:report_sales_costs" msgid "Sale Costs" msgstr "Costos de Ventas" +msgctxt "model:ir.action,name:report_shop_daily_category" +msgid "Shop Daily Category" +msgstr "Venta Diaria por Categoria" + msgctxt "model:ir.action,name:report_shop_daily_summary" msgid "Shop Daily Summary" msgstr "Informe de Comprobante Diario" @@ -730,6 +755,11 @@ msgctxt "model:ir.action,name:wizard_sale_account_moves" msgid "Sale Account Moves" msgstr "Mov. Contable Ventas" +#, fuzzy +msgctxt "model:ir.action,name:wizard_shop_daily_category" +msgid "Shop Daily Category" +msgstr "Venta Diaria por Categoria" + msgctxt "model:ir.action,name:wizard_shop_daily_summary" msgid "Shop Daily Summary" msgstr "Informe de Comprobante Diario" @@ -937,6 +967,10 @@ msgctxt "model:ir.ui.menu,name:menu_sales_costs" msgid "Sale Costs Report" msgstr "Reporte de Costo de Ventas" +msgctxt "model:ir.ui.menu,name:menu_shop_daily_category" +msgid "Shop Daily Category" +msgstr "Venta Diaria por Categoria" + msgctxt "model:ir.ui.menu,name:menu_shop_daily_summary" msgid "Shop Daily Summary" msgstr "Informe de Comprobante Diario" @@ -1009,6 +1043,10 @@ msgctxt "model:sale_pos.sales_costs.start,name:" msgid "Sales Costs Start" msgstr "Costos de Ventas" +msgctxt "model:sale_pos.shop_daily_category.start,name:" +msgid "Shop Daily Summary Start" +msgstr "Informe de Comprobante Diario" + msgctxt "model:sale_pos.shop_daily_summary.start,name:" msgid "Shop Daily Summary Start" msgstr "Informe de Comprobante Diario" @@ -3197,6 +3235,45 @@ msgctxt "report:sale_pos.sales_costs_report:" msgid "€" msgstr "" +#, fuzzy +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "$" +msgstr "$" + +#, fuzzy +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "-" +msgstr "-" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "Cantidad" +msgstr "" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "DEL" +msgstr "" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "LISTADO PRODUCTOS VENDIDOS POR ARQUEO" +msgstr "" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "Producto" +msgstr "" + +#, fuzzy +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "Total" +msgstr "Total" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "Total por categoria:" +msgstr "" + +msgctxt "report:sale_pos.shop_daily_category_report:" +msgid "Valor" +msgstr "" + #, fuzzy msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "$" @@ -3217,11 +3294,6 @@ msgctxt "report:sale_pos.shop_daily_summary_report:" msgid ")" msgstr ")" -#, fuzzy -msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "," -msgstr "," - #, fuzzy msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "-" @@ -3231,11 +3303,6 @@ msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "." msgstr "" -#, fuzzy -msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "/" -msgstr "/" - msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "/for" msgstr "" @@ -3244,14 +3311,6 @@ msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "0" msgstr "" -msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "00/00/0000" -msgstr "" - -msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "00:00:00" -msgstr "" - msgctxt "report:sale_pos.shop_daily_summary_report:" msgid "11:00 PM" msgstr "" @@ -3388,11 +3447,15 @@ msgid "category['name']" msgstr "" msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "company.id_number" +msgid "company.party.id_number" msgstr "" msgctxt "report:sale_pos.shop_daily_summary_report:" -msgid "company.name" +msgid "company.party.name" +msgstr "" + +msgctxt "report:sale_pos.shop_daily_summary_report:" +msgid "company.time_now()" msgstr "" #, fuzzy @@ -3668,9 +3731,10 @@ msgctxt "view:sale.device:" msgid "Sale Device Configuration" msgstr "Configuración de terminal de venta" +#, fuzzy msgctxt "view:sale.line:" -msgid "Lines" -msgstr "Líneas" +msgid "%" +msgstr "%" msgctxt "view:sale.payment.form:" msgid "" @@ -3876,6 +3940,14 @@ msgctxt "wizard_button:sale_pos.sales_costs,start,print_:" msgid "Print" msgstr "Imprimir" +msgctxt "wizard_button:sale_pos.shop_daily_category,start,end:" +msgid "Cancel" +msgstr "Cancelar" + +msgctxt "wizard_button:sale_pos.shop_daily_category,start,print_:" +msgid "Print" +msgstr "Imprimir" + msgctxt "wizard_button:sale_pos.shop_daily_summary,start,end:" msgid "Cancel" msgstr "Cancelar" diff --git a/shop.py b/shop.py index 603fa55..b02bb65 100644 --- a/shop.py +++ b/shop.py @@ -394,3 +394,219 @@ class ShopDailySummaryReport(Report): report_context['sum_electronic'] = sum(payment_modes['electronic']) report_context['sum_other'] = sum(payment_modes['other']) return report_context + + +class ShopDailyCategoryStart(ModelView): + 'Shop Daily Summary Start' + __name__ = 'sale_pos.shop_daily_category.start' + company = fields.Many2One('company.company', 'Company', required=True) + sale_date = fields.Date('Sale Date', required=True) + shop = fields.Many2One('sale.shop', 'Shop', required=True) + early_morning_included = fields.Boolean('Early Morning Included') + + @staticmethod + def default_company(): + return Transaction().context.get('company') + + @staticmethod + def default_sale_date(): + Date = Pool().get('ir.date') + return Date.today() + + +class ShopDailyCategory(Wizard): + 'Shop Daily Summary' + __name__ = 'sale_pos.shop_daily_category' + start = StateView('sale_pos.shop_daily_category.start', + 'sale_pos.shop_daily_category_start_view_form', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Print', 'print_', 'tryton-ok', default=True), + ]) + print_ = StateReport('sale_pos.shop_daily_category_report') + + def do_print_(self, action): + report_context = { + 'ids': [], + 'company': self.start.company.id, + 'sale_date': self.start.sale_date, + 'shop': self.start.shop.id, + 'early_morning_included': self.start.early_morning_included, + } + return action, report_context + + def transition_print_(self): + return 'end' + + +class ShopDailyCategoryReport(Report): + 'Shop Daily categories' + __name__ = 'sale_pos.shop_daily_category_report' + + @classmethod + def get_query(cls, data, products_exception): + pool = Pool() + Sale = pool.get('sale.sale') + Line = pool.get('sale.line') + Invoice = pool.get('account.invoice') + fixed_hour = time(6, 0) + + cursor = Transaction().connection.cursor() + sale = Sale.__table__() + line = Line.__table__() + result_ = {} + where_ = sale.state.in_(['processing', 'done']) + where_ = line.product.in_(products_exception) + where_ &= sale.company == data['company'] + where_ &= sale.invoice_type == 'P' + where_ &= sale.number != Null + if data['shop']: + where_ &= sale.shop == data['shop'] + + if not data['early_morning_included']: + where_ &= sale.invoice_date == data['sale_date'] + else: + # Select sales including early morning of next day + _start_date = datetime.combine(data['sale_date'], fixed_hour) + _start_date = Company.convert_timezone(_start_date, True) + + end_date = data['sale_date'] + timedelta(days=1) + _end_date = datetime.combine(end_date, fixed_hour) + _end_date = Company.convert_timezone(_end_date, True) + + where_ &= sale_date >= data['sale_date'] + where_ &= sale_date <= end_date + where_ &= create_date >= _start_date + where_ &= create_date <= _end_date + columns_ = [sale.id, Sum(line.unit_price*line.quantity).as_('amount')] + + query = line.join(sale, condition=line.sale==sale.id).select(*columns_, + where=where_, + group_by=sale.id) + + cursor.execute(*query) + result = cursor.fetchall() + for row in result: + result_[row[0]] = row[1] + + return result_ + + @classmethod + def get_context(cls, records, header, data): + report_context = super().get_context(records, header, data) + pool = Pool() + Sale = pool.get('sale.sale') + Company = pool.get('company.company') + company = Company(data['company']) + Shop = pool.get('sale.shop') + fixed_hour = time(6, 0) + + config = pool.get('sale.configuration')(1) + products_exception = [] + amount_exception = {} + if products_exception: + amount_exception = cls.get_query(data, products_exception) + + dom_sales = [ + ('shop', '=', data['shop']), + ('company', '=', data['company']), + ('number', '!=', None), + ('invoice_type', '=', 'P'), + ] + if not data['early_morning_included']: + dom_sales.append(('sale_date', '=', data['sale_date'])) + else: + # Select sales including early morning of next day + _start_date = datetime.combine(data['sale_date'], fixed_hour) + _start_date = Company.convert_timezone(_start_date, True) + + end_date = data['sale_date'] + timedelta(days=1) + _end_date = datetime.combine(end_date, fixed_hour) + _end_date = Company.convert_timezone(_end_date, True) + + dom_sales.append(('sale_date', '>=', data['sale_date'])) + dom_sales.append(('sale_date', '<=', end_date)) + dom_sales.append(('create_date', '>=', _start_date)) + dom_sales.append(('create_date', '<=', _end_date)) + + states_sale = ['processing', 'done'] + dom_sales.append(('state', 'in', states_sale)) + + sales = Sale.search(dom_sales, order=[('number', 'ASC')]) + + total_amount = [] + numbers = [] + categories = {} + _payments = {} + total_payments = [] + for sale in sales: + payments = sale.payments + sale_id = sale.id + device_id = None + try: + value_except = Decimal(amount_exception[sale_id]) + except: + value_except = Decimal(0) + if sale.sale_device: + device_id = sale.sale_device.id + if sale.total_amount <= 0: + continue + + if not sale.invoices: + continue + + invoice = sale.invoices[0] + if not invoice.number or invoice.total_amount <= 0 or not device_id: + continue + numbers.append(invoice.number) + + for line in invoice.lines: + category_id = '0' + if line.product.id in products_exception: + continue + if line.product.categories: + category = line.product.categories[0] + category_id = category.id + if category_id not in categories.keys(): + categories[category_id] = { + 'name': category.name, + 'base': [line.amount], + 'products': {line.product.template.id: { + 'name': line.product.template.name, + 'quantity': line.quantity, + 'amount': line.unit_price, + } + } + } + total_payments.append(line.unit_price) + else: + categories[category_id]['base'].append(line.amount) + if line.product.template.id in categories[category_id]['products'].keys(): + categories[category_id]['products'][line.product.template.id]['quantity'] += line.quantity + categories[category_id]['products'][line.product.template.id]['amount'] += line.unit_price + total_payments.append(line.unit_price) + else: + categories[category_id]['products'][line.product.template.id] = { + 'name': line.product.template.name, + 'quantity': line.quantity, + 'amount': line.unit_price + } + total_payments.append(line.unit_price) + if numbers: + min_number = min(numbers) + max_number = max(numbers) + + else: + min_number = '' + max_number = '' + print(categories.values()) + report_context['date'] = data['sale_date'] + report_context['company'] = company.party + report_context['shop'] = Shop(data['shop']).name + report_context['start_number'] = min_number + report_context['end_number'] = max_number + report_context['categories'] = categories.values() + report_context['sum_count_invoices'] = len(numbers) + report_context['sum_total_amount'] = sum(total_amount) + report_context['payments'] = _payments.values() + report_context['total_payments'] = sum(total_payments) + return report_context diff --git a/shop.xml b/shop.xml index 6b83d0b..b5a7740 100644 --- a/shop.xml +++ b/shop.xml @@ -29,5 +29,26 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig + + + Shop Daily Category + + sale_pos.shop_daily_category_report + sale_pos/shop_daily_category.fodt + pdf + False + + + sale_pos.shop_daily_category.start + form + shop_daily_category_start_form + + + Shop Daily Category + sale_pos.shop_daily_category + + + diff --git a/shop_daily_category.fodt b/shop_daily_category.fodt new file mode 100644 index 0000000..cc6f6d2 --- /dev/null +++ b/shop_daily_category.fodt @@ -0,0 +1,504 @@ + + + + 2023-04-20T10:17:41.990552036LibreOffice/7.3.7.2$Linux_X86_64 LibreOffice_project/30$Build-22023-04-20T14:28:15.033428239PT3H58M33S28 + + + 0 + 0 + 15803 + 8438 + true + false + + + view2 + 2501 + 2829 + 0 + 0 + 15801 + 8437 + 0 + 1 + false + 180 + false + false + false + + + + + false + false + false + true + true + true + true + true + false + 0 + false + false + false + true + false + false + true + false + false + false + false + true + true + true + false + false + false + false + false + false + false + true + false + false + true + false + false + false + true + 0 + 1 + true + false + + high-resolution + true + + + false + false + true + false + true + true + false + true + + true + 2080442 + + true + false + true + true + 0 + + false + false + false + true + false + true + false + false + false + false + true + false + false + + false + false + true + false + false + false + false + false + false + false + false + false + 1988023 + false + false + false + false + false + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ + + + + + - + $ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <company.rec_name> + + LISTADO PRODUCTOS VENDIDOS POR ARQUEO DEL <date> + + + + + + + + <for each="category in categories"> + + + + + + + + + + + + + + + + <category.name> + + + + + + + + Producto + + + Cantidad + + + Valor + + + + + + <for each="product in category['products'].values()"> + + + + + + + + <product['name']> + + + <product['quantity']> + + + <product['amount']> + + + + + + </for> + + + + + + + + + + + + + + + + + + Total por categoria: + + + <sum(product['amount'] for product in category['products'].values())> + + + + + </for> + + + + + + + + + + + + + + + + + + + + Total + + + <total_payments> + + + + + + + \ No newline at end of file diff --git a/view/shop_daily_category_start_form.xml b/view/shop_daily_category_start_form.xml new file mode 100644 index 0000000..a60a7e2 --- /dev/null +++ b/view/shop_daily_category_start_form.xml @@ -0,0 +1,13 @@ + + +
+