diff --git a/.gitignore b/.gitignore index f47da3a..11335b7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,8 @@ __pycache__/ *.py[cod] *$py.class *.py~ - +*.xml~ +*~ # C extensions *.so diff --git a/network_partner/__init__.py b/network_partner/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/network_partner/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/network_partner/__manifest__.py b/network_partner/__manifest__.py new file mode 100644 index 0000000..208c8d6 --- /dev/null +++ b/network_partner/__manifest__.py @@ -0,0 +1,35 @@ +{ + 'name': "Network Partner", + 'summary': "Makes networks based in nodes of Partners.", + 'description': """ +Network partners +================================================== +Introduce el concepto de "nodo" y "red" en contactos asociados. + +No proporciona funcionalidad por sí mismo, se usará luego en otros módulos. + +- Modelo network +- Modelo nodo +- Añade campos node_id, is_node a res.partner +- Reglas de seguridad y access lists + """, + 'author': 'Criptomart', + 'website': "https://criptomart.net", + 'category': 'Contacts', + 'version': '12.0.1.0', + 'license': 'AGPL-3', + 'depends': ['base'], + 'data': [ + 'views/res_partner_views.xml', + 'views/partner_node_views.xml', + 'views/partner_net_views.xml', + 'security/network_partner_security.xml', + 'security/ir.model.access.csv', + 'views/actions.xml', + 'views/menus.xml', + ], + 'demo': [], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/network_partner/models/__init__.py b/network_partner/models/__init__.py new file mode 100644 index 0000000..956489d --- /dev/null +++ b/network_partner/models/__init__.py @@ -0,0 +1,4 @@ +from . import res_partner +from . import partner_node +from . import partner_network + diff --git a/network_partner/models/partner_network.py b/network_partner/models/partner_network.py new file mode 100644 index 0000000..7e03a9f --- /dev/null +++ b/network_partner/models/partner_network.py @@ -0,0 +1,19 @@ +#import logging + +from odoo import models, fields, api + +#_logger = logging.getLogger(__name__) + + +class PartnerNetwork(models.Model): + _name = 'partner.network' + #_inherit = 'mail.thread' + _description = 'A network of nodes.' + + name = fields.Char(string="Nombre", help="El nombre de la red.") + #Fields + #network_partner_id = fields.Many2one('res.partner', required=True, ondelete='restrict') + #'groups_id': fields.many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', 'Groups'), + #member_id = fields.Many2many('res.partner', 'res_partner_network_rel', 'uid', 'nid', "Partners" ) + + diff --git a/network_partner/models/partner_node.py b/network_partner/models/partner_node.py new file mode 100644 index 0000000..fd52655 --- /dev/null +++ b/network_partner/models/partner_node.py @@ -0,0 +1,79 @@ +#import logging + +from odoo import models, fields, api + + +#_logger = logging.getLogger(__name__) + + +class PartnerNode(models.Model): + _name = 'partner.node' + _inherit = 'res.partner' + _description = 'A node of partners in a network' + + network_id = fields.Many2one('network.partner', string="Red", help="La red a la que pertenece el nodo.") + partner_ids = fields.One2many('res.partner', 'node_id', string='Contactos del nodo', help='Los contactos asociados a éste nodo.') + + """ + name = fields.Char(related='partner_id.name', string='Node Name', required=True, store=True, readonly=False) + partner_id = fields.Many2one('res.partner', + string="Contacto asociado", + help="El contacto asociado del nodo con sus datos como la dirección", + required=True + ) + #street = fields.Char(compute='_compute_address', inverse='_inverse_street') + #street2 = fields.Char(compute='_compute_address', inverse='_inverse_street2') + #zip = fields.Char(compute='_compute_address', inverse='_inverse_zip') + #city = fields.Char(compute='_compute_address', inverse='_inverse_city') + #state_id = fields.Many2one('res.country.state', compute='_compute_address', inverse='_inverse_state', string="Fed. State") + #country_id = fields.Many2one('res.country', compute='_compute_address', inverse='_inverse_country', string="Country") + street = fields.Char(related='partner_id.street', store=True, readonly=False) + street2 = fields.Char(related='partner_id.street2', store=True, readonly=False) + zip = fields.Char(related='partner_id.zip', store=True, readonly=False) + city = fields.Char(related='partner_id.city', store=True, readonly=False) + #state_id = fields.Char(related='partner_id.state_id', store=True, readonly=False) + #country_id = fields.Char(related='partner_id.country_id', store=True, readonly=False) + email = fields.Char(related='partner_id.email', store=True, readonly=False) + phone = fields.Char(related='partner_id.phone', store=True, readonly=False) + + def _get_company_address_fields(self, partner): + return { + 'street' : partner.street, + 'street2' : partner.street2, + 'city' : partner.city, + 'zip' : partner.zip, + 'state_id' : partner.state_id, + 'country_id' : partner.country_id, + } + + def _compute_address(self): + for node in self.filtered(lambda node: node.partner_id): + address_data = node.partner_id.sudo().address_get(adr_pref=['contact']) + if address_data['contact']: + partner = node.partner_id.browse(address_data['contact']).sudo() + node.update(node._get_company_address_fields(partner)) + + def _inverse_street(self): + for company in self: + company.partner_id.street = company.street + + def _inverse_street2(self): + for company in self: + company.partner_id.street2 = company.street2 + + def _inverse_zip(self): + for company in self: + company.partner_id.zip = company.zip + + def _inverse_city(self): + for company in self: + company.partner_id.city = company.city + + def _inverse_state(self): + for company in self: + company.partner_id.state_id = company.state_id + + def _inverse_country(self): + for company in self: + company.partner_id.country_id = company.country_id + """ diff --git a/network_partner/models/res_partner.py b/network_partner/models/res_partner.py new file mode 100644 index 0000000..c34f67c --- /dev/null +++ b/network_partner/models/res_partner.py @@ -0,0 +1,14 @@ +#import logging + +from odoo import models, fields, api + + +#_logger = logging.getLogger(__name__) + + +class ResPartner(models.Model): + _inherit = 'res.partner' + #'users': fields.many2many('res.users', 'res_groups_users_rel', 'gid', 'uid', 'Users'), + node_id = fields.Many2one('partner.node', string="Nodo") + is_node = fields.Boolean(string="Es un nodo", help="Éste partner representa un nodo en una red.") + diff --git a/network_partner/security/ir.model.access.csv b/network_partner/security/ir.model.access.csv new file mode 100644 index 0000000..43ee717 --- /dev/null +++ b/network_partner/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_network_partner_node_group_user,network.partner.node.user,network_partner.model_partner_node,network_partner.group_np_user,1,0,0,0 +access_network_partner_node_group_manager,network.partner.node.manager,network_partner.model_partner_node,network_partner.group_np_manager,1,1,1,1 +access_network_partner_net_group_user,network.partner.net.user,network_partner.model_partner_network,network_partner.group_np_user,1,0,0,0 +access_network_partner_net_group_manager,network.partner.net.manager,network_partner.model_partner_network,network_partner.group_np_manager,1,1,1,1 diff --git a/network_partner/security/network_partner_security.xml b/network_partner/security/network_partner_security.xml new file mode 100644 index 0000000..ee1ebad --- /dev/null +++ b/network_partner/security/network_partner_security.xml @@ -0,0 +1,79 @@ + + + + + + Network Partner module access + User access level for this module + 3 + + + + User + + + + + + Manager + + + + + + + + + + + + + network.partner.node.read.rule + + + [(1, '=', 1)] + + + + + + + + + network.partner.node.write.rule + + + [(1, '=', 1)] + + + + + + + + + network.partner.net.read.rule + + + [(1, '=', 1)] + + + + + + + + + network.partner.net.write.rule + + + [(1, '=', 1)] + + + + + + + + + diff --git a/network_partner/views/actions.xml b/network_partner/views/actions.xml new file mode 100644 index 0000000..5ccf0b5 --- /dev/null +++ b/network_partner/views/actions.xml @@ -0,0 +1,40 @@ + + + + + Networks + ir.actions.act_window + partner.network + form + tree,form + { } + +

+ Click to create a new Partner Network. +

+
+
+ + + Nodes + ir.actions.act_window + partner.node + form + tree,form + { } + +

+ Click to create a new Node. +

+
+
+ + + + tree + + + + +
+
diff --git a/network_partner/views/menus.xml b/network_partner/views/menus.xml new file mode 100644 index 0000000..20f1e49 --- /dev/null +++ b/network_partner/views/menus.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + diff --git a/network_partner/views/partner_net_views.xml b/network_partner/views/partner_net_views.xml new file mode 100644 index 0000000..fa10458 --- /dev/null +++ b/network_partner/views/partner_net_views.xml @@ -0,0 +1,29 @@ + + + + + partner.network.nets.form + partner.network + + +
+ + + +
+
+
+ + + partner.network.nets.tree + partner.network + + + + + + + + +
+
diff --git a/network_partner/views/partner_node_views.xml b/network_partner/views/partner_node_views.xml new file mode 100644 index 0000000..d1291a8 --- /dev/null +++ b/network_partner/views/partner_node_views.xml @@ -0,0 +1,40 @@ + + + + + + partner.network.node.form + partner.node + 20 + +
+
+

Soy el header...

+
+ + + + + + + +
+
+
+ + + partner.network.node.tree + partner.node + 10 + + + + + + + + + +
+
+ diff --git a/network_partner/views/res_partner_views.xml b/network_partner/views/res_partner_views.xml new file mode 100644 index 0000000..2199a24 --- /dev/null +++ b/network_partner/views/res_partner_views.xml @@ -0,0 +1,24 @@ + + + + + + Nodo + res.partner + + 2 + + + + + + + + + + + + + + diff --git a/network_partner/workflow.txt b/network_partner/workflow.txt new file mode 100644 index 0000000..59d6608 --- /dev/null +++ b/network_partner/workflow.txt @@ -0,0 +1,34 @@ +Order: + +The status of the purchase order or the quotation request. " + +A request for quotation is a purchase order in a 'Draft' status. + +Then the order has to be confirmed by the user responsible , the status switch to 'Confirmed'. + +Then the supplier must confirm the order to change the status to 'Approved'. + +When the purchase order is paid and received, the status becomes 'Done'. + +If a cancel action occurs in the invoice or in the receipt of goods, the status becomes "in exception." + + STATE_SELECTION = [ + ('draft', 'Draft PO'), + ('sent', 'RFQ'), + ('bid', 'Bid Received'), + ('confirmed', 'Waiting Approval'), + ('approved', 'Purchase Confirmed'), + ('except_picking', 'Shipping Exception'), + ('except_invoice', 'Invoice Exception'), + ('done', 'Done'), + ('cancel', 'Cancelled') + +Order.Line: + +'state': fields.selection([('draft', 'Draft'), ('confirmed', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], + 'Status', required=True, readonly=True, copy=False, + help=' * The \'Draft\' status is set automatically when purchase order in draft status. \ + \n* The \'Confirmed\' status is set automatically as confirm when purchase order in confirm status. \ + \n* The \'Done\' status is set automatically when purchase order is set as done. \ + \n* The \'Cancelled\' status is set automatically when user cancel purchase order.'), +