diff --git a/jikimo_workorder_exception/security/ir.model.access.csv b/jikimo_workorder_exception/security/ir.model.access.csv
index bbc066e4..660adb9c 100644
--- a/jikimo_workorder_exception/security/ir.model.access.csv
+++ b/jikimo_workorder_exception/security/ir.model.access.csv
@@ -1,2 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_jikimo_workorder_exception","access.jikimo.workorder.exception","model_jikimo_workorder_exception","mrp.group_mrp_user",1,1,1,0
+"access_jikimo_workorder_exception_group_quality","access.jikimo.workorder.exception.group_quality","model_jikimo_workorder_exception","sf_base.group_quality",1,1,1,0
+"access_jikimo_workorder_exception_group_quality_director","access.jikimo.workorder.exception.group_quality_director","model_jikimo_workorder_exception","sf_base.group_quality_director",1,1,1,0
+
diff --git a/quality_control/models/product_category.py b/quality_control/models/product_category.py
index 9b5535d4..17f26006 100644
--- a/quality_control/models/product_category.py
+++ b/quality_control/models/product_category.py
@@ -21,4 +21,12 @@ class ProductCategory(models.Model):
args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
# 调用父类的 name_search 方法
- return super(ProductCategory, self).name_search(name, args=args, operator=operator, limit=limit)
\ No newline at end of file
+ return super(ProductCategory, self).name_search(name, args=args, operator=operator, limit=limit)
+
+ @api.model
+ def search(self, args, limit=100, offset=0, order=None, count=False):
+ # 添加过滤条件,确保只返回名称不在指定列表中的记录
+ args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
+
+ # 调用父类的 search 方法
+ return super(ProductCategory, self).search(args, limit=limit, offset=offset, order=order, count=count)
\ No newline at end of file
diff --git a/sf_base/static/js/customTable.js b/sf_base/static/js/customTable.js
new file mode 100644
index 00000000..a3da6f4f
--- /dev/null
+++ b/sf_base/static/js/customTable.js
@@ -0,0 +1,125 @@
+// 获取表格数据
+function getDomData() {
+ const dom = $('div[name=cutting_speed_ids]')
+ if (!dom.length) return
+ const table = dom.find('.o_list_table')
+ const thead = table.children('thead')
+ const tbody = table.children('tbody')
+ const tbody_child = tbody.children()
+ const hideTheadDom = thead.find('[data-name=process_capability]')
+ hideTheadDom.hide().next().hide()
+ hideTheadDom.before('
精加工 | 粗加工 | ')
+ tbody_child.each(function () {
+ const dom = $(this).children('[name=process_capability]')
+ if(!dom.length) return
+ dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
+ const isCu = dom.text() == '粗加工' // 是否粗加工
+ const v = dom.next().text() // 切削速度
+ dom.after(`${!isCu ? v : ''} | ${isCu ? v : ''} | `)
+ setListenClick()
+ })
+return;
+ handleTbody(tbody, newTableData, ΦList, table)
+}
+
+// 监听点击
+function setListenClick() {
+ $(document).click(function (e) {
+ if ($(e.target).attr('customSpeed')) {
+ const orginV = $('[customInput=1]').children('input').val()
+ $('[customInput=1]').parent().html(orginV)
+ const v = $(e.target).attr('val')
+ const is = $(e.target).attr('is')
+ $(e.target).html('')
+ const input = $('')
+ input.children('input').val(v)
+ $(e.target).append(input)
+ input.children('input').focus()
+ input.children('input').select()
+ } else if ($(e.target).attr('customInput')) {
+
+ } else {
+ const orginV = $('[customInput=1]').children('input').val()
+ $('[customInput=1]').parent().html(orginV)
+ const v = $(e.target).attr('val')
+ }
+ })
+ $(document).off('change') // 防止重复绑定
+ $(document).on('change', '[customInput] input', async function () {
+ $(this).parents('td').attr('val', $(this).val())
+ $(this).parents('td').siblings('[customspeed]').attr('val', $(this).val())
+ var eve1 = new Event('change')
+ var eve2 = new Event('input')
+ var eve3 = new Event('click')
+ let patchSpeedDom = $(this).parents('td').siblings('[name=cutting_speed]')
+ let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
+ $(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
+ await timeOut(500)
+ patchProcessDom[0].dispatchEvent(eve3)
+ await timeOut(200)
+ const processVal = $(this).parent().attr('is')
+ patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
+ patchProcessDom.attr("data-tooltip", `${processVal}`)
+ patchProcessDom.find('select')[0].dispatchEvent(eve1)
+
+ patchSpeedDom[0].dispatchEvent(eve3)
+ await timeOut(200)
+ patchSpeedDom.find('input').val($(this).val())
+ await timeOut(50)
+ patchSpeedDom.find('input')[0].dispatchEvent(eve2)
+ patchSpeedDom.find('input')[0].dispatchEvent(eve1)
+ })
+ $(document).off('blur') // 防止重复绑定
+ $(document).on('blur', '[customInput] input', async function () {
+ if(!$(this).length) return
+
+ $(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
+ let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
+ try {
+ patchProcessDom[0].dispatchEvent(new Event('click'))
+ const processVal = $(this).parent().attr('is')
+ patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
+ patchProcessDom.attr("data-tooltip", `${processVal}`)
+ patchProcessDom.find('select')[0].dispatchEvent(new Event('change'))
+ } catch {
+
+ }
+
+ })
+}
+function timeOut(time) {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve()
+ }, time)
+ })
+}
+
+function listenAdd() {
+ $('td.o_field_x2many_list_row_add a').click(async function () {
+ await timeOut(500)
+ const tr = $('.o_list_table').children('tbody').children('tr').eq(-2)
+ if(tr.children('td').eq(2).text() == '') {
+ const dom = tr.children('[name=process_capability]')
+ if(!dom.length) return
+ dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
+ const isCu = dom.text() == '粗加工' // 是否粗加工
+ const v = dom.next().text() // 切削速度
+ dom.after(`${!isCu ? v : ''} | ${isCu ? v : ''} | `)
+ }
+ })
+}
+
+function listenSave() {
+ $('.o_form_button_save').click( async function () {
+ await timeOut(1000)
+ if($(this).parent().next().length) return
+ $('th[customTh],td[cusomSpeed]').remove()
+ getDomData()
+
+ })
+}
+
+listenAdd()
+listenSave()
+getDomData()
diff --git a/sf_base/static/js/setTableWidth.js b/sf_base/static/js/setTableWidth.js
new file mode 100644
index 00000000..571d46cf
--- /dev/null
+++ b/sf_base/static/js/setTableWidth.js
@@ -0,0 +1,47 @@
+// 因为表格可以拖动设置宽度,所以需要用js设置初始宽度
+function setBasicParamTableWidth() {
+ // const _100px = 'th[data-name="cutting_blade_length"],th[data-name="cutting_blade_length"],th[data-name="name"],th[data-name="tip_handling_size"],th[data-name="cutting_depth_max"],th[data-name="diameter_inner_circle"],th[data-name="diameter_mounting_hole" ],th[data-name="radius_tip_re" ],th[data-name="is_chip_breaker"],th[data-name="chip_breaker_type_code"],th[data-name="blade_profile"]'
+ // const _65px = 'th[data-name="edge_angle"],th[data-name="relief_angle"],[data-name="total_length"],th[data-name="length"],th[data-name="thickness"],th[data-name="blade_number"]'
+ // const _80px = 'th[data-name="arbor_diameter"],th[data-name="head_height"],th[data-name="head_width"],th[data-name="head_length"],th[data-name="blade_diameter"],th[data-name="blade_length"] ,th[data-name="neck_length"] ,th[data-name="neck_diameter"] ,th[data-name="shank_diameter"],th[data-name="shank_length"],th[data-name="tip_diameter"],th[data-name="knife_tip_taper"],th[data-name="blade_helix_angle"] ,th[data-name="blade_width"],th[data-name="blade_depth"]'
+ // const _50px = 'th[data-name="pitch"],th[data-name="width"],th[data-name="height"]'
+
+ const basicParamDom = $('.fixTableCss')
+ // const basicParamDom_100px = basicParamDom.find(_100px) // 四字以上
+ // const basicParamDom_65px = basicParamDom.find(_65px) // 大概三个字加单位
+ // const basicParamDom_80px = basicParamDom.find(_80px) // 大概四个字加单位
+ // const basicParamDom_50px= basicParamDom.find(_50px) // 大概两个字加单位
+ //
+ // basicParamDom_100px.css({'width': '100px', 'max-width': 'auto', ',min-width': 'auto'})
+ // basicParamDom_65px.css({'width': '65px', 'max-width': 'auto', ',min-width': 'auto'})
+ // basicParamDom_80px.css({'width': '80px', 'max-width': 'auto', ',min-width': 'auto'})
+ // basicParamDom_50px.css({'width': '50px', 'max-width': 'auto', ',min-width': 'auto'})
+ let dom = []
+ try {
+ dom = basicParamDom.find('table').find('thead').children().children()
+
+ } catch {
+ dom = []
+ }
+ if (!dom) return
+ dom.each(function () {
+ if ($(this).hasClass('row_no') >= 0) { // 序号列
+ // 不设置 通过css设置
+ }
+ const text = $(this).text().split('(')
+ if ($(this).attr('data-name') == 'name' || text[0].length > 4) {
+ $(this).width('100px')
+ } else if(text[0].length == 4){
+ $(this).width('80px')
+ } else if(text[0].length == 3){
+ $(this).width('65px')
+ } else if(text[0].length == 2){
+ $(this).width('50px')
+ }
+
+ })
+}
+
+setBasicParamTableWidth()
+$('.o_field_many2one_selection').on('click', $('#cutting_tool_material_id + ul'), function () {
+ setTimeout(setBasicParamTableWidth, 500)
+})
diff --git a/sf_base/static/js/updateTable.js b/sf_base/static/js/updateTable.js
new file mode 100644
index 00000000..beec2c94
--- /dev/null
+++ b/sf_base/static/js/updateTable.js
@@ -0,0 +1,159 @@
+// 获取表格数据
+function getDomData() {
+ const dom = $('#updateTable').prev()
+ if (!dom.length) return
+ const table = $('#updateTable').prev().find('.o_list_table')
+ const customTable = table.clone()
+ customTable.addClass('customTable')
+ table.parent().append(customTable)
+ table.hide()
+ const thead = customTable.children('thead')
+ const tbody = customTable.children('tbody')
+ const tableData = []
+ const tbody_child = tbody.children()
+
+ const tbody_child_len = tbody_child.length
+
+ for (let v = 0; v < tbody_child_len; v++) { // 将数据取出来到tableData里面
+ const data = tbody_child[v].innerText.split('\t')
+ // console.log('dom data',data)
+ const [index, deep, name, Φ, value] = data
+ tableData.push({index, deep, name, Φ, value})
+ }
+ const ΦList = [...new Set(tableData.map(_ => _.name))] // ΦList去重
+ const newTableData = {}
+ tableData.forEach(_ => {
+ const key = _.deep + '|' + _.Φ
+ !newTableData[key] ? newTableData[key] = {i: _.index} : '';
+ if (_.Φ) { // 去除没有Φ的脏数据
+ newTableData[key]['Φ' + _.Φ] = _.value
+ newTableData[key]['Φ' + _.Φ + 'i'] = _.index
+ }
+ })
+ // console.log('qwdh',tableData, ΦList, newTableData);
+
+ if (ΦList.filter(_ => _).length == 0) return;
+ handleThead(thead, ΦList)
+
+ handleTbody(tbody, newTableData, ΦList, table)
+}
+
+// 重新设置表头、
+function handleThead(thead, ΦList) {
+ const dom = thead.children().eq(0).children()
+ const len = dom.length
+ dom.eq(0).attr('rowspan', 2)
+ dom.eq(1).attr('rowspan', 2)
+ len == 5 ? dom.eq(2).attr('rowspan', 2) : ''
+ dom.eq(-2).attr('colspan', ΦList.length)
+ dom.eq(-1).remove()
+
+ const tr = document.createElement('tr')
+ for (let v = 0; v < ΦList.length; v++) {
+ const th = document.createElement('th')
+ th.innerText = 'Φ' + ΦList[v]
+ tr.append(th)
+ }
+ thead.append(tr)
+}
+
+// 重新设置表格
+function handleTbody(tbody, newTableData, ΦList, table) {
+ console.log(newTableData)
+ tbody.html('')
+ let i = 0
+ const data = Object.keys(newTableData)
+ // data.sort((a, b) => {
+ // a = a.split('=')[1].split('%')[0]
+ // b = b.split('=')[1].split('%')[0]
+ // return a - b
+ // })
+ // console.log('wqoqw ',ΦList)
+ data.forEach(_ => {
+ i++
+ const tr = $('
')
+ const td0 = $(' | ')
+ td0.text(i)
+ tr.append(td0)
+ const lit = _.split('|')
+ //
+ const td1 = $(' | ')
+ const td2 = $(' | ')
+ td1.text(lit[0])
+ td2.text(lit[1] || '')
+ tr.append(td1)
+ tr.append(td2)
+ ΦList.forEach(Φ => {
+ const td = $(' | ')
+ td.text(newTableData[_]['Φ' + Φ])
+ td.attr('col', newTableData[_]['Φ' + Φ + 'i'])
+ td.attr('val', newTableData[_]['Φ' + Φ])
+ td.attr('coustomTd', 1)
+ tr.append(td)
+ })
+ // // for (let j = 0; j < ΦList.length; j++) {
+ // // const td = document.createElement('td')
+ // // td.innerText = newTableData[data[v]][_]
+ // // th.append(td)
+ // // }
+ tbody.append(tr)
+ })
+ // $(document).click(function (e) {
+ // if ($(e.target).attr('coustomTd')) {
+ // const orginV = $('[coustomInput=1]').children('input').val()
+ // $('[coustomInput=1]').parent().html(orginV)
+ // const v = $(e.target).attr('val')
+ // console.log($(e.target));
+ // $(e.target).html('')
+ // const input = $('')
+ // input.children('input').val(v)
+ // $(e.target).append(input)
+ // input.children('input').focus()
+ // input.children('input').select()
+ // } else if ($(e.target).attr('coustomInput')) {
+ //
+ // } else {
+ // const orginV = $('[coustomInput=1]').children('input').val()
+ // $('[coustomInput=1]').parent().html(orginV)
+ // const v = $(e.target).attr('val')
+ // }
+ // })
+ // $(document).off('change') // 防止重复绑定
+// $(document).on('change', '[coustomInput] input', function () {
+// $(this).parents('td').attr('val', $(this).val());
+// var eve1 = new Event('change');
+// var eve2 = new Event('input');
+// var eve3 = new Event('click');
+// const i = $(this).parents('td').attr('col');
+// let patchDom = table.find('tbody').children('tr').eq(i - 1);
+//
+// if (patchDom.length === 0) {
+// console.error('No such row found');
+// return;
+// }
+//
+// patchDom = patchDom.children().eq(-1);
+//
+// setTimeout(() => {
+// if (patchDom.length === 0) {
+// console.error('No such cell found');
+// return;
+// }
+// patchDom[0].dispatchEvent(eve3); // Simulate click event
+//
+// setTimeout(() => {
+// patchDom = patchDom.find('input');
+// if (patchDom.length === 0) {
+// console.error('No input found in the target cell');
+// return;
+// }
+// patchDom.val($(this).val());
+// patchDom[0].dispatchEvent(eve2);
+// patchDom[0].dispatchEvent(eve1);
+// }, 200);
+// }, 500);
+// });
+
+}
+
+getDomData()
\ No newline at end of file
diff --git a/sf_base/static/src/scss/change.scss b/sf_base/static/src/scss/change.scss
new file mode 100644
index 00000000..6102b815
--- /dev/null
+++ b/sf_base/static/src/scss/change.scss
@@ -0,0 +1,52 @@
+.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector):not(.o_handle_cell):not(.o_list_button):not(.o_list_record_remove) {
+ white-space: nowrap !important;
+}
+
+.text-truncate {
+ overflow: unset !important;
+ text-overflow: unset !important;
+ white-space: unset !important;
+}
+
+
+// 设置表格不超出页面宽度
+.o_form_view .o_field_widget .o_list_renderer {
+ width: calc(100% - 64px) !important;
+ margin:0 auto;
+ overflow: auto;
+}
+
+// 表格针对处理
+.fixTableCss {
+ text-align: center;
+ .o_list_number_th,.o_list_number {
+ text-align: center!important;
+ }
+ .ui-sortable {
+ tr > td:first-child {
+ padding: 0!important;
+ }
+ }
+ .row_no {
+ padding: 0!important;;
+ width: 35px!important;
+ }
+
+ th[data-name="total_length"],th[data-name="length"],th[data-name="thickness"] {
+ .flex-row-reverse {
+ span {
+ text-align: center;
+ }
+ }
+ }
+}
+
+// 其他不能用js处理的表格
+.otherTableFix {
+ th[data-name="cutting_tool_material_id"] {
+ width: 100px!important;
+ }
+ th[data-name="ramping_angle_max"],th[data-name="ramping_angle_min"] {
+ width: 200px!important;
+ }
+}
\ No newline at end of file
diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml
index 6b97f0ec..b2d53392 100644
--- a/sf_base/views/tool_views.xml
+++ b/sf_base/views/tool_views.xml
@@ -360,6 +360,7 @@
+
@@ -380,6 +381,9 @@
+
+
+
@@ -392,6 +396,8 @@
+
+
diff --git a/sf_bf_connect/models/process_status.py b/sf_bf_connect/models/process_status.py
index 1bfdd356..09fecfae 100644
--- a/sf_bf_connect/models/process_status.py
+++ b/sf_bf_connect/models/process_status.py
@@ -36,6 +36,7 @@ class StatusChange(models.Model):
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
try:
res = super(StatusChange, self).action_confirm()
+ logging.info('原生方法返回结果:%s' % res)
# 原有方法执行后,进行额外的操作(如调用外部API)
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
config = self.env['res.config.settings'].get_values()
@@ -61,6 +62,7 @@ class StatusChange(models.Model):
traceback_error = traceback.format_exc()
logging.error("工厂加工同步订单状态失败:%s " % traceback_error)
raise UserError(e)
+ logging.info('最终返回值:%s' % res)
return res
def action_cancel(self):
diff --git a/sf_dlm_management/__manifest__.py b/sf_dlm_management/__manifest__.py
index a5c894d4..9a94082a 100644
--- a/sf_dlm_management/__manifest__.py
+++ b/sf_dlm_management/__manifest__.py
@@ -9,7 +9,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
- 'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing'],
+ 'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing','jikimo_attachment_viewer'],
'data': [
'data/stock_data.xml',
'views/product_template_management_view.xml',
diff --git a/sf_hr/models/hr_employee.py b/sf_hr/models/hr_employee.py
index e9826f29..065288de 100644
--- a/sf_hr/models/hr_employee.py
+++ b/sf_hr/models/hr_employee.py
@@ -11,6 +11,38 @@ class JkmPracticeEmployee(models.Model):
we_id = fields.Char(string='企微ID', index=True)
+ @api.model_create_multi
+ def create(self, vals_list):
+ for val in vals_list:
+ if 'work_email' in val:
+ val["we_id"] = self._get_we_id(val.get('work_email'))
+ if val.get('user_id'):
+ user = self.env['res.users'].browse(val['user_id'])
+ user.write({'we_employee_id': val["we_id"]})
+ return super(JkmPracticeEmployee, self).create(vals_list)
+
+ def write(self, vals):
+ if 'work_email' in vals:
+ vals["we_id"] = self._get_we_id(vals.get('work_email'))
+ if self.user_id:
+ self.user_id.write({'we_employee_id': vals["we_id"]})
+ return super(JkmPracticeEmployee, self).write(vals)
+
+ def _get_we_id(self, work_email):
+ json1 = {
+ 'params': {
+ 'work_email': work_email
+ }
+ }
+ url = '/api/get/we_id/info'
+ config = self.env['res.config.settings'].get_values()
+ ret = requests.post((config['ims_url'] + url), json=json1, data={})
+ result = ret.json()['result']
+ if result['code'] == 200:
+ if result['we_id']:
+ return result['we_id']
+ return None
+
def _employee_info_sync(self):
url = '/api/get/organization'
config = self.env['res.config.settings'].get_values()
diff --git a/sf_maintenance/security/ir.model.access.csv b/sf_maintenance/security/ir.model.access.csv
index 9a20f67f..8c1b0741 100644
--- a/sf_maintenance/security/ir.model.access.csv
+++ b/sf_maintenance/security/ir.model.access.csv
@@ -22,6 +22,10 @@ access_maintenance_equipment_agv_log,maintenance_equipment_agv_log,model_mainten
access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,1,1,0
access_maintenance_wizard_system_user,maintenance.request.wizard system user,model_maintenance_request_wizard,base.group_user,1,1,1,0
+access_maintenance_sf_group_equipment_user,equipment.request_sf_group_equipment_user,maintenance.model_maintenance_request,sf_group_equipment_user,1,1,1,0
+access_maintenance_wizard_sf_group_equipment_user,maintenance_wizard_sf_group_equipment_user,model_maintenance_request_wizard,sf_group_equipment_user,1,1,1,0
+access_maintenance_sf_group_equipment_manager,equipment.request_sf_group_equipment_manager,maintenance.model_maintenance_request,sf_group_equipment_manager,1,1,1,0
+access_maintenance_wizard_sf_group_equipment_manager,maintenance_wizard_sf_group_equipment_manager,model_maintenance_request_wizard,sf_group_equipment_manager,1,1,1,0
access_maintenance_equipment_group_plan_dispatch,maintenance.equipment,maintenance.model_maintenance_equipment,sf_base.group_plan_dispatch,1,0,0,0
access_maintenance_equipment_oee_group_plan_dispatch,maintenance_equipment_oee,model_maintenance_equipment_oee,sf_base.group_plan_dispatch,1,0,0,0
diff --git a/sf_maintenance/views/maintenance_request_views.xml b/sf_maintenance/views/maintenance_request_views.xml
index ad09c096..9353e80e 100644
--- a/sf_maintenance/views/maintenance_request_views.xml
+++ b/sf_maintenance/views/maintenance_request_views.xml
@@ -76,33 +76,61 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ 计划维保日期
+
-
+
-
-
-
+
+
+
-
-
+
+
+
+ maintenance.request.view.tree.sf
+ maintenance.request
+
+
+
+
+
+
+
+
+
+
+
+ maintenance.request.view.search.sf
+ maintenance.request
+
+
+
+
+
+
@@ -110,7 +138,7 @@
维保计划
maintenance.request
- kanban,tree,form,pivot,graph,calendar
+ tree,kanban,form,pivot,graph,calendar
{'default_user_id': uid}
diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py
index 71f4027a..fd15858a 100644
--- a/sf_manufacturing/__manifest__.py
+++ b/sf_manufacturing/__manifest__.py
@@ -10,7 +10,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
- 'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse'],
+ 'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse','jikimo_attachment_viewer'],
'data': [
'data/stock_data.xml',
'data/empty_racks_data.xml',
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 573bb73f..c602fd8b 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -141,12 +141,12 @@ class MrpProduction(models.Model):
], string='工序状态', default='待装夹')
# 零件图号
- part_number = fields.Char('零件图号', readonly=True)
+ part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
# 上传零件图纸
- part_drawing = fields.Binary('零件图纸', readonly=True)
+ part_drawing = fields.Binary('零件图纸', related='product_id.machining_drawings', readonly=True)
- quality_standard = fields.Binary('质检标准', readonly=True)
+ quality_standard = fields.Binary('质检标准', related='product_id.quality_standard', readonly=True)
@api.depends('product_id.manual_quotation')
def _compute_manual_quotation(self):
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 9c6b2a5c..37d42b42 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -59,7 +59,8 @@ class ResMrpWorkOrder(models.Model):
compute='_compute_state', store=True,
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
- delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
+ delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
+ tracking=True)
@api.depends('production_id.manual_quotation')
def _compute_manual_quotation(self):
@@ -1846,7 +1847,7 @@ class WorkPieceDelivery(models.Model):
return is_free
else:
raise UserError("接驳站暂未反馈站点实时状态,请稍后再试")
-
+
def delivery_avg(self):
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
if is_agv_task_dispatch:
diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py
index 3b8ed0a6..b7aa1adb 100644
--- a/sf_manufacturing/models/product_template.py
+++ b/sf_manufacturing/models/product_template.py
@@ -16,6 +16,12 @@ from OCC.Extend.DataExchange import write_stl_file
class ResProductMo(models.Model):
_inherit = 'product.template'
+ def _get_machining_precision(self):
+ machinings = self.env['sf.machining.accuracy'].sudo().search([])
+
+ list = [(m.sync_id, m.name) for m in machinings]
+ return list
+
model_file = fields.Binary('模型文件')
categ_type = fields.Selection(string='产品的类别', related='categ_id.type', store=True)
model_name = fields.Char('模型名称')
@@ -23,12 +29,7 @@ class ResProductMo(models.Model):
model_width = fields.Float('模型宽(mm)', digits=(16, 3))
model_height = fields.Float('模型高(mm)', digits=(16, 3))
model_volume = fields.Float('模型体积(m³)')
- model_machining_precision = fields.Selection([
- ('0.10', '±0.10mm'),
- ('0.05', '±0.05mm'),
- ('0.03', '±0.03mm'),
- ('0.02', '±0.02mm'),
- ('0.01', '±0.01mm')], string='加工精度')
+ model_machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
model_processing_panel = fields.Char('模型加工面板')
model_remark = fields.Char('模型备注说明')
length = fields.Float('长(mm)', digits=(16, 3))
@@ -776,8 +777,6 @@ class ResProductMo(models.Model):
part_number = fields.Char(string='零件图号', readonly=True)
machining_drawings = fields.Binary('2D加工图纸', readonly=True)
quality_standard = fields.Binary('质检标准', readonly=True)
- machining_drawings_name = fields.Char('2D加工图纸名', readonly=True)
- quality_standard_name = fields.Char('质检标准名', readonly=True)
@api.constrains('tool_length')
def _check_tool_length_size(self):
@@ -839,10 +838,10 @@ class ResProductMo(models.Model):
else:
return self.env.ref('sf_dlm.product_uom_cubic_millimeter')
- def attachment_update(self, name, res_id, res_field):
+ def attachment_update(self, name, res_id, res_field, mimetype):
attachment_info = self.env['ir.attachment'].sudo().search(
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
- attachment_info.write({'name': name})
+ attachment_info.write({'name': name, 'mimetype': mimetype})
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
def product_create(self, product_id, item, order_id, order_number, i):
@@ -882,8 +881,6 @@ class ResProductMo(models.Model):
'manual_quotation': item['manual_quotation'] or False,
'part_number': item.get('part_number') or '',
'active': True,
- 'machining_drawings_name': item['machining_drawings_name'],
- 'quality_standard_name': item['quality_standard_name'],
'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode(
item['machining_drawings']),
'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']),
@@ -894,12 +891,12 @@ class ResProductMo(models.Model):
vals.update({'taxes_id': [(6, 0, [int(tax_id)])]})
copy_product_id.sudo().write(vals)
product_id.product_tmpl_id.active = False
- if item['machining_drawings'] and item['machining_drawings_name']:
+ if item['machining_drawings'] and item['machining_drawings_name'] and item['machining_drawings_mimetype']:
self.attachment_update(item['machining_drawings_name'], copy_product_id.product_tmpl_id.id,
- 'machining_drawings')
- if item['quality_standard'] and item['quality_standard_name']:
+ 'machining_drawings', item['machining_drawings_mimetype'])
+ if item['quality_standard'] and item['quality_standard_name'] and item['quality_standard_mimetype']:
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
- 'quality_standard')
+ 'quality_standard', item['quality_standard_mimetype'])
return copy_product_id
def _get_ids(self, param):
diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py
index 02161b4a..40d159d5 100644
--- a/sf_manufacturing/models/stock.py
+++ b/sf_manufacturing/models/stock.py
@@ -272,21 +272,6 @@ class StockRule(models.Model):
workorder_duration += workorder.duration_expected
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
- # 根据销售订单号查询快速订单
- quick_easy_order = self.env['quick.easy.order'].sudo().search([('sale_order_id', '=', sale_order.id)])
- if quick_easy_order:
- production.write({'part_number': quick_easy_order.part_drawing_number,
- 'part_drawing': quick_easy_order.machining_drawings})
- else:
- production.write({'part_number': production.product_id.part_number,
- 'part_drawing': production.product_id.machining_drawings,
- 'quality_standard': production.product_id.quality_standard})
- if production.product_id.machining_drawings and production.product_id.machining_drawings_name:
- self.attachment_update(production.product_id.machining_drawings_name, production.id,
- 'part_drawing')
- if production.product_id.quality_standard and production.product_id.quality_standard_name:
- self.attachment_update(production.product_id.quality_standard_name, production.id,
- 'quality_standard')
if sale_order:
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(company_id).create({
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index 143ac4ab..8d3c6c4f 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -102,7 +102,7 @@
current
[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]
{'search_default_product': 1, 'search_default_workcenter_id':
- active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1}
+ active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,'search_default_filter_order_normal':1}
@@ -125,9 +125,9 @@
mrp.workorder
-
-
-
+
+
+
@@ -480,6 +480,15 @@
+
+
+
+
+
+
+
+
+
@@ -533,6 +542,13 @@
+
+
+
+
+
+
+
@@ -603,18 +619,6 @@
mrp.group_mrp_manager,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user,sf_base.group_sf_order_user
-
-
-
-
-
-
-
-
-
-
@@ -655,6 +659,7 @@
+
diff --git a/sf_message/data/cron_data.xml b/sf_message/data/cron_data.xml
index 736e3e91..9cddd04c 100644
--- a/sf_message/data/cron_data.xml
+++ b/sf_message/data/cron_data.xml
@@ -13,6 +13,19 @@
+
+ 检查销售订单是否完成并恢复正常时效
+
+ code
+ model._recover_sale_time_warning_func()
+ 10
+ minutes
+ -1
+
+
+
+
+
检查工单是否已逾期预警和逾期
diff --git a/sf_message/data/template_data.xml b/sf_message/data/template_data.xml
index 057dc009..beb37771 100644
--- a/sf_message/data/template_data.xml
+++ b/sf_message/data/template_data.xml
@@ -36,7 +36,7 @@
markdown
normal
### 销售订单逾期预警
-事项:共有[{{warning_num}}]({{url}})个销售订单有逾期风险
+事项:[共有{{warning_num}}个销售订单有逾期风险]({{url}})
@@ -48,7 +48,7 @@
markdown
urgent
### 销售订单已逾期提醒
-事项:共有[{{overdue_num}}]({{url}})个销售订单已逾期
+事项:[共有{{overdue_num}}个销售订单已逾期]({{url}})
@@ -97,7 +97,7 @@
timing
normal
### 工单逾期预警
-事项:共有[{{warning_num}}]({{url}})工单有逾期风险
+事项:[共有{{warning_num}}个工单有逾期风险]({{url}})
@@ -109,7 +109,7 @@
timing
normal
### 工单已逾期提醒
-事项:共有[{{overdue_num}}]({{url}})工单已逾期
+事项:[共有{{overdue_num}}个工单已逾期]({{url}})
@@ -121,7 +121,7 @@
timing
normal
### 工单逾期预警
-事项:共有[{{warning_num}}]({{url}})工单有逾期风险
+事项:[共有{{warning_num}}个工单有逾期风险]({{url}})
@@ -133,7 +133,7 @@
timing
normal
### 工单已逾期提醒
-事项:共有[{{overdue_num}}]({{url}})工单已逾期
+事项:[共有{{overdue_num}}个工单已逾期]({{url}})
@@ -145,7 +145,7 @@
timing
normal
### 工单逾期预警
-事项:共有[{{warning_num}}]({{url}})工单有逾期风险
+事项:[共有{{warning_num}}个工单有逾期风险]({{url}})
@@ -157,7 +157,7 @@
timing
normal
### 工单已逾期提醒
-事项:共有[{{overdue_num}}]({{url}})工单已逾期
+事项:[共有{{overdue_num}}个工单已逾期]({{url}})
@@ -169,7 +169,7 @@
timing
normal
### 工单逾期预警
-事项:共有[{{warning_num}}]({{url}})工单有逾期风险
+事项:[共有{{warning_num}}个工单有逾期风险]({{url}})
@@ -181,7 +181,7 @@
timing
normal
### 工单已逾期提醒
-事项:共有[{{overdue_num}}]({{url}})工单已逾期
+事项:[共有{{overdue_num}}个工单已逾期]({{url}})
@@ -262,7 +262,7 @@
markdown
normal
### 待质量判定提醒
-事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果
+事项:[共有{{judge_num}}个工单需判定质量结果]({{url}})
设备故障
diff --git a/sf_message/models/sf_message_sale.py b/sf_message/models/sf_message_sale.py
index 3fd57f8a..58d1a021 100644
--- a/sf_message/models/sf_message_sale.py
+++ b/sf_message/models/sf_message_sale.py
@@ -34,18 +34,19 @@ class SFMessageSale(models.Model):
picking_id.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids
purchase_order_id.extend(purchase_order_ids)
if purchase_order_id:
- purchase_order_list = self.env['purchase.order'].search([('id', 'in', purchase_order_id)])
+ purchase_order_list = self.env['purchase.order'].sudo().search([('id', 'in', purchase_order_id)])
for purchase_order_info in purchase_order_list:
purchase_order_info.add_queue('坯料采购提醒')
except Exception as e:
logging.info('add_queue error:%s' % e)
+ logging.info('action_confirm res:%s' % res)
return res
# 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids):
contents = []
bussiness_node = None
- url = self.env['ir.config_parameter'].get_param('web.base.url')
+ url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf)
current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
@@ -60,7 +61,7 @@ class SFMessageSale(models.Model):
contents.append(content)
elif item.message_template_id.bussiness_node_id.name == '确认接单':
content = super(SFMessageSale, self)._get_message(item)
- sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))])
+ sale_order_line = self.env['sale.order.line'].sudo().search([('order_id', '=', int(item.res_id))])
product = sale_order_line[0].product_id.name if len(sale_order_line) == 1 else '%s...' % \
sale_order_line[
0].product_id.name
@@ -100,42 +101,49 @@ class SFMessageSale(models.Model):
# # 销售订单逾期预警和已逾期
def _overdue_or_warning_func(self):
- today = datetime.today().date()
- deadline_check = today + timedelta(days=1)
- logging.info(f"today: {today}, deadline_check: {deadline_check}")
+ current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf)
+ today_str = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
+ today = today_str.strftime("%Y-%m-%d")
+ # 计算下一天的日期
+ deadline_check_str = today_str + timedelta(days=1)
+ deadline_check = deadline_check_str.strftime("%Y-%m-%d")
+ logging.info(
+ f"today: {today}, deadline_check: {deadline_check},current_time_strf: {current_time_strf}, current_time: {current_time}'")
sale_order = self.sudo().search(
[('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False), ('delivery_status', '!=', 'full')])
for item in sale_order:
- production = self.env['mrp.production'].search([('origin', '=', item.name)])
+ production = self.env['mrp.production'].sudo().search([('origin', '=', item.name)])
production_not_done = production.filtered(lambda p: p.state not in ['done', 'scrap', 'cancel'])
production_done_count = len(production.filtered(lambda p: p.state in ['done', 'scrap', 'cancel']))
+ deadline_of_delivery = item.deadline_of_delivery.strftime("%Y-%m-%d")
if (len(production_not_done) >= 1 and len(production_not_done) != item.mrp_production_count) or len(
production_not_done) != production_done_count:
- logging.info("-----不等于----")
- logging.info(f"name: {item.name}")
- logging.info(
- f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
- logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
- if deadline_check == item.deadline_of_delivery and item.delivery_warning not in ['warning']:
+ # logging.info("-----不等于----")
+ # logging.info(f"name: {item.name}")
+ # logging.info(
+ # f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
+ # logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
+ if deadline_check == deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
- elif today >= item.deadline_of_delivery and item.delivery_warning not in ['overdue']:
+ elif today >= deadline_of_delivery and item.delivery_warning not in ['overdue']:
item.delivery_warning = 'overdue'
elif production_done_count == item.mrp_production_count:
- logging.info("-----等于----")
- logging.info(f"name: {item.name}")
- logging.info(
- f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
- logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
+ # logging.info("-----等于----")
+ # logging.info(f"name: {item.name}")
+ # logging.info(
+ # f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
+ # logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
if item.delivery_status in ['pending', 'partial']:
- if deadline_check == item.deadline_of_delivery and item.delivery_warning not in ['warning']:
+ if deadline_check == deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
- elif today >= item.deadline_of_delivery and item.delivery_warning not in ['overdue']:
+ elif today >= deadline_of_delivery and item.delivery_warning not in ['overdue']:
item.delivery_warning = 'overdue'
else:
- logging.info("-----1111111----")
- logging.info(f"name: {item.name}")
- logging.info(
- f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
+ # logging.info("-----1111111----")
+ # logging.info(f"name: {item.name}")
+ # logging.info(
+ # f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
continue
# 获取业务节点
business_node_ids = {
@@ -146,11 +154,11 @@ class SFMessageSale(models.Model):
for wo in overdue_orders:
business_node_id = business_node_ids.get(wo.delivery_warning)
if business_node_id:
- message_template = self.env["jikimo.message.template"].search([
+ message_template = self.env["jikimo.message.template"].sudo().search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id)
], limit=1)
- sale_order_has = self.env['jikimo.message.queue'].search([
+ sale_order_has = self.env['jikimo.message.queue'].sudo().search([
('res_id', '=', wo.id),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template.id)
@@ -158,3 +166,32 @@ class SFMessageSale(models.Model):
if not sale_order_has:
message_name = '销售订单逾期预警' if wo.delivery_warning == 'warning' else '销售订单已逾期'
wo.add_queue(message_name)
+ if wo.delivery_warning == 'overdue':
+ # 把消息队列中销售订单预警的状态改为取消发送
+ business_node_id_warning = business_node_ids['warning']
+ if business_node_id_warning:
+ message_template_warning = self.env["jikimo.message.template"].search([
+ ("model", "=", self._name),
+ ("bussiness_node_id", "=", business_node_id_warning)
+ ], limit=1)
+ if message_template_warning:
+ sale_order_warning = self.env['jikimo.message.queue'].search([
+ ('res_id', '=', wo.id),
+ ('message_status', '=', 'pending'),
+ ('message_template_id', '=', message_template_warning.id)
+ ])
+ if sale_order_warning:
+ logging.info('取消发送:%s' % sale_order_warning)
+ sale_order_warning.write({'message_status': 'cancel'})
+
+ def _recover_sale_time_warning_func(self):
+ sale_order_done = self.sudo().search([('state', 'in', ['sale']), ('delivery_status', '=', 'full')])
+ sale_order_overdue = sale_order_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning'])
+ if sale_order_overdue:
+ sale_order_overdue.write({'delivery_warning': 'normal'})
+ message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
+ ("message_status", "=", "pending"),
+ ("res_id", "in", [item.id for item in sale_order_overdue])
+ ])
+ if message_queue_ids:
+ message_queue_ids.write({'message_status': 'cancel'})
diff --git a/sf_message/models/sf_message_stock_picking.py b/sf_message/models/sf_message_stock_picking.py
index 9d7c7f0e..6e80c670 100644
--- a/sf_message/models/sf_message_stock_picking.py
+++ b/sf_message/models/sf_message_stock_picking.py
@@ -29,14 +29,14 @@ class SFMessageStockPicking(models.Model):
[('origin', '=', record.origin), ('state', '!=', 'done'),
('picking_type_id.sequence_code', '=', 'SFP')])
if not stock_picking_sfp:
- stock_picking_send = self.env["jikimo.message.queue"].search([('res_id', '=', record.id)])
+ stock_picking_send = self.env["jikimo.message.queue"].sudo().search([('res_id', '=', record.id)])
if not stock_picking_send:
record.add_queue('订单发货提醒')
def deal_stock_picking_sfp(self, message_queue_id): # 处理订单发货提醒
content = None
- stock_picking = self.env['stock.picking'].search([('id', '=', int(message_queue_id.res_id))])
- stock_picking_out = self.env['stock.picking'].search(
+ stock_picking = self.env['stock.picking'].sudo().search([('id', '=', int(message_queue_id.res_id))])
+ stock_picking_out = self.env['stock.picking'].sudo().search(
[('origin', '=', stock_picking.origin), ('state', '=', 'assigned'),
('picking_type_id.sequence_code', '=', 'OUT')])
if stock_picking_out and len(stock_picking_out) > 0:
@@ -54,10 +54,10 @@ class SFMessageStockPicking(models.Model):
i = 0
if message_queue_id.message_template_id.name == '坯料发料提醒':
content = message_queue_id.message_template_id.content
- stock_picking_line = self.env['stock.picking'].search([('id', '=', int(message_queue_id.res_id))])
- mrp_production_info = self.env['mrp.production'].search(
+ stock_picking_line = self.env['stock.picking'].sudo().search([('id', '=', int(message_queue_id.res_id))])
+ mrp_production_info = self.env['mrp.production'].sudo().search(
[('name', '=', stock_picking_line.origin)])
- mrp_production_list = self.env['mrp.production'].search(
+ mrp_production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', mrp_production_info.product_id.id)])
for mrp_production_line in mrp_production_list:
picking_ids = mrp_production_line.picking_ids
@@ -87,9 +87,9 @@ class SFMessageStockPicking(models.Model):
return super(SFMessageStockPicking, self).get_special_url(id, tmplate_name, special_name, model_id)
def request_url(self):
- url = self.env['ir.config_parameter'].get_param('web.base.url')
+ url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('stock.stock_picking_type_action').id
- menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
+ menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'kanban'}
@@ -100,9 +100,9 @@ class SFMessageStockPicking(models.Model):
return full_url
def request_url1(self, id):
- url = self.env['ir.config_parameter'].get_param('web.base.url')
+ url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('stock.action_picking_tree_all').id
- menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
+ menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'form'}
diff --git a/sf_message/models/sf_message_workorder.py b/sf_message/models/sf_message_workorder.py
index c531e013..d5186797 100644
--- a/sf_message/models/sf_message_workorder.py
+++ b/sf_message/models/sf_message_workorder.py
@@ -26,7 +26,7 @@ class SFMessageWork(models.Model):
contents = []
product_id = []
bussiness_node = None
- url = self.env['ir.config_parameter'].get_param('web.base.url')
+ url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf)
current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
@@ -39,8 +39,8 @@ class SFMessageWork(models.Model):
for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '工单已下发通知':
content = message_queue_id.message_template_id.content
- mrp_workorder_line = self.env['mrp.workorder'].search([('id', '=', int(message_queue_id.res_id))])
- mrp_workorder_list = self.env['mrp.workorder'].search(
+ mrp_workorder_line = self.env['mrp.workorder'].sudo().search([('id', '=', int(message_queue_id.res_id))])
+ mrp_workorder_list = self.env['mrp.workorder'].sudo().search(
[('product_id', '=', mrp_workorder_line.product_id.id), ('state', '=', 'ready'),
('routing_type', '=', '装夹预调')])
if len(mrp_workorder_list) > 0 and mrp_workorder_line.product_id.id not in product_id:
@@ -61,20 +61,32 @@ class SFMessageWork(models.Model):
second=0,
microsecond=0
)
- logging.info(current_time)
- logging.info(target_time)
- logging.info(target_time - time_range)
- logging.info(target_time + time_range)
+ # logging.info(current_time)
+ # logging.info(target_time)
+ # logging.info(target_time - time_range)
+ # logging.info(target_time + time_range)
if target_time - time_range <= current_time_datetime <= target_time + time_range:
search_condition = [
('delivery_warning', '=', 'warning')] if bussiness_node in template_names['预警'] else [
('delivery_warning', '=', 'overdue')]
- record = self.sudo().search(search_condition + [('id', '=', int(item.res_id))])
+ record = self.sudo().search(search_condition + [('id', '=', int(message_queue_id.res_id))])
if record:
+ bussiness_node = item.bussiness_node_id.name
+ # 分割业务节点名称,提取出业务节点关键字
+ business_node_key = bussiness_node.split('工单')[0].strip()
+ workcenter_mapping = {
+ '装夹预调': '工件装夹',
+ 'CNC加工': '自动生产',
+ '解除装夹': '工件拆卸',
+ '表面工艺': '表面工艺外协',
+ }
+ workcenter_name = workcenter_mapping.get(business_node_key)
+ active_id = self.env['mrp.workcenter'].search([('name', 'ilike', workcenter_name)],
+ limit=1).id
i += 1
if i >= 1:
action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id
- url_with_id = f"{url}/web#view_type=list&action={action_id}"
+ url_with_id = f"{url}/web#view_type=list&action={action_id}&active_id={active_id}"
content_template = content.replace('{{url}}', url_with_id)
if bussiness_node in template_names['预警']:
content = content_template.replace('{{warning_num}}', str(i))
@@ -84,12 +96,13 @@ class SFMessageWork(models.Model):
return contents
def request_url(self):
- url = self.env['ir.config_parameter'].get_param('web.base.url')
- action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id
- menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id
+ url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ action_id = self.env.ref('sf_message.mrp_workorder_issued_action').id
+ menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_stock_dropshipping')]).id
+ active_id = self.env['mrp.workcenter'].sudo().search([('name', '=', '工件装夹中心')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'mrp.workorder',
- 'view_type': 'list', 'active_id': 1}
+ 'view_type': 'list', 'active_id': active_id}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
@@ -97,7 +110,8 @@ class SFMessageWork(models.Model):
return full_url
def _overdue_or_warning_func(self):
- workorders = self.env['mrp.workorder'].search([("state", "in", ["ready", "progress", "to be detected"])])
+ workorders = self.env['mrp.workorder'].search(
+ [("state", "in", ["ready", "progress", "to be detected"]), ('schedule_state', '=', '已排')])
grouped_workorders = {}
for workorder in workorders:
routing_type = workorder.routing_type
@@ -116,21 +130,25 @@ class SFMessageWork(models.Model):
date_planned_finished = datetime.strptime(date_planned_finished_str, '%Y-%m-%d %H:%M:%S')
twelve_hours_ago = current_time_datetime - timedelta(hours=12)
if current_time_datetime >= date_planned_finished and item.delivery_warning not in ['overdue']:
- logging.info("------overdue-------")
- logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
- f"Planned Finish: {date_planned_finished}")
+ # logging.info("------overdue-------")
+ # logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
+ # f"Planned Finish: {date_planned_finished}")
item.delivery_warning = 'overdue'
elif twelve_hours_ago <= current_time_datetime <= date_planned_finished and item.delivery_warning not in [
'warning']:
- logging.info("------warning-------")
- logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
- f"Planned Finish: {date_planned_finished}")
+ # logging.info("------warning-------")
+ # logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
+ # f"Planned Finish: {date_planned_finished}")
item.delivery_warning = 'warning'
business_node_ids = {
- '装夹预调': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id,
- 'CNC加工': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id,
- '解除装夹': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id,
- '表面工艺': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue_warning').id,
+ '装夹预调_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue').id,
+ '装夹预调_warning': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id,
+ 'CNC加工_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue').id,
+ 'CNC加工_warning': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id,
+ '解除装夹_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue').id,
+ '解除装夹_warning': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id,
+ '表面工艺_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue').id,
+ '表面工艺_warning': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue_warning').id,
}
message_templates = {key: self.env["jikimo.message.template"].sudo().search([
("model", "=", self._name),
@@ -138,13 +156,17 @@ class SFMessageWork(models.Model):
]) for key in business_node_ids}
for item in orders:
if item.delivery_warning in ['overdue', 'warning']:
- bussiness_node_id = business_node_ids.get(item.routing_type)
- if bussiness_node_id and message_templates[item.routing_type]:
- message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
- ("message_template_id", "=", message_templates[item.routing_type].id),
- ("message_status", "=", "pending"),
- ("res_id", "=", item.id)
- ])
+ warning_type = 'warning' if item.delivery_warning == 'warning' else 'overdue'
+ key = f"{item.routing_type}_{warning_type}"
+ bussiness_node_id = business_node_ids.get(key, None)
+ if bussiness_node_id:
+ message_template = message_templates.get(key)
+ if message_template and message_template.id:
+ message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
+ ("message_template_id", "=", message_template.id),
+ ("message_status", "=", "pending"),
+ ("res_id", "=", item.id)
+ ], limit=1)
if not message_queue_ids:
overdue_message = '工单已逾期' if item.delivery_warning == 'overdue' else '工单逾期预警'
queue_method_name = f'add_queue'
@@ -152,8 +174,33 @@ class SFMessageWork(models.Model):
args = [f'{item.routing_type}{overdue_message}']
# 获取add_queue方法并调用它,传入参数列表
getattr(item, queue_method_name)(*args)
+ if item.delivery_warning == 'overdue':
+ # 把消息队列中销售订单预警的状态改为取消发送
+ key = f"{item.routing_type}_{'warning'}"
+ business_node_id_warning = business_node_ids.get(key, None)
+ if business_node_id_warning:
+ message_template_warning = self.env["jikimo.message.template"].search([
+ ("model", "=", self._name),
+ ("bussiness_node_id", "=", business_node_id_warning)
+ ], limit=1)
+ if message_template_warning:
+ work_order_warning = self.env['jikimo.message.queue'].search([
+ ('res_id', '=', item.id),
+ ('message_status', '=', 'pending'),
+ ('message_template_id', '=', message_template_warning.id)
+ ])
+ if work_order_warning:
+ logging.info('取消发送:%s' % work_order_warning)
+ work_order_warning.write({'message_status': 'cancel'})
def _recover_time_warning_func(self):
workorder_done = self.env['mrp.workorder'].search([("state", "in", ["done", "rework", "cancel"])])
workorder_overdue = workorder_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning'])
- workorder_overdue.write({'delivery_warning': 'normal'})
+ if workorder_overdue:
+ workorder_overdue.write({'delivery_warning': 'normal'})
+ message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
+ ("message_status", "=", "pending"),
+ ("res_id", "in", [item.id for item in workorder_overdue])
+ ])
+ if message_queue_ids:
+ message_queue_ids.write({'message_status': 'cancel'})
diff --git a/sf_message/security/ir.model.access.csv b/sf_message/security/ir.model.access.csv
index 05a7366c..4aa153e6 100644
--- a/sf_message/security/ir.model.access.csv
+++ b/sf_message/security/ir.model.access.csv
@@ -5,24 +5,28 @@ access_jikimo_message_template_group_purchase,jikimo_message_template,jikimo_mes
access_jikimo_message_template_group_sf_stock_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_template_group_sf_order_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_template_group_sf_tool_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_tool_user,1,1,1,0
+access_jikimo_message_template_group_purchase_director,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_purchase_director,1,1,1,0
access_jikimo_message_bussiness_node_group_sale_salemanager,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_bussiness_node_group_purchase,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_purchase,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_stock_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_order_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_tool_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_tool_user,1,1,1,0
+access_jikimo_message_bussiness_node_group_purchase_director,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_purchase_director,1,1,1,0
access_jikimo_message_queue_group_sale_salemanager,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_queue_group_purchase,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_purchase,1,1,1,0
access_jikimo_message_queue_group_sf_stock_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_queue_group_sf_order_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_queue_group_sf_tool_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_tool_user,1,1,1,0
+access_jikimo_message_queue_group_purchase_director,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_purchase_director,1,1,1,0
access_jikimo_message_reminder_time_group_sale_salemanager,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_reminder_time_group_purchase,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_purchase,1,1,1,0
access_jikimo_message_reminder_time_group_sf_stock_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_reminder_time_group_sf_order_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_reminder_time_group_sf_tool_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_tool_user,1,1,1,0
+access_jikimo_message_reminder_time_group_purchase_director,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_purchase_director,1,1,1,0
diff --git a/sf_message/views/mrp_workorder_views.xml b/sf_message/views/mrp_workorder_views.xml
index 1e31fc6d..ab0a76a9 100644
--- a/sf_message/views/mrp_workorder_views.xml
+++ b/sf_message/views/mrp_workorder_views.xml
@@ -30,5 +30,36 @@
+
+
+
+ 工单
+ ir.actions.act_window
+ mrp.workorder
+ tree,form
+
+
+
+ current
+ [('state', '!=', 'cancel'),('schedule_state', '=', '已排')]
+ {'search_default_product': 1, 'search_default_workcenter_id':
+ active_id,'search_default_ready': 1, 'search_default_progress': 1}
+
+
+
+ 没有工单要做!
+
+
+ 工作订单是作为制造订单的一部分执行的操作。
+ 工序在物料清单中定义或直接添加到制造订单中。
+
+
+ 使用工作台工作中心控制面板直接登记车间中的操作.
+ 平板电脑为您的工人提供工作表,并允许他们报废产品,跟踪时间,
+ 发起维护请求,执行质量测试等.
+
+
+
\ No newline at end of file
diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py
index ae1930c6..29d32e5f 100644
--- a/sf_mrs_connect/models/sync_common.py
+++ b/sf_mrs_connect/models/sync_common.py
@@ -3166,5 +3166,5 @@ class MachiningAccuracySync(models.Model):
self.env['sf.machining.accuracy'].sudo().create({
"sync_id": time['id'],
"name": time['name'],
- "discount": time['discount'],
+ "standard_tolerance": time['standard_tolerance'],
})
diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py
index 492ef525..bdf916ce 100644
--- a/sf_plan/models/custom_plan.py
+++ b/sf_plan/models/custom_plan.py
@@ -246,26 +246,27 @@ class sf_production_plan(models.Model):
record.date_planned_finished = item.date_planned_finished
# 计算下一个cnc工单的开始时间
last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration)
- record.state = 'done'
- # record.production_id.schedule_state = '已排'
- record.sudo().production_id.schedule_state = '已排'
- record.sudo().production_id.process_state = '待装夹'
- # self.env['sale.order'].browse(record.production_id.origin).schedule_status = 'to process'
- # sale_obj = self.env['sale.order'].search([('name', '=', record.origin)])
- # if 'S' in sale_obj.name:
- # sale_obj.schedule_status = 'to process'
- mrp_production_ids = record.production_id._get_children().ids
- print('mrp_production_ids', mrp_production_ids)
- for i in mrp_production_ids:
- record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
- # record.production_id.date_planned_start = record.date_planned_start
- # record.production_id.date_planned_finished = record.date_planned_finished
- record.sudo().production_id.production_line_id = record.production_line_id.id
- if record.production_id.workorder_ids:
- record.sudo().production_id.workorder_ids.filtered(
- lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
- {'production_line_id': record.production_line_id.id,
- 'plan_start_processing_time': record.date_planned_start})
+ # 没有工单也能排程
+ record.state = 'done'
+ # record.production_id.schedule_state = '已排'
+ record.sudo().production_id.schedule_state = '已排'
+ record.sudo().production_id.process_state = '待装夹'
+ # self.env['sale.order'].browse(record.production_id.origin).schedule_status = 'to process'
+ # sale_obj = self.env['sale.order'].search([('name', '=', record.origin)])
+ # if 'S' in sale_obj.name:
+ # sale_obj.schedule_status = 'to process'
+ mrp_production_ids = record.production_id._get_children().ids
+ print('mrp_production_ids', mrp_production_ids)
+ for i in mrp_production_ids:
+ record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
+ # record.production_id.date_planned_start = record.date_planned_start
+ # record.production_id.date_planned_finished = record.date_planned_finished
+ record.sudo().production_id.production_line_id = record.production_line_id.id
+ if record.production_id.workorder_ids:
+ record.sudo().production_id.workorder_ids.filtered(
+ lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
+ {'production_line_id': record.production_line_id.id,
+ 'plan_start_processing_time': record.date_planned_start})
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
# record.state = 'done'
diff --git a/sf_plan/wizard/action_plan_some.py b/sf_plan/wizard/action_plan_some.py
index 1c08ff0f..86b3f1ac 100644
--- a/sf_plan/wizard/action_plan_some.py
+++ b/sf_plan/wizard/action_plan_some.py
@@ -37,52 +37,4 @@ class Action_Plan_All_Wizard(models.TransientModel):
# 判断能否排成
self.plan_ids.deal_processing_schedule(self.date_planned_start)
self.plan_ids.do_production_schedule()
- # for plan in temp_plan_ids:
- # # 处理每个计划
- # # 比如更新计划状态、分配资源等
- # # 示例:plan.state = 'scheduled'
- # print('处理计划:', plan.id)
- # # 拿到计划对象
- # plan_obj = self.env['sf.production.plan'].browse(plan.id)
- # plan_obj.production_line_id = self.production_line_id.id
- # plan.date_planned_start = self.date_planned_start
- # plan_obj.do_production_schedule()
- # plan_obj.state = 'done'
_logger.info('处理计划: %s 完成', self.plan_ids.ids)
-
- # # 获取当前生产线
- # production_line_id = self.production_line_id
- # # 获取当前生产线的所有生产订单
- # production_order_ids = self.env['mrp.production'].search([('production_line_id', '=', production_line_id.id)])
- # # 获取当前生产线的所有生产订单的id
- # production_order_id_list = []
- # for production_order_id in production_order_ids:
- # production_order_id_list.append(production_order_id.id)
- # # 获取当前生产线的所有生产订单的排程状态
- # production_order_plan_state_list = []
- # for production_order_id in production_order_ids:
- # production_order_plan_state_list.append(production_order_id.plan_state)
- # # 如果当前生产线的所有生产订单的排程状态都是已排程,则报错
- # if all(production_order_plan_state == '已排程' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已排程,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是未排程,则报错
- # if all(production_order_plan_state == '未排程' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都未排程,请先排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已完成,则报错
- # if all(production_order_plan_state == '已完成' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已完成,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已取消,则报错
- # if all(production_order_plan_state == '已取消' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已取消,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已暂停,则报错
- # if all(production_order_plan_state == '已暂停' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已暂停,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已完成,则报错
- # if all(production_order_plan_state == '已完成' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已完成,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已取消,则报错
- # if all(production_order_plan_state == '已取消' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已取消,请勿重复排程!')
- # # 如果当前生产线的所有生产订单的排程状态都是已暂停,则报错
- # if all(production_order_plan_state == '已暂停' for production_order_plan_state in production_order_plan_state_list):
- # raise UserError('当前生产线的所有生产订单都已暂停,请勿重复排程!')
diff --git a/sf_quality/__manifest__.py b/sf_quality/__manifest__.py
index b1151b6d..582e306a 100644
--- a/sf_quality/__manifest__.py
+++ b/sf_quality/__manifest__.py
@@ -13,7 +13,7 @@
'author': 'jikimo',
'website': 'https://sf.cs.jikimo.com',
# 此处依赖sf_manufacturing是因为我要重写其中的一个字段operation_id的string,故需要sf_manufacturing先安装
- 'depends': ['quality_control', 'web_widget_model_viewer', 'sf_manufacturing'],
+ 'depends': ['quality_control', 'web_widget_model_viewer', 'sf_manufacturing','jikimo_attachment_viewer'],
'data': [
'security/ir.model.access.csv',
'views/view.xml',
diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py
index 4756a2c5..e974c5d4 100644
--- a/sf_sale/models/quick_easy_order_old.py
+++ b/sf_sale/models/quick_easy_order_old.py
@@ -20,6 +20,12 @@ class QuickEasyOrder(models.Model):
_description = '简易下单'
_order = 'id desc'
+ def _get_machining_precision(self):
+ machinings = self.env['sf.machining.accuracy'].sudo().search([])
+
+ list = [(m.sync_id, m.name) for m in machinings]
+ return list
+
name = fields.Char('订单编号', default=lambda self: self.env['ir.sequence'].next_by_code('quick.easy.order'))
model_length = fields.Float('长(mm)', digits=(16, 3))
model_width = fields.Float('宽(mm)', digits=(16, 3))
@@ -27,12 +33,7 @@ class QuickEasyOrder(models.Model):
model_volume = fields.Float('体积(mm³)', digits=(16, 3))
model_processing_side = fields.Char('加工面', default='A')
model_feature = fields.Char('特征')
- machining_precision = fields.Selection([
- ('0.10', '±0.10mm'),
- ('0.05', '±0.05mm'),
- ('0.03', '±0.03mm'),
- ('0.02', '±0.02mm'),
- ('0.01', '±0.01mm')], string='加工精度', default='0.10')
+ machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
material_id = fields.Many2one('sf.production.materials', '材料', tracking=True)
material_model_id = fields.Many2one('sf.materials.model', '型号', domain="[('materials_id', '=', material_id)]",
tracking=True)
@@ -219,7 +220,14 @@ class QuickEasyOrder(models.Model):
'total_amount': item.price,
'remark': '',
'manual_quotation': True,
- 'barcode': barcode
+ 'barcode': barcode,
+ 'part_number': item.part_drawing_number,
+ 'machining_drawings_name': '',
+ 'quality_standard_name': '',
+ 'machining_drawings_mimetype': '',
+ 'quality_standard_mimetype': '',
+ 'machining_drawings': item.machining_drawings,
+ 'quality_standard': '',
})
# res['bfm_process_order_list'] = json.dumps(res['bfm_process_order_list'])
product_id = self.env.ref('sf_dlm.product_template_sf').sudo()
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py
index d3ec1aa0..53f73aef 100644
--- a/sf_sale/models/sale_order.py
+++ b/sf_sale/models/sale_order.py
@@ -55,7 +55,8 @@ class ReSaleOrder(models.Model):
store=True, readonly=False, copy=False, precompute=True,
states=READONLY_FIELD_STATES, default=fields.Datetime.now)
- delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
+ delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
+ tracking=True)
# 业务平台分配工厂后在智能工厂先创建销售订单
def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address,
@@ -117,12 +118,16 @@ class ReSaleOrder(models.Model):
# 业务平台分配工厂时在创建完产品后再创建销售明细信息
def sale_order_create_line(self, product, item):
+ machining_accuracy_name = ''
+ if product.model_machining_precision:
+ machining_accuracy_name = self.env['sf.machining.accuracy'].sudo().search(
+ [('sync_id', '=', product.model_machining_precision)]).name
vals = {
'order_id': self.id,
'product_id': product.id,
- 'name': '%s/%s/%s/%s/±%s/%s' % (
+ 'name': '%s/%s/%s/%s/%s/%s' % (
product.model_long, product.model_width, product.model_height, product.model_volume,
- product.model_machining_precision,
+ machining_accuracy_name,
product.materials_id.name),
'price_unit': product.list_price,
'product_uom_qty': item['number'],
diff --git a/sf_sale/views/purchase_order_view.xml b/sf_sale/views/purchase_order_view.xml
index 7a9836c5..f721d515 100644
--- a/sf_sale/views/purchase_order_view.xml
+++ b/sf_sale/views/purchase_order_view.xml
@@ -6,14 +6,20 @@
purchase.order
-
+
+ 1
+
-
+
+
1
diff --git a/sf_sale/views/quick_easy_order_view.xml b/sf_sale/views/quick_easy_order_view.xml
index 9111403d..aebb4e97 100644
--- a/sf_sale/views/quick_easy_order_view.xml
+++ b/sf_sale/views/quick_easy_order_view.xml
@@ -80,8 +80,8 @@
-
-
+
+
diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py
index 267dbe60..8fe9748e 100644
--- a/sf_tool_management/models/mrp_workorder.py
+++ b/sf_tool_management/models/mrp_workorder.py
@@ -200,6 +200,8 @@ class MrpProduction(models.Model):
self[0].write({'is_rework': False})
# 修改制造订单 编程状态变为“编程中” 制造订单状态为‘返工’
self.write({'programming_state': '编程中', 'work_state': '编程中', 'state': 'rework'})
+ self[0].workorder_ids.filtered(
+ lambda a: a.name == '装夹预调' and a.state not in ['rework', 'done', 'cancel'])._compute_state()
if missing_tool_1:
logging.info(f'线边、机内缺刀:{missing_tool_1}')
# 修改 修改cnc程序的‘刀具状态’ 为 ‘缺刀’