diff --git a/bom_import/__init__.py b/bom_import/__init__.py new file mode 100644 index 00000000..40272379 --- /dev/null +++ b/bom_import/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/bom_import/__manifest__.py b/bom_import/__manifest__.py new file mode 100644 index 00000000..2d37f526 --- /dev/null +++ b/bom_import/__manifest__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# © 2018 Trustcode +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +{ # pylint: disable=C8101,C8103 + 'name': "Importação de BoM", + + 'summary': """ + Permite a importação de BoM através de arquivos '.csv'.""", + + 'description': """""", + 'author': "Trustcode", + 'website': "http://www.trustcode.com.br", + 'category': 'Purchase', + 'version': '11.0.1.0.0', + 'license': 'AGPL-3', + 'contributors': [ + 'Johny Chen Jy ', + ], + 'depends': [ + 'mrp' + ], + 'data': [ + 'wizard/bom_import_wizard.xml', + ], +} diff --git a/bom_import/wizard/__init__.py b/bom_import/wizard/__init__.py new file mode 100644 index 00000000..b51845b4 --- /dev/null +++ b/bom_import/wizard/__init__.py @@ -0,0 +1 @@ +from . import bom_import_wizard diff --git a/bom_import/wizard/bom_import_wizard.py b/bom_import/wizard/bom_import_wizard.py new file mode 100644 index 00000000..7f43a6e5 --- /dev/null +++ b/bom_import/wizard/bom_import_wizard.py @@ -0,0 +1,70 @@ +import base64 +import tempfile +import csv +from odoo import models, fields, api, _ +from odoo.exceptions import UserError +import logging + +_logger = logging.getLogger(__name__) + + +class BomImportWizard(models.TransientModel): + _name = "bom.import.wizard" + + csv_file = fields.Binary(string="Arquivo CSV") + csv_delimiter = fields.Char( + string='Delimitador', size=3, required=True) + + has_quote_char = fields.Boolean(string=u'Possui caracter de citação?') + ncm_quote_char = fields.Char(string=u'Caracter de Citação', size=3) + + @api.multi + def action_import(self): + if not self.csv_file: + raise UserError(_('No file attached/selected!')) + + csv_file = base64.decodestring(self.csv_file) + + temp = tempfile.NamedTemporaryFile(delete=False) + temp.write(csv_file) + temp.close() + with open(temp.name, 'r') as csvfile: + if not self.has_quote_char: + ncm_lines = csv.DictReader( + csvfile, delimiter=str(self.csv_delimiter)) + else: + if not self.ncm_quote_char: + raise UserError(_(u'Se o campo indicador de caracter de \ +citação estiver marcado é necessário informá-lo!')) + ncm_lines = csv.DictReader( + csvfile, delimiter=str(self.csv_delimiter), + quotechar=self.ncm_quote_char) + for line in ncm_lines: + code = line['codigo'] + ncm_tax = { + 'federal_nacional': float(line['nacionalfederal']), + 'federal_importado': float(line['importadosfederal']), + 'estadual_imposto': float(line['estadual']), + 'municipal_imposto': float(line['municipal']), } + if len(code.zfill(4)) == 4: + try: + code = code.zfill(4) + code = code[:2] + '.' + code[2:] + service = self.env['br_account.service.type'].search( + [('code', '=', code)]) + service.update(ncm_tax) + except Exception as e: + _logger.error(e.message, exc_info=True) + elif len(code.zfill(8)) == 8: + code = code.zfill(8) + code = code[:4] + '.' + code[4:6] + '.' + code[6:] + try: + service = self.env['product.fiscal.classification'].\ + search([('code', '=', code)]) + service.update(ncm_tax) + except Exception as e: + _logger.error(e.message, exc_info=True) + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } diff --git a/bom_import/wizard/bom_import_wizard.xml b/bom_import/wizard/bom_import_wizard.xml new file mode 100644 index 00000000..1fbee79e --- /dev/null +++ b/bom_import/wizard/bom_import_wizard.xml @@ -0,0 +1,35 @@ + + + + + BoM Import Wizard + bom.import.wizard + +
+

+ Testing all the available potatos. +

+ + + + +
+
+
+
+
+ + + BoM Import Wizard + bom.import.wizard + form + form + new + + + + +
\ No newline at end of file diff --git a/multicompany_purchase_requisition/__manifest__.py b/multicompany_purchase_requisition/__manifest__.py index 9e2b1bd6..6c2b3458 100644 --- a/multicompany_purchase_requisition/__manifest__.py +++ b/multicompany_purchase_requisition/__manifest__.py @@ -26,6 +26,7 @@ "security/ir.model.access.csv", "wizard/wizard_multicompany_increment.xml", "views/purchase_multicompany_req.xml", - "views/purchase_order.xml" + "views/purchase_order.xml", + "reports/report_romaneio.xml", ], } diff --git a/multicompany_purchase_requisition/i18n/pt_BR.po b/multicompany_purchase_requisition/i18n/pt_BR.po index ba9a19bb..e36a0a0c 100644 --- a/multicompany_purchase_requisition/i18n/pt_BR.po +++ b/multicompany_purchase_requisition/i18n/pt_BR.po @@ -67,7 +67,7 @@ msgstr "Cancelar" #: model:ir.ui.view,arch_db:multicompany_purchase_requisition.view_purchase_multicompany_req_form #: model:ir.ui.view,arch_db:multicompany_purchase_requisition.view_purchase_requisition_form msgid "Cancel Call" -msgstr "Cancelar ligação" +msgstr "Cancelar Chamado" #. module: multicompany_purchase_requisition #: selection:purchase.multicompany,state:0 @@ -209,8 +209,8 @@ msgstr "Incremento" #. module: multicompany_purchase_requisition #: code:addons/multicompany_purchase_requisition/models/purchase_multicompany.py:90 #, python-format -msgid "It's not possible to assemble non confirmed purchase requisitions. Please, confirm those purchases or assemble the non confirmed purchases later." -msgstr "Não é possivel juntar requisições de compra que ainda não foram confirmadas. Por favor, confirme essas compras ou junte as requisições não confirmadas depois." +msgid "It's not possible to assemble purchase requisitions which are not in 'confirmed' state. Please, verify the purchase's state and try again later." +msgstr "Não é possivel juntar requisições de compra que não estão na situação de 'Confirmado'. Por favor, verifique a situação dessas compras e depois tente novamente." #. module: multicompany_purchase_requisition #: model:ir.model.fields,field_description:multicompany_purchase_requisition.field_purchase_multicompany___last_update diff --git a/multicompany_purchase_requisition/models/purchase_multicompany.py b/multicompany_purchase_requisition/models/purchase_multicompany.py index d5e6a582..e2751da4 100644 --- a/multicompany_purchase_requisition/models/purchase_multicompany.py +++ b/multicompany_purchase_requisition/models/purchase_multicompany.py @@ -76,6 +76,14 @@ def action_negociation(self): @api.multi def assemble_selected(self): + + if not all(item.state == 'in_progress' for item in self): + raise UserError( + _(u"It's not possible to assemble purchase requisitions \ +which are not in 'confirmed' state. Please, verify the purchase's state \ +and try again later." + )) + vals = { 'name': 'PMR %s' % (self.ids), 'description': 'Created from purchase.multicompany ID: %s' @@ -85,12 +93,7 @@ def assemble_selected(self): } centralizador_id = self.env[ 'purchase.multicompany.req'].create(vals) - if not all(item.state == 'in_progress' for item in self): - raise UserError( - _(u"It's not possible to assemble non confirmed purchase \ -requisitions. Please, confirm those purchases or assemble the non \ -confirmed purchases later." - )) + for item in self: item.centralizador_id = centralizador_id.id centralizador_id.assemble_selected(list(self)) @@ -118,6 +121,8 @@ class PurchaseMulticompanyLine(models.Model): default=lambda self: self.env['res.company']._company_default_get( 'purchase.multicompany.line')) + pm_req_line_id = fields.Many2one('purchase.multicompany.req.line') + @api.onchange('product_id') def _onchange_product_id(self): if self.product_id: diff --git a/multicompany_purchase_requisition/models/purchase_multicompany_req.py b/multicompany_purchase_requisition/models/purchase_multicompany_req.py index 2f670b20..f2d81be4 100644 --- a/multicompany_purchase_requisition/models/purchase_multicompany_req.py +++ b/multicompany_purchase_requisition/models/purchase_multicompany_req.py @@ -83,7 +83,7 @@ def _create_purchase_mult_req_lines(self, lines): def action_in_negociation(self): """Separa as linhas de acordo com o campo 'purchase_requisition' - e vendedor""" + e fornecedor""" if not all(obj.line_ids for obj in self): raise UserError( @@ -106,22 +106,15 @@ def action_in_negociation(self): if seller_id not in rfq: rfq[seller_id] = {} - if product_id not in rfq[seller_id]: - rfq[seller_id][product_id] = total_qty - - else: - rfq[seller_id][product_id] += total_qty + rfq[seller_id][line.id] = [product_id, total_qty] elif line.product_id.purchase_requisition == 'tenders': if seller_id not in tenders: tenders[seller_id] = {} - if product_id not in tenders[seller_id]: - tenders[seller_id][product_id] = total_qty + tenders[seller_id][line.id] = [product_id, total_qty] - else: - tenders[seller_id][product_id] += total_qty self._create_purchase_orders(rfq) self._create_purchase_requisition(tenders) self.write({ @@ -135,11 +128,11 @@ def _create_purchase_requisition(self, tender_dict): req_ids = [] for vendor_id, lines in tender_dict.items(): - for product_id, quantity in lines.items(): + for req_line, product_data in lines.items(): line_vals = { - 'product_id': product_id.id, - 'product_qty': quantity, - 'price_unit': product_id.seller_ids[0].price, + 'product_id': product_data[0].id, + 'product_qty': product_data[1], + 'price_unit': product_data[0].seller_ids[0].price, } pr_lines.append(self.env[ 'purchase.requisition.line'].create(line_vals).id) @@ -167,18 +160,23 @@ def _create_purchase_orders(self, rfq_dict, req_ids=False): } po_id = self.env['purchase.order'].create(vals) - for product_id, quantity in lines.items(): + for req_line_id, product_data in lines.items(): line_vals = { - 'product_id': product_id.id, - 'name': product_id.name, + 'product_id': product_data[0].id, + 'name': product_data[0].name, 'date_planned': datetime.now(), - 'product_uom': product_id.uom_id.id, - 'product_qty': quantity, - 'prod_original_qty': quantity, - 'price_unit': product_id.seller_ids[0].price, + 'product_uom': product_data[0].uom_id.id, + 'product_qty': product_data[1], + 'prod_original_qty': product_data[1], + 'price_unit': product_data[0].seller_ids[0].price, 'order_id': po_id.id, + 'req_line_id': req_line_id, } - self.env['purchase.order.line'].create(line_vals) + po_line_id = self.env['purchase.order.line'].create(line_vals) + + self.env['purchase.multicompany.req.line'].browse( + req_line_id).write({'po_line_id': po_line_id.id}) + self.write({'purchase_order_ids': [(4, po_id.id, 0)]}) @api.multi @@ -238,18 +236,22 @@ class PurchaseMulticompanyReqLine(models.Model): qty_increment = fields.Float( string='Increment', digits=dp.get_precision( 'Product Unit of Measure')) - requisition_line_ids = fields.Many2many( - 'purchase.multicompany.line', string='Purchase Company', - ondelete='cascade') + company_id = fields.Many2one( 'res.company', string='Company', store=True, readonly=True, default=lambda self: self.env['res.company']._company_default_get( 'purchase.multicompany.line')) + purchase_multicompany_req_id = fields.Many2one( 'purchase.multicompany.req', string="Purchase Multicompany Requisition") + requisition_line_ids = fields.Many2many( + 'purchase.multicompany.line', string='Purchase Company', + ondelete='cascade') + po_line_id = fields.Many2one('purchase.order.line') + state = fields.Selection( related="purchase_multicompany_req_id.state") diff --git a/multicompany_purchase_requisition/models/purchase_order.py b/multicompany_purchase_requisition/models/purchase_order.py index 2e29fbe2..e4653656 100644 --- a/multicompany_purchase_requisition/models/purchase_order.py +++ b/multicompany_purchase_requisition/models/purchase_order.py @@ -9,6 +9,22 @@ class PurchaseOrder(models.Model): 'purchase.multicompany.req', string="Centralizador" ) + def _get_pm_ids(self): + + pm_list = set() + for line in self.order_line: + for pm_line in line.req_line_id.requisition_line_ids: + pm_list = pm_list.union(pm_line.requisition_id) + return pm_list + + def _get_related_pm_line(self, line, pm_id): + + for pm_line in line.req_line_id.requisition_line_ids: + if pm_line.requisition_id.id == pm_id: + return pm_line + + return False + class PurchaseOrderLine(models.Model): _inherit = "purchase.order.line" @@ -20,3 +36,5 @@ class PurchaseOrderLine(models.Model): qty_increment = fields.Float( string='Qty Increment', digits=dp.get_precision( 'Product Unit of Measure')) + + req_line_id = fields.Many2one('purchase.multicompany.req.line') diff --git a/multicompany_purchase_requisition/reports/report_romaneio.xml b/multicompany_purchase_requisition/reports/report_romaneio.xml new file mode 100644 index 00000000..90727445 --- /dev/null +++ b/multicompany_purchase_requisition/reports/report_romaneio.xml @@ -0,0 +1,132 @@ + + + + + + + + + \ No newline at end of file