owl繼承
1 /** @odoo-module */ 2 3 import { AbstractAwaitablePopup } from "@point_of_sale/app/popup/abstract_awaitable_popup"; 4 import { _t } from "@web/core/l10n/translation"; 5 import { onMounted, useRef, useState, onWillDestroy } from "@odoo/owl"; 6 import { Orderline } from "@point_of_sale/app/generic_components/orderline/orderline"; 7 import { OrderWidget } from "@point_of_sale/app/generic_components/order_widget/order_widget"; 8 import { omit } from "@web/core/utils/objects"; 9 import { useService } from "@web/core/utils/hooks"; 10 import { usePos } from "@point_of_sale/app/store/pos_hook"; 11 import { makeEnv } from "@web/env"; 12 13 14 // IMPROVEMENT: This code is very similar to TextInputPopup. 15 // Combining them would reduce the code. 16 export class FRIDPopup extends AbstractAwaitablePopup { 17 static template = "esale_frid.FRIDPopup"; 18 static components = { 19 Orderline, 20 OrderWidget, 21 }; 22 23 static defaultProps = { 24 confirmText: _t("OK"), 25 cancelText: _t("Cancel"), 26 clearText: _t("Clear All"), 27 title: "RFID Reading", 28 }; 29 30 static props = { 31 data: Object, 32 formatCurrency: Function, 33 }; 34 35 get totalQty() { 36 let sum = 0.0 37 this.props.data.forEach(function(item) { 38 sum += parseInt(item.qty); 39 }); 40 return sum.toFixed(2); 41 } 42 43 /** 44 * @param {Object} props 45 * @param {string} props.startingValue 46 */ 47 setup() { // 鉤子,第一次安裝 48 super.setup(); 49 this.orm = useService("orm"); // 獲取orm全域性狀態 50 this.pos = usePos(); // 獲取pos全域性狀態 51 const env = makeEnv(); // 語言、登入資訊之類 52 53 console.log('這裡是pos的配置資訊:',this.pos.config) 54 55 56 onWillDestroy(this.onWillDestroy) // 銷燬鉤子 57 onMounted(this.onMounted); // 掛載鉤子 58 } 59 60 61 async addProductData (epc_barcode) { // 普通方法 62 if (this.epcList.has(epc_barcode)) { 63 return 64 } 65 this.epcList.add(epc_barcode) 66 let barcode = this.decodeEPC(epc_barcode) 67 barcode = barcode.barcode 68 console.log("barcode:", barcode) 69 try { 70 const limit = 30; 71 const ProductIds = await this.orm.call( 72 "product.product", 73 "search", 74 [ 75 [ 76 ["barcode", "=", barcode], 77 ], 78 ], 79 { 80 offset: 0, 81 limit: limit, 82 } 83 ); 84 console.log("ProductIds:",ProductIds) 85 if (ProductIds.length > 0){ 86 const product = await this.pos.db.get_product_by_id(ProductIds[0]) 87 console.log("product:",product) 88 if (product) { 89 let pdata = { 90 'attributes':[], 91 'discount': '0', 92 'pack_lot_lines': false, 93 'price': product.lst_price.toFixed(2), 94 'price_without_discount': product.lst_price.toFixed(2), 95 'productName': product.display_name, //product.description_sale, 96 'product_id': ProductIds[0], //product.product_tmpl_id, 97 'qty': "1.00", 98 'unit': product.uom_id[1], 99 'unitPrice':product.lst_price.toFixed(2), 100 'noDel': true, 101 'epc_barcode': epc_barcode, 102 "product": product, 103 } 104 console.log("pdata:",pdata) 105 this.props.data.push(pdata) 106 107 } 108 } 109 110 } catch (error) { 111 if (error instanceof ConnectionLostError || error instanceof ConnectionAbortedError) { 112 return this.popup.add(OfflineErrorPopup, { 113 title: _t("Network Error"), 114 body: _t( 115 "Product is not loaded. Tried loading the product from the server but there is a network error." 116 ), 117 }); 118 } else { 119 throw error; 120 } 121 } 122 123 }; 124 125 onMounted() { 126 // this.inputRef.el.focus() 127 this.epcList = new Set(); 128 this.heartbeatTimer = null; 129 this.connectWebSocket(this.pos.config.rfid_url, this.pos.config.rfid_client_id,this.pos.config.rfid_room,this.pos.config.rfid_account,this.pos.config.rfid_devicename); 130 console.log('onMounted') 131 } 132 133 onWillDestroy(){ 134 clearInterval(this.heartbeatTimer); 135 this.stopRead() 136 this.socket.close(); 137 console.log('onWillDestroy') 138 } 139 140 getPayload() { 141 this.props.formatCurrency(this.props.data) 142 return ""; 143 } 144 145 }
web繼承
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!-- point_of_sale_template 是固定語法 --> 3 <template id="ClearItemIcon" inherit="point_of_sale_template" xml:space="preserve"> 4 <t t-inherit="point_of_sale.Orderline" t-inherit-mode="extension"> 5 <xpath expr="//div[hasclass('product-price')]" position="inside"> 6 <t t-if="!line.noDel"> 7 <i style="margin-left:6px;cursor:pointer;color:red;" id="clear_icon" class="fa fa-trash" t-on-click="clear_button_fun"/> 8 </t> 9 10 </xpath> 11 </t> 12 </template>
view繼承
1 <?xml version="1.0" encoding="utf-8"?> 2 <odoo> 3 <data> 4 5 <record id="rfid_pos_config_view_form_inherit" model="ir.ui.view"> 6 <field name="name">rfid.pos.config</field> 7 <field name="model">pos.config</field> 8 <field name="inherit_id" ref="point_of_sale.pos_config_view_form"/> 9 <field eval="9" name="priority"/> 10 <field name="arch" type="xml"> 11 <xpath expr="//div[@groups='base.group_system']" position="before"> 12 <group> 13 <group> 14 <field name="yourself_field" /> 15 16 </group> 17 <group> 18 19 </group> 20 </group> 21 22 </xpath> 23 </field> 24 </record> 25 </data> 26 </odoo>
注意,這三個資源在__manifest__.py中,view是配置到data中,owl和web是在assets中,如:
1 # -*- coding: utf-8 -*- 2 { 3 'depends': ['base', 'point_of_sale'], 4 'assets': { 5 'point_of_sale._assets_pos': [ 6 'esale_frid/static/src/**/*', 7 ], 8 }, 9 'data': [ 10 'views/pos_config_rfid.xml', 11 ], 12 13 }