diff --git a/activity_validation/__manifest__.py b/activity_validation/__manifest__.py index 80a01611..a1b11913 100644 --- a/activity_validation/__manifest__.py +++ b/activity_validation/__manifest__.py @@ -19,7 +19,7 @@ ############################################################################## { "name": "Activity Validation", - "version": "16.0.1", + "version": "16.0.2", "author": "OmniaSolutions", "website": "https://github.com/OmniaGit/odooplm", "category": "Custom", diff --git a/activity_validation/models/product_product.py b/activity_validation/models/product_product.py index 39ce336e..910a5fc5 100755 --- a/activity_validation/models/product_product.py +++ b/activity_validation/models/product_product.py @@ -56,7 +56,8 @@ def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None def get_user_activities(self, ids_to_read=[]): activity = self.env['mail.activity'] act_filter = [ - ('activity_type_id', '=', self.env.ref('plm.mail_activity_plm_activity').id), + ('activity_type_id', 'in', [self.env.ref('plm.mail_activity_plm_activity').id, + self.env.ref('plm.mail_activity_check_out_request').id]), ('user_id', '=', self.env.uid), ('plm_state', 'not in', [False, 'done', 'cancel']) ] diff --git a/plm/__manifest__.py b/plm/__manifest__.py index 1a078dd1..c11a2c28 100644 --- a/plm/__manifest__.py +++ b/plm/__manifest__.py @@ -20,7 +20,7 @@ ############################################################################## { "name": "Product Lifecycle Management", - "version": "16.0.21", + "version": "16.0.22", "author": "OmniaSolutions", "website": "https://odooplm.omniasolutions.website", "category": "Manufacturing/Product Lifecycle Management (PLM)", @@ -31,6 +31,8 @@ "images": ["static/img/odoo_plm.png"], "depends": ["base", "board", "product", "mrp"], "data": [ + # data + "data/data.xml", # security "security/base_plm_security.xml", # views diff --git a/plm/data/data.xml b/plm/data/data.xml new file mode 100644 index 00000000..97dab052 --- /dev/null +++ b/plm/data/data.xml @@ -0,0 +1,14 @@ + + + + + Check-Out Request + fa-mail-reply + 3 + ir.attachment + 200 + request + + + + diff --git a/plm/models/ir_attachment.py b/plm/models/ir_attachment.py index f1225339..82ac9176 100755 --- a/plm/models/ir_attachment.py +++ b/plm/models/ir_attachment.py @@ -106,6 +106,19 @@ class IrAttachment(models.Model): default=False) library_path = fields.Char("File library path") + must_update_from_cad = fields.Boolean("Must Update form CAD", + compute="_compute_must_update_from_cad", + help="""When this flag is enabled the 2d document must be updated in order to guaranteey the update betwin 2d and 3d document""") + + def _compute_must_update_from_cad(self): + ir_attachment_relation = self.env['ir.attachment.relation'] + for ir_attachment in self: + ir_attachment.must_update_from_cad=False + if ir_attachment.document_type =='2d': + ir_attachment.must_update_from_cad=ir_attachment_relation.is_2d_ok(ir_attachment) + if ir_attachment.document_type =='pr': + ir_attachment.must_update_from_cad=ir_attachment_relation.is_pr_ok(ir_attachment) + def _getPrintoutName(self): for ir_attachment_id in self: ir_attachment_id.printout_name=f"{ir_attachment_id.engineering_code}_{ir_attachment_id.engineering_revision}.pdf" @@ -967,7 +980,7 @@ def _check_unique_document(self, vals): if self.env.context.get('odooPLM'): if 'name' in vals and 'engineering_code' in vals: if self.search_count([('engineering_code','=', vals['engineering_code']), - ('name','!=',vals['name'])]): + ('name','not ilike',vals['name'])]): raise Exception(_(f"You are trying to create a new attachment [{vals['name']}] with the some engineering code [{vals['engineering_code']}]")) @api.model_create_multi @@ -1603,7 +1616,15 @@ def getCheckedOut(self, oid, default=None): self.getUserSign(checkOutBrws.userid.id), checkOutBrws.hostname) return ('', False, '', '') - + + def _getCheckOutUser(self): + for ir_attachment_id in self: + checkoutType = self.env['plm.checkout'] + checkoutBrwsList = checkoutType.search([('documentid', '=', ir_attachment_id.id)]) + for checkOutBrws in checkoutBrwsList: + return checkOutBrws.userid + return self.env['res.users'] + @api.model def _file_delete(self, fname): """ @@ -1940,9 +1961,28 @@ def checkout(self, hostName, hostPws, showError=True, user_id=False): break return plm_checkout_id, msg + @api.model + def clientCanCheckOut(self, doc_attrs): + for attachment_id in self.getDocumentBrws(doc_attrs): + return attachment_id.canCheckOut1() + return False, 'not_found', f'File Not found from attributes {doc_attrs}' - def canCheckOut(self, showError=False): + def canCheckOut1(self): for docBrws in self: + if docBrws.isCheckedOutByMe(): + msg = _(f"Unable to check-Out a document that is already checked Out By {docBrws.checkout_user}") + return docBrws.id, 'check_out_by_me', msg + if docBrws.is_checkout: + msg = _(f"Unable to check-Out a document that is already checked IN by user {docBrws.checkout_user}") + return docBrws.id, 'check_out_by_user', msg + if docBrws.engineering_state not in [START_STATUS, False]: + msg = _(f"Unable to check-Out a document that is in state {docBrws.engineering_state}") + return docBrws.id, 'check_out_released', msg + return docBrws.id, 'check_in', '' + raise Exception() + + def canCheckOut(self, showError=False): + for docBrws in self: if docBrws.is_checkout: msg = _("Unable to check-Out a document that is already checked IN by user %r" % docBrws.checkout_user) if showError: @@ -2029,14 +2069,34 @@ def cleanDocumentRelations(self): for docBrws in self: for linkedBrws in linkedDocEnv.search([('child_id', '=', docBrws.id), ('parent_id', '=', docBrws.id)]): linkedBrws.unlink() + + @api.model + def getIdFromAttrs(self, attrs): + for ir_attachment in self.getDocumentBrws(json.loads(attrs)): + return ir_attachment.id + return False def getDocumentBrws(self, docVals): - docName = docVals.get('engineering_code', '') - docRev = docVals.get('engineering_revision', None) - if not docName or docRev is None: - return self.browse() - return self.search([('engineering_code', '=', docName), - ('engineering_revision', '=', docRev)]) + """ + function to convert dict client info into attachment browse record + :docVals could be dictionaty or list of dictionaty + es1. {'engineering_code': '102030', 'engineering_revision': 0} + es2. [{'engineering_code': '102030', 'engineering_revision': 0},{ },..] + :return: browse_record(ir_attachment) + """ + if not isinstance(docVals, list): + docVals=[docVals] + out = self.env[self._name] + for doc_dict in docVals: + docName = doc_dict.get('engineering_code', '') + docRev = doc_dict.get('engineering_revision', None) + if not docName or docRev is None: + continue + for ir_attachment_id in self.search([('engineering_code', '=', docName), + ('engineering_revision', '=', docRev)]): + out+=ir_attachment_id + break + return out def checkStructureDocument(self, docAttrs): docName = docAttrs.get('engineering_code', '') @@ -2616,6 +2676,7 @@ def getDefaulValueDict(self, docBrws, PLM_DT_DELTA, is_root): tmp_dict['is_latest_rev'] = docBrws.isLatestRevision() tmp_dict['PLM_DT_DELTA'] = PLM_DT_DELTA tmp_dict['is_root'] = is_root + tmp_dict['must_update_from_cad'] = docBrws.must_update_from_cad tmp_dict['msg'] = '' return tmp_dict @@ -2666,7 +2727,7 @@ def _preCheckInRecursive_all(self, doc_2d_ids=self.env[self._name] doc_3d_ids=self.env[self._name] # - for doc_id in self.browse(list(set(self.getRelatedLyTree(root_id.id)+self.getRelatedPrTree(root_id.id,recursion=True)))): + for doc_id in self.browse(list(set(self.getRelatedLyTree(root_id.id) + self.getRelatedPrTree(root_id.id,recursion=True)))): if doc_id.is3D(): doc_3d_ids+=doc_id else: @@ -2700,7 +2761,6 @@ def _preCheckInRecursive_all(self, out['to_check_3d'].append(data_info) else: out['info'].append(data_info) - return out @api.model @@ -3050,4 +3110,39 @@ def getDocBom(self, 'children': children_list} break return vals + + @api.model + def sent_check_out_requests(self, document_id): + """ + create an activity on document asking to check-out the document + """ + for ir_attachment_id in self.browse([document_id]): + _id, action, _message = ir_attachment_id.canCheckOut1() + if action=='check_out_by_user': + res_user_id = ir_attachment_id._getCheckOutUser() + message = _(f"User {self.env.user.display_name} request this document for make some modification") + todos = {'res_id': ir_attachment_id.id, + 'res_model_id': self.env['ir.model'].search([('model', '=', self._name)]).id, + 'user_id': res_user_id.id, + 'summary': _("Check-In request"), + 'note': message, + 'activity_type_id': self.env.ref("plm.mail_activity_check_out_request").id, + 'date_deadline': datetime.today().date(), + } + self.env['mail.activity'].create(todos) + return True + + def related_not_update(self): + for attachment_id in self: + relation_ids = self.env['ir.attachment.relation'].search(["|",('parent_id','=',attachment_id.id), + ('child_id','=',attachment_id.id), + ('link_kind', '=', 'LyTree')]) + return {'name': _('Attachment Relations.'), + 'res_model': 'ir.attachment.relation', + 'view_type': 'form', + 'view_mode': 'kanban,tree,form', + 'type': 'ir.actions.act_window', + 'domain': [('id', 'in', relation_ids.ids)], + 'context': {}} + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/plm/models/ir_attachment_relations.py b/plm/models/ir_attachment_relations.py index a3bc784f..265d1b6d 100755 --- a/plm/models/ir_attachment_relations.py +++ b/plm/models/ir_attachment_relations.py @@ -177,4 +177,31 @@ def removeChildRelation(self, parent_ir_attachment_id, linkType='HiTree'): self.search([('parent_id', '=', parent_ir_attachment_id), ('link_kind', '=', linkType)]).unlink() + def is_2d_ok(self, from_ir_attachment_id): + for relation_id in self.search(["|",('parent_id','=',from_ir_attachment_id.id), + ('child_id','=',from_ir_attachment_id.id), + ('link_kind', '=', 'LyTree') + ]): + if relation_id.parent_id.document_type=='2d' and relation_id.child_id.document_type in ['3d','pr']: + if relation_id.parent_id.write_date < relation_id.child_id.write_date: + return False + if relation_id.child_id.document_type=='2d' and relation_id.parent_id.document_type in ['3d','pr'] : + if relation_id.child_id.write_date +
+ +
- + - + + @@ -311,8 +322,11 @@ + + + @@ -340,6 +354,10 @@ +
+ Name: - + diff --git a/plm_box/models/ir_attachment.py b/plm_box/models/ir_attachment.py index 27b8787e..44ff3e3f 100755 --- a/plm_box/models/ir_attachment.py +++ b/plm_box/models/ir_attachment.py @@ -55,14 +55,11 @@ def create(self, vals): name = self.getNewSequencedName(vals) vals['name'] = name return super(Plm_box_document, self).create(vals) - + def getCheckOutUser(self): - for docBrws in self: - checkOutObj = self.env.get('plm.checkout') - checkOutBrwsList = checkOutObj.search([('documentid', '=', docBrws.id)]) - for checkOutBrws in checkOutBrwsList: - if checkOutBrws: - return self.getUserNameFromId(checkOutBrws.write_uid) + for checkOutBrws in self._getCheckOutUser(): + if checkOutBrws: + return checkOutBrws.name return '' @api.model