From 06bc15aa09441f1b8cb8c61e0d7dcd7140cc1f1d Mon Sep 17 00:00:00 2001 From: Oscar Date: Thu, 13 Jan 2022 17:53:38 -0500 Subject: [PATCH] fix --- __init__.py | 6 +- analytic_report.ods => analytic_report.fods | Bin detailed_report.ods => detailed_report.fods | Bin purchase.xml | 50 +-- purchase_new.py | 353 ++++++++++++++++++ ...e_detailed.fods => purchases_detailed.fods | Bin tryton.cfg | 3 +- view/print_purchase_detailed_start_form.xml | 2 +- 8 files changed, 377 insertions(+), 37 deletions(-) rename analytic_report.ods => analytic_report.fods (100%) rename detailed_report.ods => detailed_report.fods (100%) create mode 100644 purchase_new.py rename purchase_detailed.fods => purchases_detailed.fods (100%) diff --git a/__init__.py b/__init__.py index da03b23..ecec6c6 100644 --- a/__init__.py +++ b/__init__.py @@ -11,13 +11,13 @@ def register(): purchase.Purchase, purchase.Line, purchase.PurchaseAnalyticStart, - purchase.PurchaseDetailedStart, + purchase.PurchasesDetailedStart, module='purchase_co', type_='model') Pool.register( - purchase.PurchaseDetailed, + purchase.PurchasesDetailed, purchase.PurchaseAnalytic, module='purchase_co', type_='wizard') Pool.register( + purchase.PurchasesDetailedReport, purchase.PurchaseAnalyticReport, - purchase.PurchaseDetailedReport, module='purchase_co', type_='report') diff --git a/analytic_report.ods b/analytic_report.fods similarity index 100% rename from analytic_report.ods rename to analytic_report.fods diff --git a/detailed_report.ods b/detailed_report.fods similarity index 100% rename from detailed_report.ods rename to detailed_report.fods diff --git a/purchase.xml b/purchase.xml index 1162318..19cd96a 100644 --- a/purchase.xml +++ b/purchase.xml @@ -18,33 +18,21 @@ this repository contains the full copyright notices and license terms. --> Purchase Analytic Report - purchase_report.analytic.report - purchase_report/analytic_report.ods + purchase_co.analytic.report + purchase_co/analytic_report.fods - purchase_report.analytic.start + purchase_co.analytic.start form report_analytic_start_form Wizard Purchase Analytic Report - purchase_report.analytic + purchase_co.analytic - - purchase.line tree @@ -84,28 +72,26 @@ this repository contains the full copyright notices and license terms. --> - - purchase.purchase_detailed.start + + purchase.purchases_detailed.start form print_purchase_detailed_start_form - - Print Purchase Detailed - purchase.purchase_detailed + + Detailed Purchases + purchase.purchases_detailed - - - Purchase Detailed - purchase.purchase - purchase.purchase_detailed.report - purchase_co/purchase_detailed.fods + + Purchases Detailed + + purchase.purchases_detailed.report + purchase_co/purchases_detailed.fods ods - True + False - - - + diff --git a/purchase_new.py b/purchase_new.py new file mode 100644 index 0000000..e023308 --- /dev/null +++ b/purchase_new.py @@ -0,0 +1,353 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. +from datetime import date, timedelta +from decimal import Decimal +from trytond.pyson import Eval +from trytond.pool import PoolMeta, Pool +from trytond.model import fields, ModelView +from trytond.exceptions import UserError +from trytond.transaction import Transaction +from trytond.report import Report +from trytond.wizard import Wizard, StateView, Button, StateReport + + +class Configuration(metaclass=PoolMeta): + __name__ = 'purchase.configuration' + reference_required = fields.Boolean('Reference Required') + all_warehouse = fields.Boolean('All Warehouse', 'See quantity in all warehouse') + + +class Purchase(metaclass=PoolMeta): + __name__ = 'purchase.purchase' + + @fields.depends('party', 'invoice_party', 'payment_term', 'lines') + def on_change_party(self): + super(Purchase, self).on_change_party() + self.invoice_method = 'shipment' + + def create_invoice(self): + invoice = super(Purchase, self).create_invoice() + if not invoice: + return + invoice.reference = self.reference + invoice.description = self.description + invoice.save() + return invoice + + @classmethod + def process(cls, purchases): + for rec in purchases: + if not rec.reference: + raise UserError('El campo referencia es obligatorio!') + super(Purchase, cls).process(purchases) + + @classmethod + def quote(cls, purchases): + pool = Pool() + Configuration = pool.get('purchase.configuration') + config = Configuration(1) + if config.reference_required: + cls.check_duplicated(purchases) + super(Purchase, cls).quote(purchases) + + @classmethod + def check_duplicated(cls, purchases): + today = date.today() + target_date = today - timedelta(days=90) + for purchase in purchases: + duplicates = cls.search_read([ + ('reference', '=', purchase.reference), + ('party', '=', purchase.party.id), + ('purchase_date', '>=', target_date), + ], fields_names=['reference']) + if len(duplicates) >= 2: + raise UserError('Al parecer esta compra esta duplicada!') + + +class Line(metaclass=PoolMeta): + __name__ = 'purchase.line' + + stock_quantity = fields.Function(fields.Float('Stock Quantity', + digits=(16, Eval('default_uom_digits', 2))), + 'on_change_with_stock_quantity') + + @fields.depends('product', 'purchase', + '_parent_purchase.warehouse') + def on_change_with_stock_quantity(self, name=None): + if self.product: + context = {'stock_date_end': date.today()} + Location = Pool().get('stock.location') + Configuration = Pool().get('purchase.configuration') + configuration = Configuration(1) + if configuration.all_warehouse: + locations = Location.search([ + ('type', '=', 'warehouse') + ]) + location_ids = [l.storage_location.id for l in locations if l.storage_location] + elif self.purchase.warehouse: + location_ids = [self.purchase.warehouse.storage_location.id] + else: + return 0 + + product_ids = [self.product.id] + quantity = 0 + with Transaction().set_context(context): + Product = Pool().get('product.product') + pbl = Product.products_by_location( + location_ids, + grouping=('product', ), + grouping_filter=(product_ids,)) + for v in pbl.values(): + quantity += v + quantity = quantity + return quantity + + +class PurchaseAnalyticStart(ModelView): + 'Purchase Analytic Report Start' + __name__ = 'purchase_co.analytic.start' + company = fields.Many2One('company.company', 'Company', required=True) + start_date = fields.Date("Start Date", required=True) + end_date = fields.Date("End Date", required=True) + + @staticmethod + def default_company(): + return Transaction().context.get('company') + + @staticmethod + def default_end_date(): + Date = Pool().get('ir.date') + return Date.today() + + +class PurchaseAnalytic(Wizard): + 'Purchase Analytic Report' + __name__ = 'purchase_co.analytic' + start = StateView('purchase_co.analytic.start', + 'purchase_co.purchase_analytic_start_view_form', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Print', 'print_', 'tryton-ok', default=True), + ]) + print_ = StateReport('purchase_co.analytic.report') + + def do_print_(self, action): + data = { + 'company': self.start.company.id, + 'start_date': self.start.start_date, + 'end_date': self.start.end_date, + } + return action, data + + def transition_print_(self): + return 'end' + + +class PurchaseAnalyticReport(Report): + __name__ = 'purchase_co.analytic.report' + + @classmethod + def compute_amount_tax(cls, line): + Tax = Pool().get('account.tax') + tax_list = Tax.compute(Tax.browse(line['taxes']), + line['unit_price'] or Decimal('0.0'), + line['quantity'] or 0.0) + return sum([t['amount'] for t in tax_list], Decimal('0.0')) + + @classmethod + def _get_rec(cls, line): + analytic_account = None + if line['analytic_accounts.']: + analytic_account = line['analytic_accounts.'][0]['account.'] + inv_unit_price = Decimal(0) + if line['invoice_lines.']: + inv_unit_price = line['invoice_lines.'][0]['unit_price'] + + value = { + 'reference': line['purchase.']['reference'], + 'purchase_date': line['purchase.']['purchase_date'], + 'state': line['purchase.']['state'], + 'shipment_state': line['purchase.']['shipment_state'], + 'invoice_state': line['purchase.']['invoice_state'], + 'id_number': line['purchase.']['party.']['id_number'], + 'name': line['purchase.']['party.']['name'], + 'warehouse': line['purchase.']['warehouse.']['name'], + 'description': line['description'], + 'unit_name': line['unit.']['name'], + 'quantity': line['quantity'], + 'unit_price': line['unit_price'], + 'analytic_account': analytic_account['code'] + ' ' + analytic_account['name'] if analytic_account else '', + 'taxes': list(line['taxes']), + 'qty_received': sum([r['quantity'] for r in line['moves.']]), + 'amount': line['amount'], + 'inv_unit_price': inv_unit_price + } + tax_amount = cls.compute_amount_tax(value) + full_amount = value['amount'] + tax_amount + value.update({ + 'tax_amount': tax_amount, + 'full_amount': full_amount, + }) + return value + + @classmethod + def get_context(cls, records, header, data): + report_context = super().get_context(records, header, data) + pool = Pool() + Company = pool.get('company.company') + PurchaseLine = pool.get('purchase.line') + fields_names = ['purchase.reference', 'purchase.purchase_date', 'purchase.party.id_number', + 'purchase.party.name', 'description', 'unit.name', 'quantity', 'unit_price', + 'purchase.state', 'purchase.shipment_state', 'purchase.invoice_state', + 'analytic_accounts.account.name', 'analytic_accounts.account.code', 'taxes', + 'invoice_lines.unit_price', 'moves.quantity', 'amount', 'purchase.warehouse.name' + ] + + lines = PurchaseLine.search_read([ + ('purchase.company', '=', data['company']), + ('purchase.purchase_date', '>=', data['start_date']), + ('purchase.purchase_date', '<=', data['end_date']), + ], fields_names=fields_names, order=[('purchase.purchase_date', 'ASC')]) + + records = [] + + records_append = records.append + get_rec = cls._get_rec + for line in lines: + records_append(get_rec(line)) + + report_context['records'] = records + report_context['company'] = Company(data['company']) + return report_context + + +class PurchasesDetailedStart(ModelView): + 'Purchases Detailed Start' + __name__ = 'purchase.purchases_detailed.start' + company = fields.Many2One('company.company', 'Company', required=True) + start_date = fields.Date('Start Date', required=True) + end_date = fields.Date('End Date', required=True) + invoiced = fields.Boolean('Invoiced', help='Print purchase invoiced') + detailed = fields.Boolean('Detailed', help='Print report detailed') + + @staticmethod + def default_company(): + return Transaction().context.get('company') + + +class PurchasesDetailed(Wizard): + 'Purchases Detailed' + __name__ = 'purchase.purchases_detailed' + start = StateView('purchase.purchases_detailed.start', + 'purchase_co.print_purchases_detailed_start_view_form', [ + Button('Cancel', 'end', 'tryton-cancel'), + Button('Print', 'print_', 'tryton-ok', default=True), + ]) + print_ = StateReport('purchase.purchases_detailed.report') + + def do_print_(self, action): + data = { + 'company': self.start.company.id, + 'start_date': self.start.start_date, + 'end_date': self.start.end_date, + 'invoiced': self.start.invoiced, + 'detailed': self.start.detailed, + } + return action, data + + def transition_print_(self): + return 'end' + + +class PurchasesDetailedReport(Report): + __name__ = 'purchase.purchases_detailed.report' + + @classmethod + def get_context(cls, records, header, data): + report_context = super().get_context(records, header, data) + pool = Pool() + Invoice = pool.get('account.invoice') + + fields_names = [ + 'number', 'description', 'party.name', 'untaxed_amount', + 'party.id_number', 'state', 'tax_amount', 'total_amount', + ] + + lines = None + + if data['invoiced']: + title = 'INFORME DE COMPRAS' + + fields_names.append('invoice_date') + Invoiceline = pool.get('account.invoice.line') + dom_invoice = [ + ('company', '=', data['company']), + ('invoice.invoice_date', '>=', data['start_date']), + ('invoice.invoice_date', '<=', data['end_date']), + ('invoice.type', '=', 'in'), + ('origin', 'ilike', 'purchase.line%'), + ] + fields_names_lines = ['id', 'invoice', 'origin.purchase.number'] + + fields = Invoiceline.fields_get(fields_names=['operation_center']) + if 'operation_center' in fields.keys(): + fields_names_lines.append('operation_center.name') + lines = Invoiceline.search_read(dom_invoice, fields_names=fields_names_lines) + + operation_centers = {} + invoices_ids = set() + invoices_ids_add = invoices_ids.add + oc_inv_update = operation_centers.update + for v in lines: + invoices_ids_add(v['invoice']) + operation_center = '' + if v['operation_center.']: + operation_center = v['operation_center.']['name'] + purchase = v['origin.']['purchase.']['number'] + oc_inv_update({v['invoice']: {'operation_center': operation_center, 'purchase': purchase}}) + + records = Invoice.search_read( + ['id', 'in', invoices_ids], fields_names=fields_names) + + else: + fields_names.append('purchase_date') + Purchase = pool.get('purchase.purchase') + Purchaseline = pool.get('purchase.line') + + title = 'INFORME DE ORDENES DE COMPRAS' + + dom_lines = [ + ('purchase.company', '=', data['company']), + ('purchase.purchase_date', '>=', data['start_date']), + ('purchase.purchase_date', '<=', data['end_date']), + ] + fields_names_lines = ['id', 'purchase'] + + fields = Purchaseline.fields_get(fields_names=['operation_center']) + if 'operation_center' in fields.keys(): + fields_names_lines.append('operation_center.name') + lines = Purchaseline.search_read(dom_lines, fields_names=fields_names_lines) + operation_centers = {} + purchase_ids = set() + purchase_ids_add = purchase_ids.add + oc_purchase_update = operation_centers.update + for v in lines: + purchase_ids_add(v['id']) + operation_center = v.get('operation_center.', '') + if operation_center: + operation_center = operation_center['name'] + oc_purchase_update({v['purchase']: operation_center}) + + dom_purchases = [ + ('company', '=', data['company']), + ('purchase_date', '>=', data['start_date']), + ('purchase_date', '<=', data['end_date']), + ] + records = Purchase.search_read(dom_purchases, fields_names=fields_names, + order=[('party.name', 'ASC'), ('purchase_date', 'ASC')] + ) + + report_context['records'] = records + report_context['data'] = data + report_context['title'] = title + report_context['operation_centers'] = operation_centers + return report_context diff --git a/purchase_detailed.fods b/purchases_detailed.fods similarity index 100% rename from purchase_detailed.fods rename to purchases_detailed.fods diff --git a/tryton.cfg b/tryton.cfg index eb8452c..bdaa082 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,7 +1,8 @@ [tryton] -version=6.0.1 +version=6.0.2 depends: product purchase + account_col xml: purchase.xml diff --git a/view/print_purchase_detailed_start_form.xml b/view/print_purchase_detailed_start_form.xml index ad57093..3068dbd 100644 --- a/view/print_purchase_detailed_start_form.xml +++ b/view/print_purchase_detailed_start_form.xml @@ -4,7 +4,7 @@ this repository contains the full copyright notices and license terms. -->