增加平板扫码功能
6
sf_global_search/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"name": "机企猫 全局扫码搜索",
|
"name": "机企猫 全局扫码搜索",
|
||||||
|
|
||||||
"author": "Softhealer Technologies",
|
"author": "jikimo",
|
||||||
|
|
||||||
"website": "https://www.softhealer.com",
|
"website": "https://www.softhealer.com",
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
"category": "Extra Tools",
|
"category": "Extra Tools",
|
||||||
|
|
||||||
"summary": "any data search,Easy Object Search,Quick Object Find Module, advance search,Object Using Attributes,Overall Odoo Object Search,Global Model Search,advance records search,google search,Feeds search,all in one search,search option Odoo",
|
"summary": "sf_global_search",
|
||||||
|
|
||||||
"description": """
|
"description": """
|
||||||
A global search used to search any object based on the configuration. You can search all object's data easily. You can also configure one to many fields. The "Global Search" is visible to all odoo users. The search box is available at the top of the menu. Search results on click redirect to that record on the new tab. You can easily perform a search on multi-company objects also we have beautifully show company name before so you can see search results related to that company, we have show object (model) nicely whenever you have search query found in multiple objects, you can very easily see the difference of different objects. It also takes care of access rights of users, if a user doesn't have any object access than it will not show that record in search results. if the user has multi-company enabled than it shows multi-company results. We have made this looks fully configurable you can easily configure what is an important object(model) and related fields of that object(model), We have made security groups for this configurations so only who have right that user only can configure this global search objects and fields, All internal users can use this global search feature. Cheers!""",
|
A global search used to search any object based on the configuration. You can search all object's data easily. You can also configure one to many fields. The "Global Search" is visible to all odoo users. The search box is available at the top of the menu. Search results on click redirect to that record on the new tab. You can easily perform a search on multi-company objects also we have beautifully show company name before so you can see search results related to that company, we have show object (model) nicely whenever you have search query found in multiple objects, you can very easily see the difference of different objects. It also takes care of access rights of users, if a user doesn't have any object access than it will not show that record in search results. if the user has multi-company enabled than it shows multi-company results. We have made this looks fully configurable you can easily configure what is an important object(model) and related fields of that object(model), We have made security groups for this configurations so only who have right that user only can configure this global search objects and fields, All internal users can use this global search feature. Cheers!""",
|
||||||
@@ -29,14 +29,13 @@ A global search used to search any object based on the configuration. You can se
|
|||||||
'assets': {
|
'assets': {
|
||||||
|
|
||||||
'web.assets_backend': [
|
'web.assets_backend': [
|
||||||
'sh_global_search/static/src/scss/GlobalSearch.scss',
|
'sf_global_search/static/src/scss/GlobalSearch.scss',
|
||||||
'sh_global_search/static/src/xml/*.xml',
|
'sf_global_search/static/src/xml/*.xml',
|
||||||
'sh_global_search/static/src/js/*',
|
'sf_global_search/static/src/js/*',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"images": ["static/description/background.png", ],
|
"images": ["static/description/background.png", ],
|
||||||
"live_test_url": "https://youtu.be/rbkWI9j0XN0",
|
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"auto_install": False,
|
"auto_install": False,
|
||||||
"application": True,
|
"application": True,
|
||||||
@@ -404,7 +404,7 @@ class GlobalSearchFields(models.Model):
|
|||||||
|
|
||||||
def sh_o2m_dynamic_action_action(self):
|
def sh_o2m_dynamic_action_action(self):
|
||||||
if self.ttype == 'one2many':
|
if self.ttype == 'one2many':
|
||||||
view = self.env.ref('sh_global_search.sh_o2m_global_search_form')
|
view = self.env.ref('sf_global_search.sh_o2m_global_search_form')
|
||||||
return {
|
return {
|
||||||
'name': _('O2M Object Fields'),
|
'name': _('O2M Object Fields'),
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
@@ -417,7 +417,7 @@ class GlobalSearchFields(models.Model):
|
|||||||
|
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
view = self.env.ref('sh_global_search.sh_m2o_global_search_form')
|
view = self.env.ref('sf_global_search.sh_m2o_global_search_form')
|
||||||
return {
|
return {
|
||||||
'name': _('M2O Object Fields'),
|
'name': _('M2O Object Fields'),
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 421 B |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 390 B |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.8 MiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 235 KiB After Width: | Height: | Size: 235 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -13,7 +13,7 @@
|
|||||||
<!-- <div class="input-group-text"> -->
|
<!-- <div class="input-group-text"> -->
|
||||||
<!-- <button class="fa fa-qrcode icon-button" t-on-click="on2BarcodeBtnClick"> -->
|
<!-- <button class="fa fa-qrcode icon-button" t-on-click="on2BarcodeBtnClick"> -->
|
||||||
<button class="icon-button" t-on-click="on2BarcodeBtnClick">
|
<button class="icon-button" t-on-click="on2BarcodeBtnClick">
|
||||||
<img src="/sh_global_search/static/src/img/barcode.png" style="width: 20px; height: 20px;"/></button>
|
<img src="/sf_global_search/static/src/img/barcode.png" style="width: 20px; height: 20px;"/></button>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" placeholder="Searching ..." t-on-keydown="onSearchResultsNavigate" class="usermenu_search_input form-control"/>
|
<input type="text" placeholder="Searching ..." t-on-keydown="onSearchResultsNavigate" class="usermenu_search_input form-control"/>
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
@@ -143,6 +143,6 @@
|
|||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem id="sh_dynamic_action_action_menu" name="全局搜索配置" sequence="15" action="sh_dynamic_action_action" web_icon="sh_global_search,static/description/icon.png" groups="sh_global_search.group_global_search" />
|
<menuitem id="sh_dynamic_action_action_menu" name="全局搜索配置" sequence="15" action="sh_dynamic_action_action" web_icon="sf_global_search,static/description/icon.png" groups="sf_global_search.group_global_search" />
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'author': 'jikimo',
|
'author': 'jikimo',
|
||||||
'website': 'https://sf.cs.jikimo.com',
|
'website': 'https://sf.cs.jikimo.com',
|
||||||
'depends': ['sf_manufacturing', 'barcodes', ],
|
'depends': ['web', 'mail', 'sf_base', 'sf_manufacturing', 'barcodes', ],
|
||||||
'data': [
|
'data': [
|
||||||
# 定义权限组放在最上面
|
# 定义权限组放在最上面
|
||||||
# 权限组
|
# 权限组
|
||||||
@@ -31,13 +31,15 @@
|
|||||||
'views/delivery_record.xml',
|
'views/delivery_record.xml',
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'assets': {
|
'assets': {
|
||||||
'web.assets_backend': [
|
'web.assets_backend': [
|
||||||
'sf_machine_connect/static/src/js/*'
|
'sf_machine_connect/static/src/xml/barcode_button.xml',
|
||||||
|
'sf_machine_connect/static/src/js/barcode_button.js',
|
||||||
|
'sf_machine_connect/static/src/css/barcode_button.css',
|
||||||
],
|
],
|
||||||
|
|
||||||
},
|
},
|
||||||
'license': 'LGPL-3',
|
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': True,
|
'application': True,
|
||||||
# 'auto_install': False,
|
# 'auto_install': False,
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ class Machine_ftp(models.Model):
|
|||||||
machine_system_time = fields.Char('机床系统时间')
|
machine_system_time = fields.Char('机床系统时间')
|
||||||
machine_alarm_msg = fields.Char('机床系统报警')
|
machine_alarm_msg = fields.Char('机床系统报警')
|
||||||
|
|
||||||
|
|
||||||
# 刀位配置
|
# 刀位配置
|
||||||
tool_num1 = fields.Char('刀位1')
|
tool_num1 = fields.Char('刀位1')
|
||||||
tool_num2 = fields.Char('刀位2')
|
tool_num2 = fields.Char('刀位2')
|
||||||
@@ -511,7 +510,9 @@ class WorkCenterBarcode(models.Model):
|
|||||||
workorder_obj_target = self.env['mrp.workorder'].sudo().search([('tray_code', '=', barcode)])
|
workorder_obj_target = self.env['mrp.workorder'].sudo().search([('tray_code', '=', barcode)])
|
||||||
workorder_obj_current = self.env['mrp.workorder'].sudo().search([('id', '=', kwargs['current_id'])])
|
workorder_obj_current = self.env['mrp.workorder'].sudo().search([('id', '=', kwargs['current_id'])])
|
||||||
# workorder_cnc = self.env['mrp.workorder'].sudo().search(['&', ('production_id', '=', workorder_obj.production_id.id), ('name', '=', 'CNC加工')])
|
# workorder_cnc = self.env['mrp.workorder'].sudo().search(['&', ('production_id', '=', workorder_obj.production_id.id), ('name', '=', 'CNC加工')])
|
||||||
workorder_cnc = self.env['mrp.workorder'].sudo().search(['&', ('production_id', '=', workorder_obj_target.production_id.id), ('name', '=', workorder_obj_current.name)])
|
workorder_cnc = self.env['mrp.workorder'].sudo().search(
|
||||||
|
['&', ('production_id', '=', workorder_obj_target.production_id.id),
|
||||||
|
('name', '=', workorder_obj_current.name)])
|
||||||
print('222222222222222222222222')
|
print('222222222222222222222222')
|
||||||
if workorder_obj_target:
|
if workorder_obj_target:
|
||||||
print(workorder_obj_target)
|
print(workorder_obj_target)
|
||||||
@@ -526,7 +527,8 @@ class WorkCenterBarcode(models.Model):
|
|||||||
'view_id': request.env.ref('mrp.mrp_production_workorder_form_view_inherit').id,
|
'view_id': request.env.ref('mrp.mrp_production_workorder_form_view_inherit').id,
|
||||||
'res_id': workorder_cnc.id,
|
'res_id': workorder_cnc.id,
|
||||||
'target': 'current',
|
'target': 'current',
|
||||||
'context': {'id': workorder_obj_target.id},
|
'context': {'id': workorder_obj_target.id,
|
||||||
|
'clear_breadcrumbs': True, },
|
||||||
# 'flags': {'initial_mode': 'edit'},
|
# 'flags': {'initial_mode': 'edit'},
|
||||||
}
|
}
|
||||||
action = {'result': action, 'error': '返回错误'}
|
action = {'result': action, 'error': '返回错误'}
|
||||||
@@ -577,3 +579,4 @@ class DeliveryRecord(models.Model):
|
|||||||
# return super().create(values)
|
# return super().create(values)
|
||||||
# except:
|
# except:
|
||||||
# raise Exception('b_purchase_order.py:create()')
|
# raise Exception('b_purchase_order.py:create()')
|
||||||
|
|
||||||
|
|||||||
4
sf_machine_connect/static/src/css/barcode_button.css
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.barcode_button {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
126
sf_machine_connect/static/src/js/barcode_button.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import { browser } from "@web/core/browser/browser";
|
||||||
|
import { Dialog } from "@web/core/dialog/dialog";
|
||||||
|
import { _lt } from "@web/core/l10n/translation";
|
||||||
|
import { useChildRef, useOwnedDialogs, useService } from "@web/core/utils/hooks";
|
||||||
|
import { sprintf } from "@web/core/utils/strings";
|
||||||
|
import { isMobileOS } from "@web/core/browser/feature_detection";
|
||||||
|
import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner";
|
||||||
|
const { useRef } = owl;
|
||||||
|
const {xml, Component} = owl;
|
||||||
|
import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
||||||
|
import {registry} from "@web/core/registry";
|
||||||
|
import {useInputField} from "@web/views/fields/input_field_hook";
|
||||||
|
|
||||||
|
export class CodeField extends Component {
|
||||||
|
setup() {
|
||||||
|
console.log('CodeField created')
|
||||||
|
console.log('this',this)
|
||||||
|
console.log('this.props',this.props)
|
||||||
|
console.log('this.props.record',this.props.value)
|
||||||
|
useInputField({
|
||||||
|
getValue: () => this.props.value,
|
||||||
|
refName: "scan_code",
|
||||||
|
});
|
||||||
|
console.log('我是setup1')
|
||||||
|
super.setup();
|
||||||
|
this.orm = this.env.services.orm;
|
||||||
|
this.record = this.props.record;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onBarcodeBtnClick() {
|
||||||
|
const barcode = await BarcodeScanner.scanBarcode();
|
||||||
|
if (barcode) {
|
||||||
|
await this.onBarcodeScanned(barcode);
|
||||||
|
if ("vibrate" in browser.navigator) {
|
||||||
|
browser.navigator.vibrate(100);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.notification.add(this.env._t("Please, scan again !"), {
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async search(barcode) {
|
||||||
|
// alert('我是search')
|
||||||
|
const domain = [["code", "=", barcode]];
|
||||||
|
console.log(domain)
|
||||||
|
const fields = ["id", "code", "name", "state"];
|
||||||
|
console.log(fields)
|
||||||
|
const results = await this.orm.call("sf.tray", "search_read", [domain, fields]);
|
||||||
|
const values = await this.orm.call("sf.tray", "search_read", [domain]);
|
||||||
|
console.log(results)
|
||||||
|
return results.map((result) => {
|
||||||
|
return {
|
||||||
|
id: result.id,
|
||||||
|
code: result.code,
|
||||||
|
name: result.name,
|
||||||
|
state: result.state,
|
||||||
|
values: values,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async onBarcodeScanned(barcode) {
|
||||||
|
const results = await this.search(barcode);
|
||||||
|
console.log(results)
|
||||||
|
const records = results.filter((r) => !!r.id);
|
||||||
|
console.log(records)
|
||||||
|
if (records.length === 1) {
|
||||||
|
if (records[0].state === '空闲') {
|
||||||
|
console.log('currentModel',this)
|
||||||
|
console.log('this.record.data',this.record.data)
|
||||||
|
console.log('this.record.data.id', this.record.data.id)
|
||||||
|
const workorder = await this.orm.call('mrp.workorder', 'read', [this.record.data.id]);
|
||||||
|
console.log('workorder', workorder[0])
|
||||||
|
const updatedRecord = await this.orm.call("sf.tray", "write", [
|
||||||
|
[records[0].id],
|
||||||
|
{
|
||||||
|
state: "占用",
|
||||||
|
workorder_id: workorder[0].id,
|
||||||
|
production_id: workorder[0].product_id[0],
|
||||||
|
// workorder_id: workorder.id,
|
||||||
|
}]);
|
||||||
|
console.log(workorder[0].routing_type);
|
||||||
|
console.log(workorder[0].production_id);
|
||||||
|
// const productionIDS = await this.orm.call('mrp.production', 'search', [[['id', '=', workorder[0].production_id[0]]]]);
|
||||||
|
const productionIDS = await this.orm.call('mrp.workorder', 'search', [[["production_id", "=", workorder[0].production_id[0]]]]);
|
||||||
|
console.log('prooooooo', productionIDS);
|
||||||
|
console.log('values', records[0].values[0]);
|
||||||
|
productionIDS.forEach(async (data) => {
|
||||||
|
// 处理每一个数据
|
||||||
|
console.log(data);
|
||||||
|
const updatetrayRecord = await this.orm.call("mrp.workorder", "write", [
|
||||||
|
[data],
|
||||||
|
{
|
||||||
|
tray_id: records[0].values[0].id,
|
||||||
|
// tray_id: false,
|
||||||
|
}]);
|
||||||
|
console.log(updatetrayRecord)
|
||||||
|
});
|
||||||
|
this.props.update(records[0].code, records[0].tray_id);
|
||||||
|
location.replace(location.href)
|
||||||
|
// location.reload()
|
||||||
|
} else {
|
||||||
|
if (records[0].state === '占用') {
|
||||||
|
console.log('此托盘已占用,请检查')
|
||||||
|
alert('此托盘已占用,请检查')
|
||||||
|
} else {
|
||||||
|
console.log('此托盘已损坏,请登记')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const searchInput = this.autocompleteContainerRef.el.querySelector("input");
|
||||||
|
searchInput.value = barcode;
|
||||||
|
searchInput.dispatchEvent(new Event("input"));
|
||||||
|
if (this.env.isSmall) {
|
||||||
|
searchInput.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CodeField.template = 'sf_machine_connect.CodeField'
|
||||||
|
// Register the field in the registry
|
||||||
|
CodeField.props = standardFieldProps;
|
||||||
|
registry.category("fields").add("code", CodeField);
|
||||||
51
sf_machine_connect/static/src/js/barcode_form.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
odoo.define('my_module.barcode_handler', function (require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var core = require('web.core');
|
||||||
|
var registry = require('web.field_registry');
|
||||||
|
var session = require('web.session');
|
||||||
|
var FieldChar = require('web.basic_fields').FieldChar;
|
||||||
|
|
||||||
|
var _t = core._t;
|
||||||
|
|
||||||
|
var BarcodeHandlerField = FieldChar.extend({
|
||||||
|
init: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this.scanInProgress = false;
|
||||||
|
},
|
||||||
|
willStart: function () {
|
||||||
|
return this._super.apply(this, arguments).then(() => {
|
||||||
|
var barcode = this.call('barcode', 'get_barcode');
|
||||||
|
if (barcode) {
|
||||||
|
this._onBarcodeScanned(barcode);
|
||||||
|
}
|
||||||
|
this.call('barcode', 'start_listening');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroy: function () {
|
||||||
|
this.call('barcode', 'stop_listening');
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
_onBarcodeScanned: function (barcode) {
|
||||||
|
if (this.scanInProgress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.scanInProgress = true;
|
||||||
|
var self = this;
|
||||||
|
session.rpc('/mrp_barcode/scan_to_open_report_from_form', { barcode: barcode }).then(function (result) {
|
||||||
|
self.scanInProgress = false;
|
||||||
|
self.$el.val(result);
|
||||||
|
self.trigger_up('field_changed', {
|
||||||
|
dataPointID: self.dataPointID,
|
||||||
|
changes: { value: result },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.add('barcode_handlerr', BarcodeHandlerField);
|
||||||
|
|
||||||
|
return {
|
||||||
|
BarcodeHandlerField: BarcodeHandlerField,
|
||||||
|
};
|
||||||
|
});
|
||||||
77
sf_machine_connect/static/src/js/barcode_handler_field.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
||||||
|
import { useBus, useService } from "@web/core/utils/hooks";
|
||||||
|
const { Component, xml } = owl;
|
||||||
|
|
||||||
|
|
||||||
|
export class BarcodeHandlerField extends Component {
|
||||||
|
setup() {
|
||||||
|
console.log('99999999111');
|
||||||
|
this.actionService = useService("action")
|
||||||
|
console.log(this.actionService)
|
||||||
|
|
||||||
|
const barcode = useService("barcode");
|
||||||
|
// this.rpc = useService("rpc");
|
||||||
|
// useBus(barcode.bus, "barcode_scanned", this.onBarcodeScanned.bind(this));
|
||||||
|
useBus(barcode.bus, "barcode_scanned", this.onBarcodeScanned.bind(this));
|
||||||
|
}
|
||||||
|
async _rpc(params) {
|
||||||
|
// const { data } = await this.env.services.rpc('/web/dataset/call_kw', params);
|
||||||
|
const response = await this.env.services.rpc('/web/dataset/call_kw', params);
|
||||||
|
console.log('response', response);
|
||||||
|
console.log('response.result', response.result);
|
||||||
|
|
||||||
|
// return response
|
||||||
|
const responseObject = JSON.parse(response)
|
||||||
|
return responseObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onBarcodeScanned(event) {
|
||||||
|
const { barcode } = event.detail;
|
||||||
|
this.props.update(barcode);
|
||||||
|
// const actionService = useService("action");
|
||||||
|
// const productId = 12345
|
||||||
|
console.log('111222222222211111');
|
||||||
|
|
||||||
|
// 根据条形码获取相关数据,例如产品ID
|
||||||
|
const response = await this._rpc({
|
||||||
|
model: 'mrp.workorder',
|
||||||
|
method: 'get_product_id_by_barcode',
|
||||||
|
args: [barcode],
|
||||||
|
kwargs:{},
|
||||||
|
});
|
||||||
|
// console.log(productId.result)
|
||||||
|
if (response.result) {
|
||||||
|
const action = response.result;
|
||||||
|
console.log(action)
|
||||||
|
console.log('11111111111111111111111111111111111');
|
||||||
|
// 通过产品ID执行操作并跳转到表单视图
|
||||||
|
// await this.actionService.doAction({
|
||||||
|
// // type: 'ir.actions.act_window',
|
||||||
|
// // res_model: 'product.product',
|
||||||
|
// // res_id: productId,
|
||||||
|
// // views: [[false, 'form']],
|
||||||
|
// // target: 'current',
|
||||||
|
// 'name': '工单',
|
||||||
|
// 'type': 'ir.actions.act_window',
|
||||||
|
// 'views': [[false, 'form']],
|
||||||
|
// 'view_mode': 'form',
|
||||||
|
// 'res_model': 'mrp.workorder',
|
||||||
|
// 'view_id': 918,
|
||||||
|
// 'res_id': 1023,
|
||||||
|
// 'target': 'current',
|
||||||
|
// });
|
||||||
|
await this.actionService.doAction(response.result);
|
||||||
|
} else {
|
||||||
|
console.error("Barcode not found or RPC call failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BarcodeHandlerField.template = xml``;
|
||||||
|
BarcodeHandlerField.props = { ...standardFieldProps };
|
||||||
|
|
||||||
|
registry.category("fields").add("barcode_handlerrr", BarcodeHandlerField);
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
// /** @odoo-module **/
|
|
||||||
//
|
|
||||||
// import { browser } from "@web/core/browser/browser";
|
|
||||||
// import { Dialog } from "@web/core/dialog/dialog";
|
|
||||||
// import { _lt } from "@web/core/l10n/translation";
|
|
||||||
// import { useChildRef, useOwnedDialogs, useService } from "@web/core/utils/hooks";
|
|
||||||
// import { sprintf } from "@web/core/utils/strings";
|
|
||||||
// import { isMobileOS } from "@web/core/browser/feature_detection";
|
|
||||||
// import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner";
|
|
||||||
//
|
|
||||||
// const {xml, Component} = owl;
|
|
||||||
// import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
|
||||||
// // Import the registry
|
|
||||||
// import {registry} from "@web/core/registry";
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// export class CodeField extends Component {
|
|
||||||
// setup() {
|
|
||||||
// super.setup();
|
|
||||||
// }
|
|
||||||
// async onBarcodeBtnClick() {
|
|
||||||
// const barcode = await BarcodeScanner.scanBarcode();
|
|
||||||
// if (barcode) {
|
|
||||||
// await this.onBarcodeScanned(barcode);
|
|
||||||
// if ("vibrate" in browser.navigator) {
|
|
||||||
// browser.navigator.vibrate(100);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// this.notification.add(this.env._t("Please, scan again !"), {
|
|
||||||
// type: "warning",
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// async search(barcode) {
|
|
||||||
// const results = await this.orm.call("sf.tray", "name_search", [code], {
|
|
||||||
// name: barcode,
|
|
||||||
// args: this.getDomain(),
|
|
||||||
// operator: "ilike",
|
|
||||||
// limit: 2, // If one result we set directly and if more than one we use normal flow so no need to search more
|
|
||||||
// context: this.context,
|
|
||||||
// });
|
|
||||||
// return results.map((result) => {
|
|
||||||
// const [id, displayName] = result;
|
|
||||||
// return {
|
|
||||||
// id,
|
|
||||||
// name: displayName,
|
|
||||||
// };
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// async onBarcodeScanned(barcode) {
|
|
||||||
// const results = await this.search(barcode);
|
|
||||||
// const records = results.filter((r) => !!r.id);
|
|
||||||
// if (records.length === 1) {
|
|
||||||
// this.update([{ id: records[0].id, name: records[0].name }]);
|
|
||||||
// } else {
|
|
||||||
// const searchInput = this.autocompleteContainerRef.el.querySelector("input");
|
|
||||||
// searchInput.value = barcode;
|
|
||||||
// searchInput.dispatchEvent(new Event("input"));
|
|
||||||
// if (this.env.isSmall) {
|
|
||||||
// searchInput.click();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// CodeField.template = xml`
|
|
||||||
// <button
|
|
||||||
// t-on-click="onBarcodeBtnClick"
|
|
||||||
// type="button"
|
|
||||||
// class="btn ms-3 o_barcode"
|
|
||||||
// tabindex="-1"
|
|
||||||
// draggable="false"
|
|
||||||
// aria-label="Scan barcode"
|
|
||||||
// title="Scan barcode"
|
|
||||||
// data-tooltip="Scan barcode"
|
|
||||||
// />
|
|
||||||
// `;
|
|
||||||
// // CodeField.template = 'sf_machine_connect.CodeField';
|
|
||||||
// CodeField.props = standardFieldProps;
|
|
||||||
//
|
|
||||||
// // Add the field to the correct category
|
|
||||||
// registry.category("fields").add("code", CodeField);
|
|
||||||
/** @odoo-module **/
|
|
||||||
|
|
||||||
import { browser } from "@web/core/browser/browser";
|
|
||||||
import { Dialog } from "@web/core/dialog/dialog";
|
|
||||||
import { _lt } from "@web/core/l10n/translation";
|
|
||||||
import { useChildRef, useOwnedDialogs, useService } from "@web/core/utils/hooks";
|
|
||||||
import { sprintf } from "@web/core/utils/strings";
|
|
||||||
import { isMobileOS } from "@web/core/browser/feature_detection";
|
|
||||||
import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner";
|
|
||||||
|
|
||||||
const {xml, Component} = owl;
|
|
||||||
import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
|
||||||
// Import the registry
|
|
||||||
import {registry} from "@web/core/registry";
|
|
||||||
|
|
||||||
|
|
||||||
export class CodeField extends Component {
|
|
||||||
setup() {
|
|
||||||
super.setup();
|
|
||||||
this.orm = this.env.services.orm;
|
|
||||||
this.record = this.props.record;
|
|
||||||
}
|
|
||||||
async onBarcodeBtnClick() {
|
|
||||||
// console.log(BarcodeScanner)
|
|
||||||
const barcode = await BarcodeScanner.scanBarcode();
|
|
||||||
// console.log(typeof barcode)
|
|
||||||
// alert(barcode)
|
|
||||||
|
|
||||||
if (barcode) {
|
|
||||||
// console.log("存在")
|
|
||||||
// alert('存在')
|
|
||||||
|
|
||||||
await this.onBarcodeScanned(barcode);
|
|
||||||
if ("vibrate" in browser.navigator) {
|
|
||||||
browser.navigator.vibrate(100);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// console.log("不存在")
|
|
||||||
// alert('不存在')
|
|
||||||
this.notification.add(this.env._t("Please, scan again !"), {
|
|
||||||
type: "warning",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async search(barcode) {
|
|
||||||
alert('我是search')
|
|
||||||
const domain = [["code", "=", barcode]];
|
|
||||||
// const domain = [];
|
|
||||||
console.log(domain)
|
|
||||||
alert('走到这里了')
|
|
||||||
const fields = ["id", "code", "name", "state"];
|
|
||||||
console.log(fields)
|
|
||||||
alert('走到这里了1')
|
|
||||||
const results = await this.orm.call("sf.tray", "search_read", [domain, fields]);
|
|
||||||
const values = await this.orm.call("sf.tray", "search_read", [domain]);
|
|
||||||
console.log(results)
|
|
||||||
alert('走到这里了2')
|
|
||||||
return results.map((result) => {
|
|
||||||
return {
|
|
||||||
id: result.id,
|
|
||||||
code: result.code,
|
|
||||||
name: result.name,
|
|
||||||
state: result.state,
|
|
||||||
values: values,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async onBarcodeScanned(barcode) {
|
|
||||||
// alert('我是ONbarcodeScanned')
|
|
||||||
const results = await this.search(barcode);
|
|
||||||
console.log(results)
|
|
||||||
const records = results.filter((r) => !!r.id);
|
|
||||||
console.log(records)
|
|
||||||
if (records.length === 1) {
|
|
||||||
if (records[0].state === '空闲') {
|
|
||||||
// const currentModel = this.env.models['mrp.workorder'];
|
|
||||||
console.log('currentModel',this)
|
|
||||||
console.log('this.record.data',this.record.data)
|
|
||||||
// const recordID = this.controllerParams.recordID;
|
|
||||||
// console.log('当前页面记录 ID:', recordID);
|
|
||||||
// console.log('this.record',this.record.id)
|
|
||||||
// console.log('this.record',this.controllerParams.recordID)
|
|
||||||
// const workorder = await this.orm.call('mrp.workorder', 'read', [this.record.data.id, ['id']]);
|
|
||||||
console.log('this.record.data.id', this.record.data.id)
|
|
||||||
const workorder = await this.orm.call('mrp.workorder', 'read', [this.record.data.id]);
|
|
||||||
console.log('workorder', workorder[0])
|
|
||||||
const updatedRecord = await this.orm.call("sf.tray", "write", [
|
|
||||||
[records[0].id],
|
|
||||||
{
|
|
||||||
// state: "占用",
|
|
||||||
workorder_id: workorder[0].id,
|
|
||||||
production_id: workorder[0].product_id[0],
|
|
||||||
// workorder_id: workorder.id,
|
|
||||||
}]);
|
|
||||||
console.log(workorder[0].routing_type);
|
|
||||||
console.log(workorder[0].production_id);
|
|
||||||
// const productionIDS = await this.orm.call('mrp.production', 'search', [[['id', '=', workorder[0].production_id[0]]]]);
|
|
||||||
const productionIDS = await this.orm.call('mrp.workorder', 'search', [[["production_id", "=", workorder[0].production_id[0]]]]);
|
|
||||||
console.log('prooooooo', productionIDS);
|
|
||||||
console.log('values', records[0].values[0]);
|
|
||||||
productionIDS.forEach(async (data) => {
|
|
||||||
// 处理每一个数据
|
|
||||||
console.log(data);
|
|
||||||
const updatetrayRecord = await this.orm.call("mrp.workorder", "write", [
|
|
||||||
[data],
|
|
||||||
{
|
|
||||||
tray_id: records[0].values[0].id,
|
|
||||||
// tray_id: false,
|
|
||||||
}]);
|
|
||||||
console.log(updatetrayRecord)
|
|
||||||
});
|
|
||||||
// this.trigger_up('reload')
|
|
||||||
// this.props.update(records[0].code, records[0].values);
|
|
||||||
this.props.update(records[0].code, records[0].tray_id);
|
|
||||||
// this.trigger_up('button_clicked', {
|
|
||||||
// attrs: {
|
|
||||||
// name: 'save',
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// this.do_action({
|
|
||||||
// 'type': 'ir.actions.act_window',
|
|
||||||
// 'res_model': 'mrp.workorder',
|
|
||||||
// 'view_mode': 'form',
|
|
||||||
// 'view_type': 'form',
|
|
||||||
// 'res_id': workorder[0].id,
|
|
||||||
// 'target': 'current',
|
|
||||||
// })
|
|
||||||
} else {
|
|
||||||
if (records[0].state === '占用') {
|
|
||||||
console.log('此托盘已占用,请检查')
|
|
||||||
alert('此托盘已占用,请检查')
|
|
||||||
} else {
|
|
||||||
console.log('此托盘已损坏,请登记')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
const searchInput = this.autocompleteContainerRef.el.querySelector("input");
|
|
||||||
searchInput.value = barcode;
|
|
||||||
searchInput.dispatchEvent(new Event("input"));
|
|
||||||
if (this.env.isSmall) {
|
|
||||||
searchInput.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeField.template = xml`
|
|
||||||
<div class="o_field_widget o_input o_barcode_field">
|
|
||||||
<!-- <input class="o_input" type="text" t-att-value="value"/>-->
|
|
||||||
<div class="o_input_container">
|
|
||||||
<t t-raw="widget"/>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
t-on-click="onBarcodeBtnClick"
|
|
||||||
type="button"
|
|
||||||
class="sf_button o_barcode btn ms-3 o_barcode"
|
|
||||||
tabindex="-1"
|
|
||||||
draggable="false"
|
|
||||||
aria-label="Scan barcode"
|
|
||||||
title="Scan barcode"
|
|
||||||
data-tooltip="Scan barcode"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
// CodeField.template = 'sf_machine_connect.CodeField';
|
|
||||||
CodeField.props = standardFieldProps;
|
|
||||||
|
|
||||||
// Add the field to the correct category
|
|
||||||
registry.category("fields").add("code", CodeField);
|
|
||||||
|
|
||||||
// style="position: relative; left: 200px;"
|
|
||||||
19
sf_machine_connect/static/src/xml/barcode_button.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
<t t-name="sf_machine_connect.CodeField" owl="1">
|
||||||
|
<div>
|
||||||
|
<input t-ref="scan_code" t-att-id="props.id" t-att-type="props.inputType" t-att-placeholder="props.placeholder" class="barcode_button o_input"/>
|
||||||
|
<button
|
||||||
|
t-on-click="onBarcodeBtnClick"
|
||||||
|
type="button"
|
||||||
|
class="btn ms-3 o_barcode"
|
||||||
|
tabindex="-1"
|
||||||
|
draggable="false"
|
||||||
|
aria-label="Scan barcode"
|
||||||
|
title="Scan barcode"
|
||||||
|
data-tooltip="Scan barcode"
|
||||||
|
style="position: absolute !important;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</templates>
|
||||||
@@ -15,6 +15,10 @@
|
|||||||
<!-- invisible="1" -->
|
<!-- invisible="1" -->
|
||||||
<field name="_barcode_scanned" widget="barcode_handler" string="扫码"/>
|
<field name="_barcode_scanned" widget="barcode_handler" string="扫码"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//page//field[@name='tray_code']" position="replace">
|
||||||
|
<field name="tray_code" widget="code"/>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||