Compare commits
4 Commits
feature/修改
...
feature/sf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b7f4c3f06 | ||
|
|
26de811174 | ||
|
|
d023848c70 | ||
|
|
a109c0fb39 |
@@ -10,9 +10,9 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['web', 'purchase', 'base_setup'],
|
||||
'depends': ['web'],
|
||||
'data': [
|
||||
'views/bye_odoo.xml',
|
||||
|
||||
],
|
||||
'demo': [
|
||||
],
|
||||
@@ -22,24 +22,11 @@
|
||||
],
|
||||
'web.assets_backend': [
|
||||
'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*',
|
||||
'jikimo_frontend/static/src/fields/Many2OneRadioField/*',
|
||||
# 移除odoo相关标识
|
||||
'jikimo_frontend/static/src/bye_odoo/*',
|
||||
'jikimo_frontend/static/src/scss/custom_style.scss',
|
||||
# 'jikimo_frontend/static/src/views/list_nums/list_nbCols.js',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums.xml',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums2.xml',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums3.xml',
|
||||
'jikimo_frontend/static/src/js/custom_form_status_indicator.js',
|
||||
'jikimo_frontend/static/src/js/custom_image_temp.js',
|
||||
'jikimo_frontend/static/src/scss/rowno_in_tree.scss',
|
||||
# 'jikimo_frontend/static/src/views/list_nums/list_render.xml',
|
||||
# 'jikimo_frontend/static/src/list/list_up_down_button.xml',
|
||||
# 'jikimo_frontend/static/src/list/custom_import.js',
|
||||
# 'jikimo_frontend/static/src/list/custom_width.js',
|
||||
'jikimo_frontend/static/src/views/list_nums/extent_purchase.xml',
|
||||
'jikimo_frontend/static/src/css/list_border_styles.css',
|
||||
|
||||
],
|
||||
|
||||
},
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="partner_demo_company" model="res.partner">
|
||||
<field name="name">JKM</field>
|
||||
<field name="street">B-25</field>
|
||||
<field name="city">USA</field>
|
||||
<!-- Use the correct reference or actual ID for the country -->
|
||||
<field name="country_id" ref="base.bd"/>
|
||||
<field name="zip">1229</field>
|
||||
<field name="phone">+8801-712901764</field>
|
||||
<field name="email">info@kolpolok.com</field>
|
||||
<field name="website">www.kolpoloktechnologies.com</field>
|
||||
</record>
|
||||
|
||||
<record id="demo_company" model="res.company">
|
||||
<field name="name">Custom</field>
|
||||
<field name="logo" type="base64" file="kolpolok_custom_title_and_favicon/static/src/img/favicon.ico"/>
|
||||
<field name="favicon" type="base64" file="kolpolok_custom_title_and_favicon/static/src/img/favicon.ico"/>
|
||||
<field name="partner_id" ref="partner_demo_company"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,16 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
import { UserMenu } from "@web/webclient/user_menu/user_menu";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { registry } from "@web/core/registry";
|
||||
const userMenuRegistry = registry.category("user_menuitems");
|
||||
|
||||
|
||||
patch(UserMenu.prototype, "legion_hide_odoo.UserMenu", {
|
||||
setup() {
|
||||
this._super.apply(this, arguments);
|
||||
userMenuRegistry.remove("documentation");
|
||||
userMenuRegistry.remove("support");
|
||||
userMenuRegistry.remove("odoo_account");
|
||||
},
|
||||
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { WebClient } from "@web/webclient/webclient";
|
||||
import { patch } from "web.utils";
|
||||
|
||||
patch(WebClient.prototype, "kolpolok_custom_title_and_favicon.WebClient", {
|
||||
setup() {
|
||||
this._super();
|
||||
this.title.setParts({ zopenerp: "JIKIMO" });
|
||||
},
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
.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){
|
||||
border:1px solid #dee2e6 !important;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.many2one_radio_field {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { RadioField } from "@web/views/fields/radio/radio_field"; // 导入单选按钮组件
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
export class Many2OneRadioField extends RadioField {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
// 例如,你可以重写setup方法来添加一些事件监听器或者初始化一些变量
|
||||
setup() {
|
||||
super.setup(); // 调用父类的setup方法
|
||||
// 你自己的代码
|
||||
}
|
||||
|
||||
onImageClick(event) {
|
||||
// 放大图片逻辑
|
||||
// 获取图片元素
|
||||
const img = event.target;
|
||||
const close = img.nextSibling;
|
||||
// 实现放大图片逻辑
|
||||
// 比如使用 CSS 放大
|
||||
img.parentElement.classList.add('zoomed');
|
||||
close.classList.add('img_close');
|
||||
}
|
||||
|
||||
onCloseClick(event) {
|
||||
const close = event.target;
|
||||
const img = close.previousSibling;
|
||||
img.parentElement.classList.remove('zoomed');
|
||||
close.classList.remove('img_close');
|
||||
}
|
||||
|
||||
get items() {
|
||||
return Many2OneRadioField.getItems(this.props.name, this.props.record);
|
||||
}
|
||||
|
||||
static getItems(fieldName, record) {
|
||||
switch (record.fields[fieldName].type) {
|
||||
case "selection":
|
||||
return record.fields[fieldName].selection;
|
||||
case "many2one": {
|
||||
const value = record.preloadedData[fieldName] || [];
|
||||
return value.map((item) => [item.id, item.display_name, item.image]);
|
||||
}
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Many2OneRadioField.template = "jikimo_frontend.Many2OneRadioField";
|
||||
// MyCustomWidget.supportedTypes = ['many2many'];
|
||||
|
||||
registry.category("fields").add("many2one_radio", Many2OneRadioField);
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="jikimo_frontend.Many2OneRadioField" owl="1">
|
||||
<div
|
||||
role="radiogroup"
|
||||
t-attf-class="o_{{ props.orientation }}"
|
||||
t-att-aria-label="string"
|
||||
>
|
||||
<t t-foreach="items" t-as="item" t-key="item[0]">
|
||||
<div class="form-check o_radio_item many2one_radio_field" aria-atomic="true">
|
||||
<input
|
||||
type="radio"
|
||||
class="form-check-input o_radio_input"
|
||||
t-att-checked="item[0] === value"
|
||||
t-att-disabled="props.readonly"
|
||||
t-att-name="id"
|
||||
t-att-data-value="item[0]"
|
||||
t-att-data-index="item_index"
|
||||
t-att-id="`${id}_${item[0]}`"
|
||||
t-on-change="() => this.onChange(item)"
|
||||
/>
|
||||
<label class="form-check-label o_form_label" t-att-for="`${id}_${item[0]}`" t-esc="item[1]" />
|
||||
<div t-on-dblclick="onImageClick">
|
||||
<t>
|
||||
<img t-att-src="item[2]" width="50" height="50"/>
|
||||
<div class="close" t-on-click="onCloseClick">×</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -15,24 +15,23 @@ export class MyCustomWidget extends Many2ManyCheckboxesField {
|
||||
// 放大图片逻辑
|
||||
// 获取图片元素
|
||||
const img = event.target;
|
||||
const close = img.nextSibling;
|
||||
const close = img.nextSibling
|
||||
|
||||
// 实现放大图片逻辑
|
||||
// 比如使用 CSS 放大
|
||||
img.parentElement.classList.add('zoomed');
|
||||
close.classList.add('img_close');
|
||||
close.classList.add('img_close')
|
||||
}
|
||||
|
||||
onCloseClick(event) {
|
||||
const close = event.target;
|
||||
const img = close.previousSibling;
|
||||
img.parentElement.classList.remove('zoomed');
|
||||
close.classList.remove('img_close');
|
||||
const img = close.previousSibling
|
||||
img.parentElement.classList.remove('zoomed')
|
||||
close.classList.remove('img_close')
|
||||
}
|
||||
}
|
||||
|
||||
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget";
|
||||
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget"
|
||||
// MyCustomWidget.supportedTypes = ['many2many'];
|
||||
|
||||
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,210 +0,0 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
// import { Dialog } from "@web/core/dialog/dialog";
|
||||
import {_t} from "@web/core/l10n/translation";
|
||||
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
|
||||
import {Field} from "@web/views/fields/field";
|
||||
|
||||
var Dialog = require('web.Dialog');
|
||||
// var {patch} = require("web.utils") 这句话也行
|
||||
const filedRequiredList = {
|
||||
// 设备大模块
|
||||
'control_system_id': { multiple: false, noLabel: false },
|
||||
'workbench_L': { multiple: true, noLabel: false },
|
||||
'number_of_axles': { multiple: true, noLabel: false },
|
||||
'x_axis': { multiple: true, noLabel: false },
|
||||
'number_of_knife_library': { multiple: false, noLabel: false },
|
||||
'brand_id': { multiple: false, noLabel: false },
|
||||
'type_id': { multiple: false, noLabel: false },
|
||||
'taper_type_id': { multiple: false, noLabel: false },
|
||||
'eq_maintenance_id': { multiple: false, noLabel: false },
|
||||
'overhaul_id': { multiple: false, noLabel: false },
|
||||
'overhaul_period': { multiple: false, noLabel: false },
|
||||
'maintenance_equipment_category_id': { multiple: false, noLabel: false },
|
||||
'maintenance_type': { multiple: false, noLabel: false },
|
||||
|
||||
// 销售大模块
|
||||
'partner_id': { multiple: false, noLabel: false },
|
||||
'validity_date': { multiple: false, noLabel: false },
|
||||
'vat': { multiple: false, noLabel: false },
|
||||
'phone': { multiple: false, noLabel: false },
|
||||
'mobile': { multiple: false, noLabel: false },
|
||||
'email': { multiple: false, noLabel: false },
|
||||
'category_id': { multiple: false, noLabel: false },
|
||||
'radio_field_1_person': { multiple: false, noLabel: true },
|
||||
|
||||
// 采购大模块
|
||||
'date_order': { multiple: false, noLabel: false },
|
||||
'picking_type_id': { multiple: false, noLabel: false },
|
||||
|
||||
// 制造大模块
|
||||
'production_line_id': { multiple: false, noLabel: false },
|
||||
'date_approve': { multiple: false, noLabel: false },
|
||||
'date_planned_start': { multiple: false, noLabel: false },
|
||||
'date_planned_finished': { multiple: false, noLabel: false },
|
||||
}
|
||||
const tableRequiredList = [
|
||||
'product_template_id', 'product_uom_qty', 'price_unit','product_id','product_qty',
|
||||
'name', 'fault_type', 'maintenance_standards', 'Period'
|
||||
]
|
||||
|
||||
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
async _onDiscardChanges() {
|
||||
// var self = this;
|
||||
Dialog.confirm(this, _t("Are you sure you want to discard changes?"), {
|
||||
title: _t("Discard Changes"),
|
||||
|
||||
// confirm_callback: function () {
|
||||
// self.model.discardChanges(self.handle);
|
||||
// },
|
||||
});
|
||||
},
|
||||
|
||||
async discard() {
|
||||
// if (window.confirm("Are you sure you want to discard changes?")) {
|
||||
// await this.props.discard();
|
||||
// }
|
||||
// const result = await this._confirmDiscardChange();
|
||||
await this._confirmDiscardChange();
|
||||
await this.props.discard();
|
||||
},
|
||||
|
||||
_confirmDiscardChange() {
|
||||
var self = this;
|
||||
var def = new Promise(function (resolve, reject) {
|
||||
var message = _t("请确认是否要舍弃之前的更改?");
|
||||
var dialog = Dialog.confirm(self, message, {
|
||||
title: _t("Warning"),
|
||||
confirm_callback: resolve.bind(self, true),
|
||||
cancel_callback: reject,
|
||||
});
|
||||
dialog.on('closed', self, reject);
|
||||
});
|
||||
return def;
|
||||
},
|
||||
|
||||
}
|
||||
);
|
||||
patch(Field.prototype, 'jikimo_frontend.Field', {
|
||||
setup() {
|
||||
owl.onMounted(this.setRequired);
|
||||
return this._super(...arguments);
|
||||
},
|
||||
setRequired() {
|
||||
const id = this.props.id
|
||||
const isRequired = filedRequiredList[id]
|
||||
if(id == 'number_of_axles') {
|
||||
console.log(isRequired)
|
||||
}
|
||||
if(isRequired) {
|
||||
let dom;
|
||||
dom = $(`label[for=${id}]`)
|
||||
if(isRequired.multiple && dom.length > 1) {
|
||||
dom = dom.eq(-1)
|
||||
dom = dom.parent().parent().next().find('label')
|
||||
}
|
||||
if(isRequired.noLabel) {
|
||||
dom = dom.parent().parent()
|
||||
}
|
||||
let t = dom.html()
|
||||
t = '<i class="c* r" style="color: red;margin-left: -4px">*</i>' + t
|
||||
dom.html(t)
|
||||
}
|
||||
}
|
||||
})
|
||||
patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
|
||||
setup(){
|
||||
owl.onMounted(() => {
|
||||
this.activeElement = this.uiService.activeElement;
|
||||
this.setRequired()
|
||||
})
|
||||
return this._super(...arguments);
|
||||
},
|
||||
setRequired() {
|
||||
this.allColumns.forEach(_ => {
|
||||
if( tableRequiredList.indexOf(_.name) >= 0 ) {
|
||||
const dom = $(`th[data-name=${_.name}]`)
|
||||
dom.addClass('addRequired')
|
||||
}
|
||||
})
|
||||
try {
|
||||
const dom = this.tableRef.el
|
||||
if(dom ) {
|
||||
const tfoot = $(dom).children('tfoot')
|
||||
const tbooy = $(dom).children('tbody')
|
||||
if(tfoot.length) {
|
||||
const tfoot_tr = tfoot.children().eq(0)
|
||||
const tbody_tr = tbooy.children().eq(0)
|
||||
if(tfoot_tr.children().length < tbody_tr.children().length) {
|
||||
tfoot_tr.prepend('<td class="prepend">')
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$(function () {
|
||||
document.addEventListener('click', function () {
|
||||
const dom = $('.o_form_status_indicator_buttons ')
|
||||
if (dom) {
|
||||
const dom1 = dom.children().eq(0)
|
||||
const dom2 = dom.children().eq(1)
|
||||
if (!dom1.text()) {
|
||||
dom1.append('保存')
|
||||
dom2.append('取消')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function customRequired() {
|
||||
let timer = null
|
||||
let timer_count = 0
|
||||
clearInterval(timer)
|
||||
timer = setInterval(() => {
|
||||
timer_count++
|
||||
const dom = $('.custom_required')
|
||||
let tableDom = $('.table_custom_required')
|
||||
if (tableDom.length) {
|
||||
tableDom = tableDom.eq(0).parents('tr').children('.table_custom_required')
|
||||
tableDom.each(function () {
|
||||
const i = $(this).index()
|
||||
const requiredDom = $(this).parents('table').find('thead').find('th').eq(i).find('span').eq(0)
|
||||
const t = requiredDom.text().replace('*', '')
|
||||
requiredDom.html('<i style="color: red;margin-left: -4px">*</i>' + t)
|
||||
})
|
||||
clearInterval(timer)
|
||||
}
|
||||
if (dom.length) {
|
||||
dom.each(function () {
|
||||
const requiredDom = $(this).parent().prev().find('label')
|
||||
let t = requiredDom.html()
|
||||
if (t && t.indexOf('c*') < 0) {
|
||||
t = '<i class="c*" style="color: red;margin-left: -4px">*</i>' + t
|
||||
}
|
||||
requiredDom.html(t)
|
||||
})
|
||||
clearInterval(timer)
|
||||
}
|
||||
if (timer_count == 20) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
|
||||
var currentUrl = location.href
|
||||
const listenerUrl = setInterval(() => {
|
||||
const isChange = currentUrl != location.href
|
||||
if (isChange) {
|
||||
currentUrl = location.href
|
||||
customRequired()
|
||||
}
|
||||
}, 500)
|
||||
customRequired()
|
||||
})
|
||||
@@ -1,32 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
import { url } from "@web/core/utils/urls";
|
||||
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
|
||||
|
||||
patch(ImageField.prototype, 'jikimo_frontend/static/src/js/custom_image.js', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
getUrl(previewFieldName) {
|
||||
console.log('666666666666666666666666666666666')
|
||||
if (this.state.isValid && this.props.value) {
|
||||
if (1) {
|
||||
if (!this.rawCacheKey) {
|
||||
this.rawCacheKey = this.props.record.data.__last_update;
|
||||
}
|
||||
return url("/web/image", {
|
||||
model: this.props.record.resModel,
|
||||
id: this.props.record.resId,
|
||||
field: previewFieldName,
|
||||
unique: imageCacheKey(this.rawCacheKey),
|
||||
});
|
||||
} else {
|
||||
// Use magic-word technique for detecting image type
|
||||
const magic = fileTypeMagicWordMap[this.props.value[0]] || "png";
|
||||
return `data:image/${magic};base64,${this.props.value}`;
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1,45 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { url } from "@web/core/utils/urls";
|
||||
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
|
||||
import { isBinarySize } from "@web/core/utils/binary";
|
||||
export const fileTypeMagicWordMap = {
|
||||
"/": "jpg",
|
||||
R: "gif",
|
||||
i: "png",
|
||||
P: "svg+xml",
|
||||
};
|
||||
|
||||
const placeholder = "/web/static/img/placeholder.png";
|
||||
|
||||
export class CustomImageField extends ImageField {
|
||||
setup() {
|
||||
super.setup();
|
||||
// this.dialog = useService("dialog");
|
||||
}
|
||||
|
||||
getUrl(previewFieldName) {
|
||||
console.log('8888888888886666666666666666666')
|
||||
if (this.state.isValid && this.props.value) {
|
||||
if (isBinarySize(this.props.value) || this.props.value.length < 50) {
|
||||
if (!this.rawCacheKey) {
|
||||
this.rawCacheKey = this.props.record.data.__last_update;
|
||||
}
|
||||
return url("/web/image", {
|
||||
model: this.props.record.resModel,
|
||||
id: this.props.record.resId,
|
||||
field: previewFieldName,
|
||||
unique: imageCacheKey(this.rawCacheKey),
|
||||
});
|
||||
} else {
|
||||
// Use magic-word technique for detecting image type
|
||||
const magic = fileTypeMagicWordMap[this.props.value[0]] || "png";
|
||||
return `data:image/${magic};base64,${this.props.value}`;
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("fields").add("custom_image", CustomImageField);
|
||||
@@ -1,95 +0,0 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
|
||||
// var {patch} = require("web.utils") 这句话也行
|
||||
|
||||
patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
// The following code manipulates the DOM directly to avoid having to wait for a
|
||||
// render + patch which would occur on the next frame and cause flickering.
|
||||
freezeColumnWidths() {
|
||||
// console.log('ccccccccccccccccccccccccccc')
|
||||
if (!this.keepColumnWidths) {
|
||||
this.columnWidths = null;
|
||||
}
|
||||
|
||||
const table = this.tableRef.el;
|
||||
const headers = [...table.querySelectorAll("thead th:not(.o_list_actions_header)")];
|
||||
const column_num = headers.length;
|
||||
|
||||
if (!this.columnWidths || !this.columnWidths.length) {
|
||||
// no column widths to restore
|
||||
// Set table layout auto and remove inline style to make sure that css
|
||||
// rules apply (e.g. fixed width of record selector)
|
||||
table.style.tableLayout = "auto";
|
||||
headers.forEach((th) => {
|
||||
th.style.width = null;
|
||||
th.style.maxWidth = null;
|
||||
});
|
||||
|
||||
this.setDefaultColumnWidths(column_num);
|
||||
|
||||
// Squeeze the table by applying a max-width on largest columns to
|
||||
// ensure that it doesn't overflow
|
||||
this.columnWidths = this.computeColumnWidthsFromContent();
|
||||
table.style.tableLayout = "fixed";
|
||||
}
|
||||
headers.forEach((th, index) => {
|
||||
if (!th.style.width) {
|
||||
th.style.width = `${Math.floor(this.columnWidths[index])}px`;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setDefaultColumnWidths(column_num) {
|
||||
// const bbb = this.state.columns[0].name
|
||||
const widths = this.state.columns.map((col) =>
|
||||
this.calculateColumnWidth(col));
|
||||
// const sumOfRelativeWidths = (widths
|
||||
// .filter(({ type }) => type === "relative")
|
||||
// .reduce((sum, { value }) => sum + value, 0));
|
||||
|
||||
// 获取数组的最后一项
|
||||
const lastItem = widths[widths.length - 1];
|
||||
|
||||
// 复制最后一项
|
||||
const newItem = { ...lastItem };
|
||||
|
||||
// 将新的对象添加到数组的末尾
|
||||
widths.push(newItem);
|
||||
|
||||
// 判断销售的sequence
|
||||
// if (this.state.columns[0].name === "sequence") {
|
||||
// widths[1] = { type: "relative", value: 0.1 };
|
||||
// }
|
||||
|
||||
// 判断 this.state.columns 是否存在且长度大于零
|
||||
if (this.state.columns && this.state.columns.length > 0
|
||||
&& this.state.columns[0].name === "sequence") {
|
||||
widths[1] = { type: "relative", value: 0.1 };
|
||||
}
|
||||
|
||||
|
||||
// 1 because nth-child selectors are 1-indexed,
|
||||
// 2 when the first column contains
|
||||
// the checkboxes to select records.
|
||||
const columnOffset = this.hasSelectors ? 2 : 1;
|
||||
widths.forEach(({ type, value }, width) => {
|
||||
const headerEl = this.tableRef.el.querySelector(
|
||||
`th:nth-child(${width + columnOffset})`);
|
||||
if (type === "absolute") {
|
||||
if (this.isEmpty) {
|
||||
headerEl.style.width = value;
|
||||
} else {
|
||||
headerEl.style.minWidth = value;
|
||||
}
|
||||
} else if (type === "relative" && this.isEmpty) {
|
||||
headerEl.style.width = `${((value / column_num) * 100
|
||||
).toFixed(2)}%`;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates>
|
||||
<t t-name="list_up_down_button" t-inherit="web.ListView.Buttons" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//t[@t-if='nbTotal and !nbSelected and activeActions.exportXlsx and isExportEnable and !env.isSmall']" position="before">
|
||||
<!-- 新增的导入文件按钮 -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-upload o_list_import_file" data-tooltip="导入文件" aria-label="Import File" title="" t-on-click="onDirectImportData"/> -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-upload o_list_import_file" data-tooltip="导入文件" aria-label="Import File" title="" t-on-click="onDirectImportData"/> -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-download o_list_export_xlsx" data-tooltip="导出全部" aria-label="导出全部" t-on-click="onDirectExportData"/> -->
|
||||
<button type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导出全部" aria-label="导出全部" t-on-click="onDirectExportData">导出全部</button>
|
||||
<!-- <button type="button" t-component="base_import.ImportRecords" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据" t-on-click="importRecords">导入数据</button> -->
|
||||
<!-- <button type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据" t-on-click="importRecords">导入数据</button> -->
|
||||
<!-- <t t-component="base_import.ImportRecords"> -->
|
||||
<!-- <button t-on-click="importRecords" type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据">导入数据</button> -->
|
||||
<!-- </t> -->
|
||||
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-if='nbTotal and !nbSelected and activeActions.exportXlsx and isExportEnable and !env.isSmall']" position="replace">
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -8,16 +8,9 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div:has(.o_required_modifier) > label::before {
|
||||
content: '*' !important;
|
||||
color: red !important;
|
||||
padding: 0 4px !important;
|
||||
vertical-align: top !important;
|
||||
font-size: unset !important;
|
||||
}
|
||||
|
||||
|
||||
.my-image div {
|
||||
|
||||
width: 110px !important;
|
||||
height: 110px !important;
|
||||
}
|
||||
@@ -79,9 +72,9 @@ td.o_required_modifier {
|
||||
}
|
||||
|
||||
.oe_kanban_card.kanban_color_1 {
|
||||
background-color: #fff !important;
|
||||
background-color: #27FEA9 !important;
|
||||
opacity: 0.7;
|
||||
color: #777;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.oe_kanban_card.kanban_color_3 {
|
||||
@@ -135,7 +128,7 @@ td.o_required_modifier {
|
||||
.text-truncate {
|
||||
overflow: unset !important;
|
||||
text-overflow: unset !important;
|
||||
//white-space: nowrap!important;
|
||||
white-space: unset !important;
|
||||
}
|
||||
|
||||
.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) {
|
||||
@@ -205,8 +198,8 @@ div[class="o_content o_component_with_search_panel"] img[name="equipment_image"]
|
||||
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
position: absolute;
|
||||
//top: -52px;
|
||||
//left: -55px;
|
||||
top: -52px;
|
||||
left: 3rem;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
@@ -253,16 +246,16 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
||||
// position: absolute;
|
||||
// top: 55px;
|
||||
// right: 43.5%;
|
||||
//}
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
||||
position: absolute;
|
||||
top: 55px;
|
||||
right: 43.5%;
|
||||
}
|
||||
//------------------------------------------
|
||||
|
||||
.test_model > .o_form_label {
|
||||
margin-left: 4px !important;
|
||||
//line-height: 0 !important;
|
||||
line-height: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
@@ -270,10 +263,10 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
||||
right: 52%;
|
||||
}
|
||||
|
||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
//
|
||||
// left: -95px;
|
||||
//}
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
|
||||
left: -4.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,177 +311,27 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
||||
.o_horizontal_separator {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
//
|
||||
//.o_field_widget input[class='o_input'] {
|
||||
//text-align: center
|
||||
//}
|
||||
|
||||
.o_field_widget input[class='o_input'] {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
div:has(.o_required_modifier) > label::before {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
//.o_form_view .o_form_label {
|
||||
// position: relative;
|
||||
// width: 9rem;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// white-space: nowrap;
|
||||
// padding-left: 1rem;
|
||||
//}
|
||||
//
|
||||
//.o_form_view .o_form_label:hover {
|
||||
// white-space: normal;
|
||||
// overflow: visible;
|
||||
//}
|
||||
|
||||
.o_form_view {
|
||||
.o_form_sheet_bg .o_form_sheet {
|
||||
//max-width: none !important;
|
||||
width: auto !important;
|
||||
max-width: 98% !important;
|
||||
}
|
||||
.o_FormRenderer_chatterContainer {
|
||||
max-width: none;
|
||||
}
|
||||
.o_form_view .o_form_label {
|
||||
position: relative;
|
||||
width: 9rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
|
||||
// 2023-11-16 hy 新增
|
||||
.o_kanban_card_content .btn-group {
|
||||
position: unset;
|
||||
.o_form_view .o_form_label:hover {
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.o_kanban_card_content .btn-group button{
|
||||
top: 100px;
|
||||
left: 168px;
|
||||
}
|
||||
|
||||
|
||||
.o_kanban_primary_right {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 168px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
.row {
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
>div {
|
||||
padding: 0;
|
||||
width: unset;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.oe_kanban_details li.o_text_overflow {
|
||||
display: block;
|
||||
}
|
||||
.o_stock_kanban .o_kanban_card_content {
|
||||
.row {
|
||||
align-items: center;
|
||||
|
||||
.o_kanban_primary_left, .o_kanban_primary_right {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.o_kanban_primary_right {
|
||||
position: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 机床换刀申请表格宽度设置
|
||||
.o_list_table_ungrouped {
|
||||
min-width: 1089px;
|
||||
}
|
||||
// 加工能力\冷却方式 竖列展示改为横列展示
|
||||
.processingMethod {
|
||||
.o_cell.flex-grow-1.flex-sm-grow-0 {
|
||||
width: 100%!important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.o_inner_group.processingMethod {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置所有表格序号列padding为0
|
||||
.o_form_view .o_notebook > .tab-content > .tab-pane > :first-child:not(.o_group) .o_field_x2many.o_field_x2many_list tr > :first-child, .o_form_view .o_notebook > .tab-content > .tab-pane > :first-child.o_invisible_modifier + .o_field_widget .o_field_x2many.o_field_x2many_list tr > :first-child {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// 设置剩余number类型数据表格列 left
|
||||
.o_list_renderer .o_list_table thead .o_list_number_th {
|
||||
text-align:left;
|
||||
}
|
||||
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector).o_list_number {
|
||||
text-align: left;
|
||||
}
|
||||
.o_list_renderer .flex-row-reverse {
|
||||
flex-direction: unset!important;
|
||||
}
|
||||
|
||||
.o_list_renderer .flex-row-reverse > .text-end {
|
||||
text-align: left!important;
|
||||
}
|
||||
|
||||
// 设置modal弹窗样式
|
||||
.modal.o_technical_modal {
|
||||
.modal-lg {
|
||||
@media (min-width: 992px) {
|
||||
max-width: 1200px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.o_form_view .o_inner_group {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 更改表格底部按钮样式
|
||||
.o_list_renderer .o_field_x2many_list_row_add a,.treeHeaderBtn,.o_x2m_control_panel .o_cp_buttons .btn{
|
||||
display: inline-block;
|
||||
margin: 5px 0;
|
||||
font-size: 14px;
|
||||
color: #71639e;
|
||||
border: 1px solid #71639e;
|
||||
padding: 0.2rem 0.6rem;
|
||||
font-size: 1.08333333rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: all .3s;
|
||||
}
|
||||
.o_list_renderer .o_field_x2many_list_row_add a:hover,.treeHeaderBtn:hover,.o_x2m_control_panel .o_cp_buttons .btn:hover{
|
||||
background: #71639e;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
// 修改时间输入框宽度
|
||||
.o_datepicker_input.o_input.datetimepicker-input {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
|
||||
.o_form_view .o_form_editable .o_row > .o_field_widget, .o_form_view .o_form_editable .o_row > .o_field_widget.o_field_float_time {
|
||||
width: auto !important;
|
||||
flex: unset;
|
||||
}
|
||||
.addRequired {
|
||||
padding-left: calc(0.3rem + 2px)!important;
|
||||
}
|
||||
.addRequired:before {
|
||||
content: '*';
|
||||
color: red;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.o_list_renderer .o_list_table tfoot .o_list_number {
|
||||
text-align: left;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
.row_no {
|
||||
width: 35px !important;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<templates>
|
||||
<t t-name="purchase.PurchaseListView" t-inherit="web.ListRenderer" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//div[hasclass('o_list_renderer')]" position="before">
|
||||
<PurchaseDashBoard />
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -8,4 +8,4 @@ patch(ListRenderer.prototype, '/jikimo_frontend/static/src/views/list_nums/list_
|
||||
const nbCols = this._super(...arguments);
|
||||
return nbCols + 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<t t-name="og.web.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="extension">
|
||||
<xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
||||
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
||||
<th><i class="fa fa-list-ol"/></th>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<template>
|
||||
<t
|
||||
t-name="rowno_in_tree.ListRenderer"
|
||||
t-inherit="web.ListRenderer"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
|
||||
>
|
||||
<xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
||||
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
||||
</xpath>
|
||||
<xpath expr="//div/table/tfoot/tr/td" position="before">
|
||||
<td />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="rowno_in_tree.add_number"
|
||||
t-inherit="web.ListRenderer.Rows"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//t[@t-foreach='list.records']" position="before">
|
||||
<t t-set="RowNumber" t-value="1" />
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//t[@t-call='{{ constructor.recordRowTemplate }}']"
|
||||
position="after"
|
||||
>
|
||||
<t t-set="RowNumber" t-value="RowNumber+1" />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="rowno_in_tree.ListRenderer.RecordRowNumber"
|
||||
t-inherit="web.ListRenderer.RecordRow"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//td[@class='o_list_record_selector']" position="before">
|
||||
<td tabindex="-1">
|
||||
<span t-esc="RowNumber" />
|
||||
</td>
|
||||
</xpath>
|
||||
</t>
|
||||
</template>
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<!-- 修改页面头部图标及文字 -->
|
||||
<template id="favicon_icon" inherit_id="web.layout" name="Web layout">
|
||||
<!-- change the title with reliance partner -->
|
||||
<xpath expr="//head//title" position="before">
|
||||
<title t-esc="'JIKIMO'"/>
|
||||
</xpath>
|
||||
<!-- change the default favicon icon with -->
|
||||
<xpath expr="//head//link[@rel='shortcut icon']" position="replace">
|
||||
<link type="image/x-icon" rel="shortcut icon" href="/jikimo_frontend/static/src/img/jikimo-logo.ico"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- hide 登录页面 powerd by odoo 及管理数据库 -->
|
||||
<template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout">
|
||||
<xpath expr="//div[@class='card-body']//div[last()]" position="replace"></xpath>
|
||||
</template>
|
||||
|
||||
<!-- 隐藏odoo版本信息 -->
|
||||
<record id="jikimo_res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">jikimo.res.config.settings.view.form.inherit.base.setup</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='about']" position="replace">
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,14 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import models
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def uninstall_hook(cr, registry):
|
||||
# 使用cr来执行数据库操作
|
||||
with api.Environment.manage():
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
# 执行数据清理操作
|
||||
access_rights = env['access.right'].search([])
|
||||
access_rights.unlink()
|
||||
followers = env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
followers.unlink()
|
||||
@@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': '机企猫 隐藏项目',
|
||||
'version': '16.0.1.0.0',
|
||||
'category': 'Extra Tools, Productivity',
|
||||
'summary': """ Can hide options from user """,
|
||||
'description': """ By using this module we can hide the options like create,
|
||||
delete,export,and archive/un archive in the model which we want. Here we
|
||||
are also able to select the user groups except Administrator which we want
|
||||
to apply the above hiding functionality """,
|
||||
'author': '机企猫-MGW',
|
||||
'company': '机企猫',
|
||||
'depends': ['base_setup', 'mail'],
|
||||
'data': [
|
||||
'security/security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/model_access_rights_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'jikimo_hide_options/static/src/js/form_controller.js',
|
||||
'jikimo_hide_options/static/src/js/list_controller.js',
|
||||
'jikimo_hide_options/static/src/js/kanban_controller.js'
|
||||
]
|
||||
},
|
||||
'images': ['static/description/banner.jpg'],
|
||||
'license': 'LGPL-3',
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': False,
|
||||
'uninstall_hook': 'uninstall_hook',
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import model_access_rights
|
||||
from . import models
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class ModelAccessRights(models.Model):
|
||||
"""This class is used to detect, which all options want to hide from the
|
||||
specified group and model"""
|
||||
_name = 'access.right'
|
||||
_inherit = 'mail.thread'
|
||||
_description = 'Manage Modules Access Control'
|
||||
_rec_name = 'model_id'
|
||||
|
||||
model_id = fields.Many2one('ir.model', ondelete='cascade', required=True,
|
||||
help="select the model")
|
||||
groups_id = fields.Many2one('res.groups', required=True,
|
||||
help="select the group")
|
||||
is_delete = fields.Boolean(string="Delete", help="hide the delete option")
|
||||
is_export = fields.Boolean(string="Export",
|
||||
help="hide the 'Export All'"
|
||||
" option from list view")
|
||||
is_create_or_update = fields.Boolean(string="Create/Update",
|
||||
help="hide the create option from list"
|
||||
" as well as form view")
|
||||
is_archive = fields.Boolean(string="Archive/UnArchive",
|
||||
help="hide the archive option")
|
||||
|
||||
@api.model
|
||||
def hide_buttons(self):
|
||||
"""This function contains a query that detects which all options want
|
||||
to hide, in which model,and to which user groups"""
|
||||
access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
'is_export',
|
||||
'is_create_or_update',
|
||||
'is_archive',
|
||||
'groups_id'])
|
||||
for dic in access_right_rec:
|
||||
model = self.env['ir.model'].sudo().browse(dic['model_id'][0]).model
|
||||
group_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).name
|
||||
|
||||
module_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).module
|
||||
dic.update({
|
||||
'model': model,
|
||||
'group_name': group_name,
|
||||
'module': module_name
|
||||
})
|
||||
return access_right_rec
|
||||
# @api.model
|
||||
# def hide_buttons(self):
|
||||
# """This function contains a query that detects which all options want
|
||||
# to hide, in which model,and to which user groups"""
|
||||
# access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
# 'is_export',
|
||||
# 'is_create_or_update',
|
||||
# 'is_archive',
|
||||
# 'groups_id'])
|
||||
# for dic in access_right_rec:
|
||||
# model = self.env['ir.model'].sudo().browse(dic['model_id']).model
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).module
|
||||
# dic.update({
|
||||
# 'model': model,
|
||||
# 'group_name': group_name,
|
||||
# 'module': module_name
|
||||
# })
|
||||
# return access_right_rec
|
||||
|
||||
|
||||
# class AccessRightCleanup(models.Model):
|
||||
# _name = 'access.right.cleanup' # 定义一个新的模型名
|
||||
# _description = 'Access Right Cleanup'
|
||||
|
||||
|
||||
|
||||
# @api.model
|
||||
# def _module_uninstall(self):
|
||||
# """在模块卸载时执行清理操作"""
|
||||
# super(AccessRightCleanup, self)._module_uninstall()
|
||||
# # 这里执行你的清理逻辑
|
||||
#
|
||||
# # 获取access.right模型的所有记录
|
||||
# access_rights = self.env['access.right'].search([])
|
||||
# for access_right in access_rights:
|
||||
# # 删除access.right模型的所有记录
|
||||
# access_right.unlink()
|
||||
#
|
||||
# # 查找所有关联到access.right模型的关注者记录
|
||||
# followers = self.env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
# for follower in followers:
|
||||
# # 删除关注者记录
|
||||
# follower.unlink()
|
||||
#
|
||||
# # # 示例:删除自定义数据表(确保先检查外键约束等)
|
||||
# # self.env.cr.execute('DROP TABLE IF EXISTS access_right CASCADE;')
|
||||
#
|
||||
# # 其他清理工作...
|
||||
@@ -1,353 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
from operator import attrgetter
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.models import BaseModel, _unlink, LOG_ACCESS_COLUMNS, \
|
||||
INSERT_BATCH_SIZE, SQL_DEFAULT
|
||||
# from odoo.tools import OrderedSet, split_every, attrgetter, clean_context
|
||||
from odoo.tools import OrderedSet, split_every, clean_context
|
||||
|
||||
|
||||
@api.model
|
||||
def _create(self, data_list):
|
||||
""" Create records from the stored field values in ``data_list``. """
|
||||
assert data_list
|
||||
cr = self.env.cr
|
||||
|
||||
# insert rows in batches of maximum INSERT_BATCH_SIZE
|
||||
ids = [] # ids of created records
|
||||
other_fields = OrderedSet() # non-column fields
|
||||
|
||||
for data_sublist in split_every(INSERT_BATCH_SIZE, data_list):
|
||||
stored_list = [data['stored'] for data in data_sublist]
|
||||
fnames = sorted({name for stored in stored_list for name in stored})
|
||||
|
||||
columns = []
|
||||
rows = [[] for _ in stored_list]
|
||||
for fname in fnames:
|
||||
field = self._fields[fname]
|
||||
if field.column_type:
|
||||
columns.append(fname)
|
||||
for stored, row in zip(stored_list, rows):
|
||||
if fname in stored:
|
||||
colval = field.convert_to_column(stored[fname], self,
|
||||
stored)
|
||||
if field.translate is True and colval:
|
||||
if 'en_US' not in colval.adapted:
|
||||
colval.adapted['en_US'] = next(
|
||||
iter(colval.adapted.values()))
|
||||
row.append(colval)
|
||||
else:
|
||||
row.append(SQL_DEFAULT)
|
||||
else:
|
||||
other_fields.add(field)
|
||||
|
||||
if field.type == 'properties':
|
||||
# force calling fields.create for properties field because
|
||||
# we might want to update the parent definition
|
||||
other_fields.add(field)
|
||||
|
||||
if not columns:
|
||||
# manage the case where we create empty records
|
||||
columns = ['id']
|
||||
for row in rows:
|
||||
row.append(SQL_DEFAULT)
|
||||
|
||||
header = ", ".join(f'"{column}"' for column in columns)
|
||||
template = ", ".join("%s" for _ in rows)
|
||||
cr.execute(
|
||||
f'INSERT INTO "{self._table}" ({header}) VALUES {template} RETURNING "id"',
|
||||
[tuple(row) for row in rows],
|
||||
)
|
||||
ids.extend(id_ for id_, in cr.fetchall())
|
||||
|
||||
# put the new records in cache, and update inverse fields, for many2one
|
||||
#
|
||||
# cachetoclear is an optimization to avoid modified()'s cost until other_fields are processed
|
||||
cachetoclear = []
|
||||
records = self.browse(ids)
|
||||
inverses_update = defaultdict(list) # {(field, value): ids}
|
||||
common_set_vals = set(
|
||||
LOG_ACCESS_COLUMNS + [self.CONCURRENCY_CHECK_FIELD, 'id',
|
||||
'parent_path'])
|
||||
for data, record in zip(data_list, records):
|
||||
data['record'] = record
|
||||
# DLE P104: test_inherit.py, test_50_search_one2many
|
||||
vals = dict(
|
||||
{k: v for d in data['inherited'].values() for k, v in d.items()},
|
||||
**data['stored'])
|
||||
set_vals = common_set_vals.union(vals)
|
||||
for field in self._fields.values():
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
self.env.cache.set(record, field, ())
|
||||
elif field.related and not field.column_type:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
# DLE P123: `test_adv_activity`, `test_message_assignation_inbox`, `test_message_log`, `test_create_mail_simple`, ...
|
||||
# Set `mail.message.parent_id` to False in cache so it doesn't do the useless SELECT when computing the modified of `child_ids`
|
||||
# in other words, if `parent_id` is not set, no other message `child_ids` are impacted.
|
||||
# + avoid the fetch of fields which are False. e.g. if a boolean field is not passed in vals and as no default set in the field attributes,
|
||||
# then we know it can be set to False in the cache in the case of a create.
|
||||
elif field.name not in set_vals and not field.compute:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
for fname, value in vals.items():
|
||||
field = self._fields[fname]
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
cachetoclear.append((record, field))
|
||||
else:
|
||||
cache_value = field.convert_to_cache(value, record)
|
||||
self.env.cache.set(record, field, cache_value)
|
||||
if field.type in ('many2one', 'many2one_reference') and \
|
||||
self.pool.field_inverses[field]:
|
||||
inverses_update[(field, cache_value)].append(record.id)
|
||||
|
||||
for (field, value), record_ids in inverses_update.items():
|
||||
field._update_inverses(self.browse(record_ids), value)
|
||||
|
||||
# update parent_path
|
||||
records._parent_store_create()
|
||||
|
||||
# protect fields being written against recomputation
|
||||
protected = [(data['protected'], data['record']) for data in data_list]
|
||||
with self.env.protecting(protected):
|
||||
# mark computed fields as todo
|
||||
records.modified(self._fields, create=True)
|
||||
|
||||
if other_fields:
|
||||
# discard default values from context for other fields
|
||||
others = records.with_context(clean_context(self._context))
|
||||
for field in sorted(other_fields, key=attrgetter('_sequence')):
|
||||
field.create([
|
||||
(other, data['stored'][field.name])
|
||||
for other, data in zip(others, data_list)
|
||||
if field.name in data['stored']
|
||||
])
|
||||
|
||||
# mark fields to recompute
|
||||
records.modified([field.name for field in other_fields],
|
||||
create=True)
|
||||
|
||||
# if value in cache has not been updated by other_fields, remove it
|
||||
for record, field in cachetoclear:
|
||||
if self.env.cache.contains(record,
|
||||
field) and not self.env.cache.get(
|
||||
record, field):
|
||||
self.env.cache.remove(record, field)
|
||||
|
||||
# check Python constraints for stored fields
|
||||
records._validate_fields(
|
||||
name for data in data_list for name in data['stored'])
|
||||
records.check_access_rule('create')
|
||||
# This is used to restrict the access right to create a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)],
|
||||
# ['model_id', 'is_create_or_update',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_create_or_update']:
|
||||
# raise UserError('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.')
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)],
|
||||
['model_id', 'is_create_or_update', 'groups_id']
|
||||
)
|
||||
|
||||
# 如果找到相关记录,并且当前用户不是管理员
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
# 获取与权限相关的用户组信息
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
# 如果找到了用户组数据
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
# 检查当前用户是否属于该组
|
||||
if self.env.user.has_group(group_xml_id):
|
||||
# 如果该用户组被限制创建或更新操作
|
||||
if rec['is_create_or_update']:
|
||||
raise UserError(
|
||||
_("You are restricted from performing this operation. Please contact the administrator."))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||
pass
|
||||
|
||||
return records
|
||||
|
||||
|
||||
@api.model
|
||||
def unlink(self):
|
||||
""" unlink()
|
||||
|
||||
Deletes the records in ``self``.
|
||||
|
||||
:raise AccessError: if the user is not allowed to delete all the given records
|
||||
:raise UserError: if the record is default property for other records
|
||||
"""
|
||||
if not self:
|
||||
return True
|
||||
|
||||
self.check_access_rights('unlink')
|
||||
self.check_access_rule('unlink')
|
||||
|
||||
from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG
|
||||
for func in self._ondelete_methods:
|
||||
# func._ondelete is True if it should be called during uninstallation
|
||||
if func._ondelete or not self._context.get(MODULE_UNINSTALL_FLAG):
|
||||
func(self)
|
||||
|
||||
# TOFIX: this avoids an infinite loop when trying to recompute a
|
||||
# field, which triggers the recomputation of another field using the
|
||||
# same compute function, which then triggers again the computation
|
||||
# of those two fields
|
||||
for field in self._fields.values():
|
||||
self.env.remove_to_compute(field, self)
|
||||
|
||||
self.env.flush_all()
|
||||
|
||||
cr = self._cr
|
||||
Data = self.env['ir.model.data'].sudo().with_context({})
|
||||
Defaults = self.env['ir.default'].sudo()
|
||||
Property = self.env['ir.property'].sudo()
|
||||
Attachment = self.env['ir.attachment'].sudo()
|
||||
ir_property_unlink = Property
|
||||
ir_model_data_unlink = Data
|
||||
ir_attachment_unlink = Attachment
|
||||
|
||||
# mark fields that depend on 'self' to recompute them after 'self' has
|
||||
# been deleted (like updating a sum of lines after deleting one line)
|
||||
with self.env.protecting(self._fields.values(), self):
|
||||
self.modified(self._fields, before=True)
|
||||
for sub_ids in cr.split_for_in_conditions(self.ids):
|
||||
records = self.browse(sub_ids)
|
||||
|
||||
# Check if the records are used as default properties.
|
||||
refs = [f'{self._name},{id_}' for id_ in sub_ids]
|
||||
if Property.search(
|
||||
[('res_id', '=', False), ('value_reference', 'in', refs)],
|
||||
limit=1):
|
||||
raise UserError(
|
||||
_('Unable to delete this document because it is used as a default property'))
|
||||
|
||||
# Delete the records' properties.
|
||||
ir_property_unlink |= Property.search([('res_id', 'in', refs)])
|
||||
|
||||
query = f'DELETE FROM "{self._table}" WHERE id IN %s'
|
||||
cr.execute(query, (sub_ids,))
|
||||
|
||||
# Removing the ir_model_data reference if the record being deleted
|
||||
# is a record created by xml/csv file, as these are not connected
|
||||
# with real database foreign keys, and would be dangling references.
|
||||
#
|
||||
# Note: the following steps are performed as superuser to avoid
|
||||
# access rights restrictions, and with no context to avoid possible
|
||||
# side-effects during admin calls.
|
||||
data = Data.search(
|
||||
[('model', '=', self._name), ('res_id', 'in', sub_ids)])
|
||||
ir_model_data_unlink |= data
|
||||
|
||||
# For the same reason, remove the defaults having some of the
|
||||
# records as value
|
||||
Defaults.discard_records(records)
|
||||
|
||||
# For the same reason, remove the relevant records in ir_attachment
|
||||
# (the search is performed with sql as the search method of
|
||||
# ir_attachment is overridden to hide attachments of deleted
|
||||
# records)
|
||||
query = 'SELECT id FROM ir_attachment WHERE res_model=%s AND res_id IN %s'
|
||||
cr.execute(query, (self._name, sub_ids))
|
||||
ir_attachment_unlink |= Attachment.browse(
|
||||
row[0] for row in cr.fetchall())
|
||||
|
||||
# invalidate the *whole* cache, since the orm does not handle all
|
||||
# changes made in the database, like cascading delete!
|
||||
self.env.invalidate_all(flush=False)
|
||||
if ir_property_unlink:
|
||||
ir_property_unlink.unlink()
|
||||
if ir_model_data_unlink:
|
||||
ir_model_data_unlink.unlink()
|
||||
if ir_attachment_unlink:
|
||||
ir_attachment_unlink.unlink()
|
||||
# DLE P93: flush after the unlink, for recompute fields depending on
|
||||
# the modified of the unlink
|
||||
self.env.flush_all()
|
||||
# auditing: deletions are infrequent and leave no trace in the database
|
||||
_unlink.info('User #%s deleted %s records with IDs: %r', self._uid,
|
||||
self._name, self.ids)
|
||||
# This is used to restrict the access right to unlink a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)], ['model_id', 'is_delete',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_delete']:
|
||||
# raise UserError(_('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.'))
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
# current_model_id = self.env['ir.model'].sudo().search([('model', '=', self._name)]).id
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)], ['model_id', 'is_delete', 'groups_id']
|
||||
)
|
||||
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
if self.env.user.has_group(group_xml_id) and rec['is_delete']:
|
||||
raise UserError(
|
||||
_('You are restricted from performing this operation. Please contact the administrator.'))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
BaseModel._create = _create
|
||||
BaseModel.unlink = unlink
|
||||
@@ -1,2 +0,0 @@
|
||||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_access_right,access.access.right,model_access_right,jikimo_hide_options.model_access_rights_groups_configure_model_access,1,1,1,1
|
||||
|
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Add a group named Configure Model Access in res.groups-->
|
||||
<odoo>
|
||||
<record id="model_access_rights_groups_configure_model_access" model="res.groups">
|
||||
<field name="name">配置隐藏项目</field>
|
||||
<field name="category_id" ref="base.module_category_usability"/>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 310 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 576 B |
|
Before Width: | Height: | Size: 733 B |
|
Before Width: | Height: | Size: 911 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 673 B |
|
Before Width: | Height: | Size: 878 B |
|
Before Width: | Height: | Size: 653 B |
|
Before Width: | Height: | Size: 905 B |
|
Before Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 427 B |
|
Before Width: | Height: | Size: 627 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 988 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 589 B |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 967 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,596 +0,0 @@
|
||||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
|
||||
<!-- TITLE BAR -->
|
||||
<div class="d-flex align-items-center justify-content-between"
|
||||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
|
||||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" style="width: 42px; height: 42px;" />
|
||||
<div>
|
||||
<div
|
||||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Community
|
||||
</div>
|
||||
<div
|
||||
style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Enterprise
|
||||
</div>
|
||||
<div
|
||||
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Odoo.sh
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF TITLE BAR -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12">
|
||||
<!-- APP HERO -->
|
||||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
|
||||
Hide Create|Delete|Archive|Export Options - Model Wise</h1>
|
||||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">Hide Create, Delete, Archive, Export Options in Models</p>
|
||||
<!-- END OF APP HERO -->
|
||||
<img src="assets/screenshots/hero.gif" class="img-responsive"
|
||||
style="width: 100%; margin-left: auto; margin-right: auto;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- NAVIGATION SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/compass.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Explore This
|
||||
Module</h2>
|
||||
</div>
|
||||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#overview">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
|
||||
more about this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#features">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
features of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#screenshots">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
screenshots of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF NAVIGATION SECTION -->
|
||||
|
||||
<!-- OVERVIEW SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pie-chart.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Overview
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 py-4">
|
||||
By using this module we can hide the options like create,delete,export,and archive/un archive in the model
|
||||
which we want. Here we are also able to select the user groups except Administrator which we want to apply the
|
||||
above hiding functionality </div>
|
||||
</div>
|
||||
<!-- END OF OVERVIEW SECTION -->
|
||||
|
||||
<!-- FEATURES SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/features.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Features
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div class="d-flex align-items-center" style="margin-top: 40px; margin-bottom: 40px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Easily hide the options like Create,Delete,Export and Archive/UnArchive</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific model</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific user group</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">No additional configuration needed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF FEATURES SECTION -->
|
||||
|
||||
<!-- SCREENSHOTS SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="screenshots">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pictures.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Screenshots
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Go to Settings > Users and there you can see the Configure Model Access, by enabling that
|
||||
option and refresh the page, you can see a new menu named 'Restrict Access Rights'</h3>
|
||||
<img src="assets/screenshots/model_access_right_01.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> User in the Purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_02.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Select the Model, Groups and the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_03.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> We can see Create option is hidden in purchase.order to those who are User
|
||||
in purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_04.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">User in Project module</h3>
|
||||
<img src="assets/screenshots/model_access_right_05.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> By default, we can see Export and Archive/UnArchive options</h3>
|
||||
<img src="assets/screenshots/model_access_right_06.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Select the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_07.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Export and Archive/UnArchive functionality are hidden</h3>
|
||||
<img src="assets/screenshots/model_access_right_08.png" class="img-thumbnail">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SCREENSHOTS SECTION -->
|
||||
<!-- RELATED PRODUCTS -->
|
||||
<div class="d-flex align-items-center"
|
||||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/categories.png"/>
|
||||
</div>
|
||||
<h2 class="mt-2"
|
||||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
|
||||
Related
|
||||
Products
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="demo1" class="row carousel slide" data-ride="carousel">
|
||||
<!-- The slideshow -->
|
||||
<div class="carousel-inner" style="padding: 30px;">
|
||||
<div class="carousel-item" style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_odoo_base/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/1.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/woo_commerce/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l2.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/shopify_odoo_connector/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l3.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item active"
|
||||
style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/hr_zk_attendance/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l4.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/whatsapp_redirect/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l5.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_website_product_media/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l6.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
|
||||
style="width:35px; color:#000"> <span
|
||||
class="carousel-control-prev-icon"><i
|
||||
class="fa fa-chevron-left"
|
||||
style="font-size:24px"></i></span>
|
||||
</a> <a class="carousel-control-next" href="#demo1"
|
||||
data-slide="next" style="width:35px; color:#000">
|
||||
<span class="carousel-control-next-icon"><i
|
||||
class="fa fa-chevron-right"
|
||||
style="font-size:24px"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF RELATED PRODUCTS -->
|
||||
|
||||
<!-- OUR SERVICES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/star.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our Services
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Customization</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Support</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Hire
|
||||
Odoo
|
||||
Developer</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Integration</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Migration</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Consultancy</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Licensing Consultancy</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR SERVICES -->
|
||||
|
||||
<!-- OUR INDUSTRIES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/corporate.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our
|
||||
Industries
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Trading
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easily procure
|
||||
and
|
||||
sell your products</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
POS
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easy
|
||||
configuration
|
||||
and convivial experience</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/education-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Education
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
A platform for
|
||||
educational management</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Manufacturing
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Plan, track and
|
||||
schedule your operations</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
E-commerce & Website
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Mobile
|
||||
friendly,
|
||||
awe-inspiring product pages</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Service Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Keep track of
|
||||
services and invoice</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Restaurant
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Run your bar or
|
||||
restaurant methodically</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Hotel Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
An
|
||||
all-inclusive
|
||||
hotel management application</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR INDUSTRIES -->
|
||||
|
||||
<!-- SUPPORT -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/customer-support.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Support
|
||||
</h2>
|
||||
</div>
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/support.png" height="48" width="48" style="width: 42px; height: 42px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>Need Help?</h4>
|
||||
<p style="line-height: 100%;">Got questions or need help? Get in touch.</p>
|
||||
<a href="mailto:odoo@cybrosys.com">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
|
||||
odoo@cybrosys.com</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/whatsapp.png" height="52" width="52" style="width: 52px; height: 52px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>WhatsApp</h4>
|
||||
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
|
||||
<a href="https://api.whatsapp.com/send?phone=918606827707">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">+91 86068
|
||||
27707</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
|
||||
<img src="assets/misc/logo.png" width="144" height="31"
|
||||
style="width:144px; height: 31px; margin-top: 40px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SUPPORT -->
|
||||
@@ -1,46 +0,0 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the form view
|
||||
*/
|
||||
import { FormController} from "@web/views/form/form_controller";
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const { onWillStart} = owl;
|
||||
patch(FormController.prototype, 'jikimo_hide_options/static/src/js/form_controller.js.FormController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the form view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.user.hasGroup(group)) {
|
||||
if (!this.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.canCreate = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
this.archInfo.activeActions.delete = false
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { KanbanController } from '@web/views/kanban/kanban_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(KanbanController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.KanbanController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the Kanban view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.model.user.hasGroup(group)) {
|
||||
if (!self.model.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.props.archInfo.activeActions.create=false
|
||||
self.props.archInfo.activeActions.edit=false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.props.archInfo.activeActions.delete=false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { ListController} from '@web/views/list/list_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(ListController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.ListController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the list view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.userService.hasGroup(group)) {
|
||||
if (!this.userService.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.activeActions.create = false;
|
||||
}
|
||||
if (result[i].is_export) {
|
||||
self.isExportEnable = false
|
||||
self.isExportEnable = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.activeActions.delete = false;
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false;
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Action for the menu Restrict Model Access-->
|
||||
<record id="access_right_action" model="ir.actions.act_window">
|
||||
<field name="name">隐藏项目</field>
|
||||
<field name="res_model">access.right</field>
|
||||
<field name='view_mode'>tree,form</field>
|
||||
</record>
|
||||
<!-- Tree view for the model access.right-->
|
||||
<record id="access_right_view_tree" model="ir.ui.view">
|
||||
<field name="name">access.right.view.tree</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Form view for the model access.right-->
|
||||
<record id="access_right_view_form" model="ir.ui.view">
|
||||
<field name="name">access.right.view.form</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Creating a menu named Restrict Model Access-->
|
||||
<menuitem id="access_right_menu"
|
||||
name="隐藏项目"
|
||||
parent="base.menu_administration"
|
||||
action="access_right_action"
|
||||
sequence="6"
|
||||
groups="jikimo_hide_options.model_access_rights_groups_configure_model_access"/>
|
||||
</odoo>
|
||||
@@ -23,7 +23,7 @@ html .o_web_client > .o_action_manager > .o_action {
|
||||
}
|
||||
|
||||
.o_form_view {
|
||||
//background-color: unset !important;
|
||||
background-color: unset !important;
|
||||
min-height: unset !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
<xpath expr="//field[@name='state']" position="after">
|
||||
<field name="production_state" invisible="1"/>
|
||||
</xpath>
|
||||
<!-- <xpath expr="//button[@name='action_open_wizard']" position="after">-->
|
||||
<!-- <button name="open_tablet_view" type="object" icon="fa-tablet" title="Open Tablet View" context="{'from_production_order': True}" attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'cancel', 'done')), ('state', '=', 'done')]}"/>-->
|
||||
<!-- </xpath>-->
|
||||
<xpath expr="//button[@name='action_open_wizard']" position="after">
|
||||
<button name="open_tablet_view" type="object" icon="fa-tablet" title="Open Tablet View" context="{'from_production_order': True}" attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'cancel', 'done')), ('state', '=', 'done')]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ csv_internal_sep = ,
|
||||
data_dir = /var/lib/odoo
|
||||
db_host = 172.17.0.2
|
||||
db_maxconn = 64
|
||||
db_name = sf_t2cs_003
|
||||
db_name = sf_cs_dev937
|
||||
db_password = sf
|
||||
db_port = 5432
|
||||
db_sslmode = prefer
|
||||
db_template = template0
|
||||
db_user = sf
|
||||
dbfilter =
|
||||
without_demo = all
|
||||
demo = {}
|
||||
email_from = False
|
||||
from_filter = False
|
||||
geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb
|
||||
@@ -56,6 +56,7 @@ test_tags = None
|
||||
;transient_age_limit = 1.0
|
||||
;translate_modules = ['all']
|
||||
unaccent = False
|
||||
upgrade_path =
|
||||
upgrade_path =
|
||||
without_demo = False
|
||||
workers = 0
|
||||
|
||||
|
||||
@@ -263,8 +263,6 @@ class QualityCheck(models.Model):
|
||||
picture = fields.Binary('Picture', attachment=True)
|
||||
additional_note = fields.Text(
|
||||
'Additional Note', help="Additional remarks concerning this check.")
|
||||
report_result = fields.Char('检测结果', readonly=True)
|
||||
report_pdf = fields.Binary('检测报告', readonly=True)
|
||||
|
||||
def _compute_alert_count(self):
|
||||
alert_data = self.env['quality.alert'].read_group([('check_id', 'in', self.ids)], ['check_id'], ['check_id'])
|
||||
@@ -410,5 +408,3 @@ class QualityAlert(models.Model):
|
||||
domain = [('team_ids', '=', False)]
|
||||
stage_ids = stages._search(domain, order=order, access_rights_uid=SUPERUSER_ID)
|
||||
return stages.browse(stage_ids)
|
||||
|
||||
|
||||
|
||||
@@ -9,10 +9,8 @@ access_quality_point_user,quality.point,quality.model_quality_point,quality.grou
|
||||
access_quality_point_test_type_user,quality.point.test_type,quality.model_quality_point_test_type,quality.group_quality_user,1,0,0,0
|
||||
access_quality_check_stock_user,quality.check,quality.model_quality_check,stock.group_stock_user,1,1,1,0
|
||||
access_stock_lot_user,stock.lot,stock.model_stock_lot,quality.group_quality_user,1,0,0,0
|
||||
|
||||
access_stock_pack_user,stock.move.line,stock.model_stock_move_line,quality.group_quality_user,1,0,0,0
|
||||
access_stock_picking_group_quality_user,stock_picking_group_quality_user,stock.model_stock_picking,quality.group_quality_user,1,0,0,0
|
||||
|
||||
access_stock_picking,stock.move.line,stock.model_stock_picking,quality.group_quality_user,1,0,0,0
|
||||
access_quality_alert_team_manager,quality.alert.team,quality.model_quality_alert_team,quality.group_quality_manager,1,1,1,1
|
||||
access_quality_check_manager,quality.check,quality.model_quality_check,quality.group_quality_manager,1,1,1,1
|
||||
access_quality_alert_manager,quality.alert,quality.model_quality_alert,quality.group_quality_manager,1,1,1,1
|
||||
|
||||
|
@@ -7,15 +7,10 @@
|
||||
<field name="model">quality.point</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box"/>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger"
|
||||
attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<h2>
|
||||
<field name="name" readonly="1"/>
|
||||
</h2>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<h2><field name="name" readonly="1"/></h2>
|
||||
<group>
|
||||
<group>
|
||||
<field name="active" invisible="1"/>
|
||||
@@ -38,14 +33,13 @@
|
||||
<field name="note" placeholder="Describe the quality check to do..."/>
|
||||
</page>
|
||||
<page string="Notes" name="Notes">
|
||||
<field name="reason" string="Note"
|
||||
placeholder="Describe why you need to perform this quality check..."/>
|
||||
<field name="reason" string="Note" placeholder="Describe why you need to perform this quality check..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
@@ -91,18 +85,17 @@
|
||||
<filter name="filter_date_close" date="date_close"/>
|
||||
<separator/>
|
||||
<filter string="Late Activities" name="activities_overdue"
|
||||
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
<filter string="Today Activities" name="activities_today"
|
||||
domain="[('my_activity_date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
domain="[('my_activity_date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter string="Future Activities" name="activities_upcoming_all"
|
||||
domain="[('my_activity_date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
domain="[('my_activity_date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Stage" name="groupby_stage" domain="[]" context="{'group_by': 'stage_id'}"/>
|
||||
<filter string="Responsible" name="groupby_user" domain="[]" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Root Cause" name="groupby_reason" domain="[]" context="{'group_by': 'reason_id'}"/>
|
||||
<filter string="Creation Date" name="groupby_createmonth" domain="[]"
|
||||
context="{'group_by': 'create_date'}"/>
|
||||
<filter string="Creation Date" name="groupby_createmonth" domain="[]" context="{'group_by': 'create_date'}"/>
|
||||
<filter string="Quality Team" name="groupby_team_id" domain="[]" context="{'group_by': 'team_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
@@ -129,4 +122,4 @@
|
||||
</record>
|
||||
|
||||
<!-- js stuff -->
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
<field name="tag_ids"/>
|
||||
</div>
|
||||
<div>
|
||||
<strong>
|
||||
<field name="product_tmpl_id"/>
|
||||
</strong>
|
||||
<strong><field name="product_tmpl_id"/></strong>
|
||||
</div>
|
||||
<div>
|
||||
<field name="display_name"/>
|
||||
@@ -67,28 +65,20 @@
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="product_id" invisible="1"/>
|
||||
<div class="oe_button_box">
|
||||
<button name="action_see_check" type="object" attrs="{'invisible': [('check_id', '=', False)]}"
|
||||
class="oe_stat_button" icon="fa-check-square-o">
|
||||
<button name="action_see_check" type="object" attrs="{'invisible': [('check_id', '=', False)]}" class="oe_stat_button" icon="fa-check-square-o">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="check_id" readonly="1"/>
|
||||
</span>
|
||||
<span class="o_stat_value"><field name="check_id" readonly="1"/></span>
|
||||
<span class="o_stat_text">Quality Check</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" readonly="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="oe_title"><h1><field name="name" readonly="1"/></h1></div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="title"/>
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="product_id" groups="product.group_product_variant"/>
|
||||
<field name="lot_id" context="{'default_product_id': product_id}"
|
||||
groups="stock.group_production_lot"/>
|
||||
<field name="lot_id" context="{'default_product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="picking_id"/>
|
||||
</group>
|
||||
<group>
|
||||
@@ -154,25 +144,25 @@
|
||||
</record>
|
||||
|
||||
<record id="quality_alert_view_pivot" model="ir.ui.view">
|
||||
<field name="name">quality.alert.view.pivot</field>
|
||||
<field name="model">quality.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Quality Alert Analysis" sample="1">
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="team_id" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
<field name="name">quality.alert.view.pivot</field>
|
||||
<field name="model">quality.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Quality Alert Analysis" sample="1">
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="team_id" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_alert_view_graph" model="ir.ui.view">
|
||||
<field name="name">quality.alert.view.graph</field>
|
||||
<field name="model">quality.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Quality Alert Analysis" sample="1">
|
||||
<field name="reason_id"/>
|
||||
<field name="stage_id"/>
|
||||
</graph>
|
||||
</field>
|
||||
<field name="name">quality.alert.view.graph</field>
|
||||
<field name="model">quality.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Quality Alert Analysis" sample="1">
|
||||
<field name="reason_id"/>
|
||||
<field name="stage_id"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_alert_view_calendar" model="ir.ui.view">
|
||||
@@ -196,8 +186,7 @@
|
||||
<field name="view_mode">kanban,tree,form,pivot,graph,calendar</field>
|
||||
<field name="domain">[('team_id', '=', active_id)]</field>
|
||||
<field name="context">{'default_team_id': active_id,
|
||||
'search_default_team_id': [active_id]}
|
||||
</field>
|
||||
'search_default_team_id': [active_id]}</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_alert_action_check" model="ir.actions.act_window">
|
||||
@@ -206,7 +195,7 @@
|
||||
<field name="view_mode">kanban,tree,form,pivot,graph,calendar</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new quality alert
|
||||
Create a new quality alert
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -223,35 +212,24 @@
|
||||
</record>
|
||||
|
||||
<!-- QUALITY.CHECK -->
|
||||
<record id="quality_check_view_form" model="ir.ui.view">
|
||||
<record id="quality_check_view_form" model="ir.ui.view">
|
||||
<field name="name">quality.check.view.form</field>
|
||||
<field name="model">quality.check</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
<button name="do_pass" type="object" class="btn-primary"
|
||||
attrs="{'invisible': [('quality_state', '!=', 'none')]}" string="Pass" data-hotkey="q"/>
|
||||
<button name="do_pass" type="object" attrs="{'invisible': [('quality_state', '!=', 'fail')]}"
|
||||
groups="quality.group_quality_manager" string="Pass" data-hotkey="q"/>
|
||||
<button name="do_fail" type="object" class="btn-primary"
|
||||
attrs="{'invisible': [('quality_state', '!=', 'none')]}" string="Fail" data-hotkey="w"/>
|
||||
<button name="do_fail" type="object" attrs="{'invisible': [('quality_state', '!=', 'pass')]}"
|
||||
groups="quality.group_quality_manager" string="Fail" data-hotkey="w"/>
|
||||
<button name="do_measure" type="object"
|
||||
attrs="{'invisible': ['|', ('test_type', '!=', 'measure'), ('quality_state', '!=', 'none')]}"
|
||||
string="Measure" data-hotkey="v"/>
|
||||
<button name="do_alert" type="object"
|
||||
attrs="{'invisible': ['|', ('alert_ids', '!=', []), ('quality_state', '!=', 'pass')]}"
|
||||
string="Create Alert" data-hotkey="g"/>
|
||||
<button name="do_alert" type="object" class="btn-primary"
|
||||
attrs="{'invisible': ['|', ('alert_ids', '!=', []), ('quality_state', '!=', 'fail')]}"
|
||||
string="Create Alert" data-hotkey="g"/>
|
||||
<button name="do_pass" type="object" class="btn-primary" attrs="{'invisible': [('quality_state', '!=', 'none')]}" string="Pass" data-hotkey="q"/>
|
||||
<button name="do_pass" type="object" attrs="{'invisible': [('quality_state', '!=', 'fail')]}" groups="quality.group_quality_manager" string="Pass" data-hotkey="q"/>
|
||||
<button name="do_fail" type="object" class="btn-primary" attrs="{'invisible': [('quality_state', '!=', 'none')]}" string="Fail" data-hotkey="w"/>
|
||||
<button name="do_fail" type="object" attrs="{'invisible': [('quality_state', '!=', 'pass')]}" groups="quality.group_quality_manager" string="Fail" data-hotkey="w"/>
|
||||
<button name="do_measure" type="object" attrs="{'invisible': ['|', ('test_type', '!=', 'measure'), ('quality_state', '!=', 'none')]}" string="Measure" data-hotkey="v"/>
|
||||
<button name="do_alert" type="object" attrs="{'invisible': ['|', ('alert_ids', '!=', []), ('quality_state', '!=', 'pass')]}" string="Create Alert" data-hotkey="g"/>
|
||||
<button name="do_alert" type="object" class="btn-primary" attrs="{'invisible': ['|', ('alert_ids', '!=', []), ('quality_state', '!=', 'fail')]}" string="Create Alert" data-hotkey="g"/>
|
||||
<field name="quality_state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_see_alerts" icon="fa-bell" type="object" class="oe_stat_button"
|
||||
attrs="{'invisible': [('alert_count', '=', 0)]}">
|
||||
<button name="action_see_alerts" icon="fa-bell" type="object" class="oe_stat_button" attrs="{'invisible': [('alert_count', '=', 0)]}">
|
||||
<field name="alert_count" string="Alerts" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -264,27 +242,21 @@
|
||||
<field name="move_line_id" invisible="1"/>
|
||||
<field name="product_tracking" invisible="1"/>
|
||||
<field name="is_lot_tested_fractionally" invisible="1"/>
|
||||
<field name="lot_name"
|
||||
attrs="{'invisible': ['|', ('product_tracking', '=', 'none'), '|', ('show_lot_text', '=', False), '|', ('measure_on', '!=', 'move_line'), ('move_line_id', '=', False)]}"/>
|
||||
<field name="lot_id"
|
||||
attrs="{'invisible': ['|', ('product_tracking', '=', 'none'), '|', ('show_lot_text', '=', True), ('measure_on', '!=', 'move_line')]}"/>
|
||||
<field name="lot_name" attrs="{'invisible': ['|', ('product_tracking', '=', 'none'), '|', ('show_lot_text', '=', False), '|', ('measure_on', '!=', 'move_line'), ('move_line_id', '=', False)]}"/>
|
||||
<field name="lot_id" attrs="{'invisible': ['|', ('product_tracking', '=', 'none'), '|', ('show_lot_text', '=', True), ('measure_on', '!=', 'move_line')]}"/>
|
||||
<label for="qty_line" attrs="{'invisible': [('move_line_id', '=', False)]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('move_line_id', '=', False)]}">
|
||||
<field name="qty_line"/>
|
||||
<field name="qty_line"/>
|
||||
<field name="uom_id"/>
|
||||
</div>
|
||||
<label for="qty_to_test"
|
||||
attrs="{'invisible': ['|', ('move_line_id', '=', False), '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||
<div class="o_row"
|
||||
attrs="{'invisible': ['|', ('move_line_id', '=', False), '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}">
|
||||
<field name="qty_to_test"/>
|
||||
<label for="qty_to_test" attrs="{'invisible': ['|', ('move_line_id', '=', False), '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||
<div class="o_row" attrs="{'invisible': ['|', ('move_line_id', '=', False), '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}">
|
||||
<field name="qty_to_test"/>
|
||||
<field name="uom_id"/>
|
||||
</div>
|
||||
<label for="qty_tested"
|
||||
attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||
<div class="o_row"
|
||||
attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}">
|
||||
<field name="qty_tested" attrs="{'readonly': [('quality_state', '!=', 'none')]}"/>
|
||||
<label for="qty_tested" attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||
<div class="o_row" attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False)]}">
|
||||
<field name="qty_tested" attrs="{'readonly': [('quality_state', '!=', 'none')]}"/>
|
||||
<field name="uom_id"/>
|
||||
</div>
|
||||
<field name="test_type" invisible="1"/>
|
||||
@@ -292,32 +264,26 @@
|
||||
<field name="alert_ids" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="picking_id"
|
||||
attrs="{'invisible': [('quality_state', 'in', ('pass', 'fail')), ('picking_id', '=', False)]}"/>
|
||||
<field name="picking_id" attrs="{'invisible': [('quality_state', 'in', ('pass', 'fail')), ('picking_id', '=', False)]}"/>
|
||||
<field name="point_id"/>
|
||||
<field string="Type" name="test_type_id" options="{'no_open': True, 'no_create': True}"
|
||||
attrs="{'readonly': [('point_id', '!=', False)]}"/>
|
||||
<field string="Type" name="test_type_id" options="{'no_open': True, 'no_create': True}" attrs="{'readonly': [('point_id', '!=', False)]}"/>
|
||||
<field name="control_date" invisible="1"/>
|
||||
<field name="team_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="user_id" string="Control Person" invisible="1"/>
|
||||
<field name="partner_id" string="Partner"
|
||||
attrs="{'invisible': [('partner_id', '=', False)]}"/>
|
||||
<field name="partner_id" string="Partner" attrs="{'invisible': [('partner_id', '=', False)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('test_type', '!=', 'picture')]}">
|
||||
<field name="picture" widget="image"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes" name="notes">
|
||||
<group>
|
||||
<field name="report_result"/>
|
||||
<field name="report_pdf" widget="pdf_viewer"/>
|
||||
<field string="Instructions" name="note"/>
|
||||
<field string="Notes" name="additional_note"/>
|
||||
|
||||
</group>
|
||||
</page>
|
||||
<notebook>
|
||||
<page string="Notes" name="notes">
|
||||
<group>
|
||||
<field string="Instructions" name="note"/>
|
||||
<field string="Notes" name="additional_note"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
@@ -345,30 +311,18 @@
|
||||
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<strong>
|
||||
<span>
|
||||
<t t-esc="record.name.value"/>
|
||||
</span>
|
||||
</strong>
|
||||
<strong><span><t t-esc="record.name.value"/></span></strong>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<strong>
|
||||
<span t-attf-class="float-end text-end badge #{['none'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-secondary' : ['fail'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-danger' : ['done'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-primary' : 'text-bg-success'}">
|
||||
<t t-esc="record.quality_state.value"/>
|
||||
</span>
|
||||
</strong>
|
||||
<strong><span t-attf-class="float-end text-end badge #{['none'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-secondary' : ['fail'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-danger' : ['done'].indexOf(record.quality_state.raw_value) > -1 ? 'text-bg-primary' : 'text-bg-success'}"><t t-esc="record.quality_state.value"/></span></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row text-muted">
|
||||
<div class="col-8">
|
||||
<span>
|
||||
<t t-esc="record.product_id.value"/>
|
||||
</span>
|
||||
<span><t t-esc="record.product_id.value"/></span>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<span>
|
||||
<t t-esc="record.lot_id.value"/>
|
||||
</span>
|
||||
<span><t t-esc="record.lot_id.value"/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_kanban_bottom_right float-end">
|
||||
@@ -396,8 +350,7 @@
|
||||
<field name="user_id" string="Checked By" optional="show" widget='many2one_avatar_user'/>
|
||||
<field name="point_id" optional="hide"/>
|
||||
<field name="team_id" optional="show"/>
|
||||
<field name="quality_state" optional="show" widget='badge' decoration-success="quality_state == 'pass'"
|
||||
decoration-info="quality_state == 'none'" decoration-danger="quality_state == 'fail'"/>
|
||||
<field name="quality_state" optional="show" widget='badge' decoration-success="quality_state == 'pass'" decoration-info="quality_state == 'none'" decoration-danger="quality_state == 'fail'"/>
|
||||
<field name="company_id" groups="base.main_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -415,14 +368,14 @@
|
||||
</record>
|
||||
|
||||
<record id="quality_check_view_pivot" model="ir.ui.view">
|
||||
<field name="name">quality.check.view.pivot</field>
|
||||
<field name="model">quality.check</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Quality Check Analysis" sample="1">
|
||||
<field name="control_date" type="col" interval="day"/>
|
||||
<field name="product_id" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
<field name="name">quality.check.view.pivot</field>
|
||||
<field name="model">quality.check</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Quality Check Analysis" sample="1">
|
||||
<field name="control_date" type="col" interval="day"/>
|
||||
<field name="product_id" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_check_view_search" model="ir.ui.view">
|
||||
@@ -430,8 +383,7 @@
|
||||
<field name="model">quality.check</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="product_id" string="Product"
|
||||
filter_domain="['|', ('product_id', 'ilike', self), ('lot_id', 'ilike', self)]"/>
|
||||
<field name="product_id" string="Product" filter_domain="['|', ('product_id', 'ilike', self), ('lot_id', 'ilike', self)]"/>
|
||||
<field name="picking_id"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="team_id"/>
|
||||
@@ -474,11 +426,10 @@
|
||||
</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No quality check found
|
||||
</p>
|
||||
<p>
|
||||
Define Quality Control Points in order to automatically generate
|
||||
quality checks at the right logistic operation: transfers, manufacturing orders.
|
||||
No quality check found
|
||||
</p><p>
|
||||
Define Quality Control Points in order to automatically generate
|
||||
quality checks at the right logistic operation: transfers, manufacturing orders.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -507,11 +458,10 @@
|
||||
<field name="view_mode">tree,kanban,form,pivot,graph</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No quality check found
|
||||
</p>
|
||||
<p>
|
||||
Define Quality Control Points in order to automatically generate
|
||||
quality checks at the right logistic operation: transfers, manufacturing orders.
|
||||
No quality check found
|
||||
</p><p>
|
||||
Define Quality Control Points in order to automatically generate
|
||||
quality checks at the right logistic operation: transfers, manufacturing orders.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -535,25 +485,17 @@
|
||||
<field name="inherit_id" ref="stock.product_template_form_view_procurement_button"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='action_view_related_putaway_rules']" position="after">
|
||||
<button name="action_see_quality_control_points" type="object" class="oe_stat_button" icon="fa-list"
|
||||
attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}"
|
||||
groups="quality.group_quality_user">
|
||||
<button name="action_see_quality_control_points" type="object" class="oe_stat_button" icon="fa-list" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}" groups="quality.group_quality_user">
|
||||
<field string="Quality Points" name="quality_control_point_qty" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="action_see_quality_checks" type="object" class="oe_stat_button" icon="fa-check"
|
||||
attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('quality_pass_qty', '=', 0),('quality_fail_qty', '=', 0)]}"
|
||||
groups="quality.group_quality_user">
|
||||
<button name="action_see_quality_checks" type="object" class="oe_stat_button" icon="fa-check" attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('quality_pass_qty', '=', 0),('quality_fail_qty', '=', 0)]}" groups="quality.group_quality_user">
|
||||
<div class="o_field_widget o_stat_info mr4">
|
||||
<span class="o_stat_text">Pass:</span>
|
||||
<span class="o_stat_text">Fail:</span>
|
||||
</div>
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="quality_pass_qty"/>
|
||||
</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="quality_fail_qty"/>
|
||||
</span>
|
||||
<span class="o_stat_value"><field name="quality_pass_qty"/></span>
|
||||
<span class="o_stat_value"><field name="quality_fail_qty"/></span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
@@ -567,25 +509,17 @@
|
||||
<field name="inherit_id" ref="stock.product_form_view_procurement_button"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='action_view_related_putaway_rules']" position="after">
|
||||
<button name="action_see_quality_control_points" type="object" icon="fa-list" class="oe_stat_button"
|
||||
attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}"
|
||||
groups="quality.group_quality_user">
|
||||
<button name="action_see_quality_control_points" type="object" icon="fa-list" class="oe_stat_button" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}" groups="quality.group_quality_user">
|
||||
<field string="Quality Points" name="quality_control_point_qty" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="action_see_quality_checks" type="object" class="oe_stat_button" icon="fa-check"
|
||||
groups="quality.group_quality_user"
|
||||
attrs="{'invisible':[ ('quality_pass_qty', '=', 0),('quality_fail_qty', '=', 0)]}">
|
||||
<button name="action_see_quality_checks" type="object" class="oe_stat_button" icon="fa-check" groups="quality.group_quality_user" attrs="{'invisible':[ ('quality_pass_qty', '=', 0),('quality_fail_qty', '=', 0)]}" >
|
||||
<div class="o_field_widget o_stat_info mr4">
|
||||
<span class="o_stat_text">Pass:</span>
|
||||
<span class="o_stat_text">Fail:</span>
|
||||
</div>
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="quality_pass_qty"/>
|
||||
</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="quality_fail_qty"/>
|
||||
</span>
|
||||
<span class="o_stat_value"><field name="quality_pass_qty"/></span>
|
||||
<span class="o_stat_value"><field name="quality_fail_qty"/></span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
@@ -599,8 +533,8 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="%(quality_check_action_production_lot)d" type="action"
|
||||
attrs="{'invisible': [('quality_check_qty', '=', 0)]}"
|
||||
icon="fa-check" class="oe_stat_button" groups="quality.group_quality_user">
|
||||
attrs="{'invisible': [('quality_check_qty', '=', 0)]}"
|
||||
icon="fa-check" class="oe_stat_button" groups="quality.group_quality_user">
|
||||
<field string="Quality Checks" name="quality_check_qty" widget="statinfo"/>
|
||||
</button>
|
||||
</xpath>
|
||||
@@ -623,36 +557,24 @@
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="#{kanban_color(record.color.raw_value)}">
|
||||
<span class="oe_kanban_color_help"
|
||||
t-attf-title="In #{kanban_getcolorname(record.color.raw_value)}" role="img"
|
||||
t-attf-aria-label="In #{kanban_getcolorname(record.color.raw_value)}"/>
|
||||
<span class="oe_kanban_color_help" t-attf-title="In #{kanban_getcolorname(record.color.raw_value)}" role="img" t-attf-aria-label="In #{kanban_getcolorname(record.color.raw_value)}"/>
|
||||
<div t-attf-class="o_kanban_card_header">
|
||||
<div class="o_kanban_card_header_title">
|
||||
<div class="o_primary">
|
||||
<field name="name"/>
|
||||
</div>
|
||||
<div class="o_primary"><field name="name"/></div>
|
||||
<div t-if="record.alias_name.value and record.alias_domain.value">
|
||||
<small><i class="fa fa-envelope-o" role="img" aria-label="Domain alias"
|
||||
title="Domain alias"></i>&nbsp;
|
||||
<field name="alias_id"/>
|
||||
</small>
|
||||
<small><i class="fa fa-envelope-o" role="img" aria-label="Domain alias" title="Domain alias"></i>&nbsp; <field name="alias_id"/></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container o_kanban_card_content">
|
||||
<div class="row">
|
||||
<div class="col-6 o_kanban_primary_left">
|
||||
<button class="btn btn-primary" name="%(quality_alert_action_team)d"
|
||||
type="action">
|
||||
<span>
|
||||
<field name="alert_count"/>
|
||||
Quality Alerts
|
||||
</span>
|
||||
<button class="btn btn-primary" name="%(quality_alert_action_team)d" type="action">
|
||||
<span><field name="alert_count"/> Quality Alerts</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 o_kanban_primary_right">
|
||||
<a class="oe_kanban_stock_picking_type_list"
|
||||
name="%(quality_check_action_team)d" type="action">
|
||||
<a class="oe_kanban_stock_picking_type_list" name="%(quality_check_action_team)d" type="action">
|
||||
<field name="check_count"/>
|
||||
Checks In Progress
|
||||
</a>
|
||||
@@ -663,14 +585,11 @@
|
||||
<div t-if="widget.editable" role="menuitem">
|
||||
<a class="dropdown-item ps-0" type="edit">Configuration</a>
|
||||
</div>
|
||||
<div t-if="widget.editable" role="menuitem" aria-haspopup="true"
|
||||
class="o_no_padding_kanban_colorpicker">
|
||||
<div t-if="widget.editable" role="menuitem" aria-haspopup="true" class="o_no_padding_kanban_colorpicker">
|
||||
<ul class="oe_kanban_colorpicker" data-field="color" role="popup"/>
|
||||
</div>
|
||||
</div>
|
||||
<a class="o_kanban_manage_toggle_button o_left" href="#">
|
||||
<i class="fa fa-ellipsis-v" role="img" aria-label="Manage" title="Manage"/>
|
||||
</a>
|
||||
<a class="o_kanban_manage_toggle_button o_left" href="#"><i class="fa fa-ellipsis-v" role="img" aria-label="Manage" title="Manage"/></a>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -683,7 +602,6 @@
|
||||
<field name="model">quality.alert.team</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header></header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Team Name"/>
|
||||
@@ -696,14 +614,13 @@
|
||||
<label for="alias_name" string="Email Alias"/>
|
||||
<div name="alias_def">
|
||||
<field name="alias_id" class="oe_read_only oe_inline"
|
||||
string="Email Alias" required="0"/>
|
||||
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;">
|
||||
<field name="alias_name" class="oe_inline"/>@
|
||||
<field name="alias_domain" class="oe_inline" readonly="1"/>
|
||||
string="Email Alias" required="0"/>
|
||||
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
|
||||
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="alias_contact" class="oe_inline" groups="base.group_no_one"
|
||||
string="Accept Emails From"/>
|
||||
string="Accept Emails From"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
@@ -740,9 +657,7 @@
|
||||
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<strong>
|
||||
<field name="name"/>
|
||||
</strong>
|
||||
<strong><field name="name"/></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -756,15 +671,14 @@
|
||||
<field name="name">Quality Overview</field>
|
||||
<field name="res_model">quality.alert.team</field>
|
||||
<field name="view_mode">kanban,form</field>
|
||||
<field name="view_id" ref="quality_alert_team_dashboard_view_kanban"/>
|
||||
<field name="view_id" ref="quality_alert_team_dashboard_view_kanban" />
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
</p><p>
|
||||
Quality Teams group the different quality alerts/checks
|
||||
according to the roles (teams) that need them.
|
||||
</p>
|
||||
<p>
|
||||
Quality Teams group the different quality alerts/checks
|
||||
according to the roles (teams) that need them.
|
||||
</p>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_alert_team_action_config" model="ir.actions.act_window">
|
||||
@@ -801,9 +715,9 @@
|
||||
<field name="res_model">quality.tag</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new tag
|
||||
</p>
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new tag
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -832,9 +746,7 @@
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click">
|
||||
<div>
|
||||
<strong>
|
||||
<field name="name"/>
|
||||
</strong>
|
||||
<strong><field name="name"/></strong>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
@@ -850,9 +762,8 @@
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new quality alert stage
|
||||
</p>
|
||||
<p>
|
||||
Quality Alert stages define the different steps a quality alert should go through.
|
||||
</p><p>
|
||||
Quality Alert stages define the different steps a quality alert should go through.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -904,19 +815,9 @@
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
|
||||
<div>
|
||||
<strong>
|
||||
<t t-esc="record.name.value"/>
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Products :</strong>
|
||||
<t t-esc="record.product_ids.value"/>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Operations :</strong>
|
||||
<t t-esc="record.picking_type_ids.value"/>
|
||||
</div>
|
||||
<div><strong><t t-esc="record.name.value"/></strong></div>
|
||||
<div><strong>Products :</strong> <t t-esc="record.product_ids.value"/></div>
|
||||
<div><strong>Operations :</strong> <t t-esc="record.picking_type_ids.value"/></div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -934,54 +835,39 @@
|
||||
<field string="Quality Checks" name="check_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="action_see_spc_control" type="object" class="oe_stat_button"
|
||||
attrs="{'invisible': ['|', ('check_count', '=', 0), ('test_type', '!=', 'measure')]}">
|
||||
<span class="fa fa-2x" data-icon="∑" style="padding-left: 10px;" role="img"
|
||||
aria-label="Statistics" title="Statistics"/>
|
||||
attrs="{'invisible': ['|', ('check_count', '=', 0), ('test_type', '!=', 'measure')]}">
|
||||
<span class="fa fa-2x" data-icon="∑" style="padding-left: 10px;" role="img" aria-label="Statistics" title="Statistics"/>
|
||||
<div class="o_field_widget o_stat_info mr4">
|
||||
<span class="o_stat_text">AVG:</span>
|
||||
<span class="o_stat_text">STD:</span>
|
||||
</div>
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="average"/>
|
||||
</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="standard_deviation"/>
|
||||
</span>
|
||||
<span class="o_stat_value"><field name="average"/></span>
|
||||
<span class="o_stat_value"><field name="standard_deviation"/></span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='instructions']" position="after">
|
||||
<page string="Message If Failure" name="message_if_failure"
|
||||
attrs="{'invisible': [('test_type', 'in', ['picture', 'instructions', 'register_consumed_materials', 'print_label'])]}">
|
||||
attrs="{'invisible': [('test_type', 'in', ['picture', 'instructions', 'register_consumed_materials', 'print_label'])]}">
|
||||
<field name="failure_message"/>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='test_type']" position="before">
|
||||
<field name="measure_on"/>
|
||||
<field name="measure_frequency_type" string="Control Frequency"/>
|
||||
<label for="measure_frequency_value" string=""
|
||||
attrs="{'invisible': [('measure_frequency_type', '=', 'all')]}"/>
|
||||
<label for="measure_frequency_value" string="" attrs="{'invisible': [('measure_frequency_type', '=', 'all')]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('measure_frequency_type', '=', 'all')]}">
|
||||
<span attrs="{'invisible': [('measure_frequency_type', '=', 'all')]}">Every</span>
|
||||
<field name="measure_frequency_value" nolabel="1"
|
||||
attrs="{'invisible': [('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<label for="measure_frequency_value" string="% of Operations"
|
||||
attrs="{'invisible': ['|', ('measure_on', '=', 'move_line'), ('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<label for="measure_frequency_value" string="% of Transfers"
|
||||
attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<field name="measure_frequency_unit_value" string="Frequency" nolabel="1"
|
||||
attrs="{'invisible': [('measure_frequency_type', '!=', 'periodical')]}"/>
|
||||
<field name="measure_frequency_unit"
|
||||
attrs="{'invisible': [('measure_frequency_type', '!=', 'periodical')], 'required': [('measure_frequency_type', '=', 'periodical')]}"/>
|
||||
<span attrs="{'invisible': [('measure_frequency_type', '=', 'all')]}">Every </span>
|
||||
<field name="measure_frequency_value" nolabel="1" attrs="{'invisible': [('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<label for="measure_frequency_value" string="% of Operations" attrs="{'invisible': ['|', ('measure_on', '=', 'move_line'), ('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<label for="measure_frequency_value" string="% of Transfers" attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('measure_frequency_type', '!=', 'random')]}"/>
|
||||
<field name="measure_frequency_unit_value" string="Frequency" nolabel="1" attrs="{'invisible': [('measure_frequency_type', '!=', 'periodical')]}"/>
|
||||
<field name="measure_frequency_unit" attrs="{'invisible': [('measure_frequency_type', '!=', 'periodical')], 'required': [('measure_frequency_type', '=', 'periodical')]}"/>
|
||||
</div>
|
||||
<field name="is_lot_tested_fractionally" attrs="{'invisible': [('measure_on', '!=', 'move_line')]}"
|
||||
string="Partial Transfer Test"/>
|
||||
<label for="testing_percentage_within_lot"
|
||||
attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '!=', True)]}"
|
||||
string="Percentage"/>
|
||||
<div class="o_row"
|
||||
attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '!=', True)]}">
|
||||
<field name="is_lot_tested_fractionally" attrs="{'invisible': [('measure_on', '!=', 'move_line')]}" string="Partial Transfer Test"/>
|
||||
<label for="testing_percentage_within_lot" attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '!=', True)]}" string="Percentage"/>
|
||||
<div class="o_row" attrs="{'invisible': ['|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '!=', True)]}">
|
||||
<field name="testing_percentage_within_lot" nolabel="1"/>
|
||||
<label for="testing_percentage_within_lot" string="%"/>
|
||||
</div>
|
||||
@@ -990,15 +876,12 @@
|
||||
<label for="norm" attrs="{'invisible': [('test_type', '!=', 'measure')]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('test_type', '!=', 'measure')]}">
|
||||
<field name="norm" attrs="{'required': [('test_type', '=', 'measure')]}"/>
|
||||
<field name="norm_unit" string="Unit of Measure"
|
||||
attrs="{'required': [('test_type', '=', 'measure')]}"/>
|
||||
<field name="norm_unit" string="Unit of Measure" attrs="{'required': [('test_type', '=', 'measure')]}"/>
|
||||
</div>
|
||||
<label for="tolerance_min" string="Tolerance" attrs="{'invisible': [('test_type', '!=', 'measure')]}"/>
|
||||
<div attrs="{'invisible': [('test_type', '!=', 'measure')]}" class="o_row">
|
||||
<span>from</span>
|
||||
<field name="tolerance_min"/>
|
||||
<span>to</span>
|
||||
<field name="tolerance_max"/>
|
||||
<span>from </span> <field name="tolerance_min"/>
|
||||
<span>to </span> <field name="tolerance_max"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
@@ -1011,96 +894,95 @@
|
||||
<field name="search_view_id" ref="quality_point_view_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No quality control point found
|
||||
</p>
|
||||
<p>
|
||||
Quality control points define the quality checks which should be
|
||||
performed at each operation, for your different products.
|
||||
No quality control point found
|
||||
</p><p>
|
||||
Quality control points define the quality checks which should be
|
||||
performed at each operation, for your different products.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Menu structure-->
|
||||
<menuitem
|
||||
id="menu_quality_root"
|
||||
name="Quality"
|
||||
web_icon="quality_control,static/description/icon.svg"
|
||||
sequence="150"
|
||||
groups="quality.group_quality_user"/>
|
||||
id="menu_quality_root"
|
||||
name="Quality"
|
||||
web_icon="quality_control,static/description/icon.svg"
|
||||
sequence="150"
|
||||
groups="quality.group_quality_user"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_dashboard"
|
||||
name="Overview"
|
||||
action="quality_alert_team_action"
|
||||
parent="menu_quality_root"
|
||||
sequence="5"/>
|
||||
id="menu_quality_dashboard"
|
||||
name="Overview"
|
||||
action="quality_alert_team_action"
|
||||
parent="menu_quality_root"
|
||||
sequence="5"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_control"
|
||||
name="Quality Control"
|
||||
parent="menu_quality_root"
|
||||
sequence="15"/>
|
||||
id="menu_quality_control"
|
||||
name="Quality Control"
|
||||
parent="menu_quality_root"
|
||||
sequence="15"/>
|
||||
<menuitem
|
||||
id="menu_quality_control_points"
|
||||
name="Control Points"
|
||||
parent="menu_quality_control"
|
||||
action="quality_point_action"
|
||||
groups="quality.group_quality_manager"
|
||||
sequence="17"/>
|
||||
id="menu_quality_control_points"
|
||||
name="Control Points"
|
||||
parent="menu_quality_control"
|
||||
action="quality_point_action"
|
||||
groups="quality.group_quality_manager"
|
||||
sequence="17"/>
|
||||
<menuitem
|
||||
id="menu_quality_checks"
|
||||
name="Quality Checks"
|
||||
action="quality_check_action_main"
|
||||
parent="menu_quality_control"
|
||||
sequence="18"/>
|
||||
id="menu_quality_checks"
|
||||
name="Quality Checks"
|
||||
action="quality_check_action_main"
|
||||
parent="menu_quality_control"
|
||||
sequence="18"/>
|
||||
<menuitem
|
||||
id="menu_quality_alert"
|
||||
name="Quality Alerts"
|
||||
action="quality_alert_action_check"
|
||||
parent="menu_quality_control"
|
||||
sequence="20"/>
|
||||
id="menu_quality_alert"
|
||||
name="Quality Alerts"
|
||||
action="quality_alert_action_check"
|
||||
parent="menu_quality_control"
|
||||
sequence="20"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_configuration"
|
||||
name="Configuration"
|
||||
groups="quality.group_quality_manager"
|
||||
parent="menu_quality_root"
|
||||
sequence="25"/>
|
||||
id="menu_quality_configuration"
|
||||
name="Configuration"
|
||||
groups="quality.group_quality_manager"
|
||||
parent="menu_quality_root"
|
||||
sequence="25"/>
|
||||
<menuitem
|
||||
id="menu_quality_config_alert_team"
|
||||
name="Quality Teams"
|
||||
action="quality_alert_team_action_config"
|
||||
parent="menu_quality_configuration"
|
||||
sequence="5"/>
|
||||
id="menu_quality_config_alert_team"
|
||||
name="Quality Teams"
|
||||
action="quality_alert_team_action_config"
|
||||
parent="menu_quality_configuration"
|
||||
sequence="5"/>
|
||||
<menuitem
|
||||
id="menu_quality_config_alert_stage"
|
||||
name="Quality Alert Stages"
|
||||
action="quality_alert_stage_action"
|
||||
parent="menu_quality_configuration"
|
||||
groups="base.group_no_one"
|
||||
sequence="15"/>
|
||||
id="menu_quality_config_alert_stage"
|
||||
name="Quality Alert Stages"
|
||||
action="quality_alert_stage_action"
|
||||
parent="menu_quality_configuration"
|
||||
groups="base.group_no_one"
|
||||
sequence="15"/>
|
||||
<menuitem
|
||||
id="menu_config_quality_tags"
|
||||
name="Quality Tags"
|
||||
groups="base.group_no_one"
|
||||
action="quality_tag_action"
|
||||
parent="menu_quality_configuration"
|
||||
sequence="25"/>
|
||||
id="menu_config_quality_tags"
|
||||
name="Quality Tags"
|
||||
groups="base.group_no_one"
|
||||
action="quality_tag_action"
|
||||
parent="menu_quality_configuration"
|
||||
sequence="25"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_reporting"
|
||||
name="Reporting"
|
||||
groups="quality.group_quality_manager"
|
||||
parent="menu_quality_root"
|
||||
sequence="20"/>
|
||||
id="menu_quality_reporting"
|
||||
name="Reporting"
|
||||
groups="quality.group_quality_manager"
|
||||
parent="menu_quality_root"
|
||||
sequence="20"/>
|
||||
<menuitem
|
||||
id="menu_quality_alert_report"
|
||||
action="quality_alert_action_report"
|
||||
parent="menu_quality_reporting"
|
||||
sequence="6"/>
|
||||
id="menu_quality_alert_report"
|
||||
action="quality_alert_action_report"
|
||||
parent="menu_quality_reporting"
|
||||
sequence="6"/>
|
||||
<menuitem
|
||||
id="menu_quality_check_report"
|
||||
action="quality_check_action_report"
|
||||
parent="menu_quality_reporting"
|
||||
sequence="5"/>
|
||||
id="menu_quality_check_report"
|
||||
action="quality_check_action_report"
|
||||
parent="menu_quality_reporting"
|
||||
sequence="5"/>
|
||||
</odoo>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
from . import models
|
||||
from . import commons
|
||||
from . import controllers
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['base', 'mrp_workorder', 'sale', 'purchase', 'sales_team'],
|
||||
'depends': ['account', 'base', 'mrp_workorder', 'sale'],
|
||||
'data': [
|
||||
'security/group_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
@@ -19,12 +19,9 @@
|
||||
'views/fixture_view.xml',
|
||||
'views/functional_fixture_view.xml',
|
||||
'views/menu_view.xml',
|
||||
'views/tool_views.xml',
|
||||
'views/tool_basic_param.xml',
|
||||
'views/tool_menu.xml',
|
||||
"views/tool_views.xml",
|
||||
"views/tool_menu.xml",
|
||||
'views/menu_fixture_view.xml',
|
||||
'views/change_base_view.xml',
|
||||
'views/Printer.xml',
|
||||
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class Printer(models.Model):
|
||||
_name = 'printer'
|
||||
_description = 'Printer'
|
||||
|
||||
name = fields.Char(string='名称', required=True)
|
||||
ip_address = fields.Char(string='IP 地址', required=True)
|
||||
port = fields.Integer(string='端口', default=9100)
|
||||
|
||||
|
||||
class TableStyle(models.Model):
|
||||
_name = 'table.style'
|
||||
_description = '标签样式'
|
||||
|
||||
name = fields.Char(string='名称', required=True)
|
||||
# todo
|
||||
|
||||
|
||||
class PrinterConfiguration(models.Model):
|
||||
_name = 'printer.configuration'
|
||||
_description = 'Printer Configuration'
|
||||
|
||||
name = fields.Char(string='名称', required=True)
|
||||
printer_id = fields.Many2one('printer', string='打印机')
|
||||
model = fields.Many2one('ir.model', string='模型名称')
|
||||
# # 其他相关字段...
|
||||
@@ -1,2 +1 @@
|
||||
from . import common
|
||||
from . import Printer
|
||||
from. import common
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import time, datetime
|
||||
import hashlib
|
||||
from odoo import models
|
||||
import socket
|
||||
import time
|
||||
import hashlib
|
||||
|
||||
|
||||
class Common(models.Model):
|
||||
_name = 'sf.sync.common'
|
||||
_description = u'公用类'
|
||||
|
||||
def get_headers(self, token, secret_key):
|
||||
def get_headers(self,token, secret_key):
|
||||
'''
|
||||
获取requests中的heardes参数
|
||||
'''
|
||||
@@ -20,75 +20,4 @@ class Common(models.Model):
|
||||
'checkstr': check_sf_str}
|
||||
return headers
|
||||
|
||||
def get_add_time(self, parse_time):
|
||||
"""
|
||||
把时间增加8小时
|
||||
:return:
|
||||
"""
|
||||
dt = datetime.datetime.strptime(parse_time, "%Y-%m-%d %H:%M:%S")
|
||||
d = dt + datetime.timedelta(hours=8)
|
||||
nTime = d.strftime("%Y-%m-%d %H:%M:%S")
|
||||
return nTime
|
||||
|
||||
|
||||
class PrintingUtils(models.AbstractModel):
|
||||
_name = 'printing.utils'
|
||||
_description = 'Utility class for printing functionalities'
|
||||
|
||||
def generate_zpl_code(self, code):
|
||||
# 实现生成ZPL代码的逻辑
|
||||
# 初始化ZPL代码字符串
|
||||
zpl_code = "^XA\n"
|
||||
zpl_code += "^CW1,E:SIMSUN.TTF^FS\n"
|
||||
zpl_code += "^CI28\n"
|
||||
|
||||
# 设置二维码位置
|
||||
zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行
|
||||
zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n"
|
||||
|
||||
# 设置资产编号文本位置
|
||||
zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
|
||||
zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
|
||||
|
||||
# 设置{code}文本位置
|
||||
# 假设{code}文本需要位于资产编号和二维码下方,中间位置
|
||||
# 设置{code}文本位置并启用自动换行
|
||||
zpl_code += "^FO300,120\n" # {code}文本的起始位置
|
||||
zpl_code += "^FB400,4,0,L,0\n" # 定义一个宽度为500点的文本框,最多4行,左对齐
|
||||
zpl_code += f"^A1N,40,40^FD{code}^FS\n"
|
||||
|
||||
# 在{code}文本框周围绘制线框
|
||||
# 假设线框的外部尺寸为宽度500点,高度200点
|
||||
# zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框,边框粗细为2点
|
||||
|
||||
zpl_code += "^PQ1,0,1,Y\n"
|
||||
zpl_code += "^XZ\n"
|
||||
return zpl_code
|
||||
|
||||
def send_to_printer(self, host, port, zpl_code):
|
||||
|
||||
# 实现发送ZPL代码到打印机的逻辑
|
||||
# 将ZPL代码转换为字节串
|
||||
print('zpl_code', zpl_code)
|
||||
zpl_bytes = zpl_code.encode('utf-8')
|
||||
print(zpl_bytes)
|
||||
|
||||
# 创建socket对象
|
||||
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
mysocket.connect((host, port)) # 连接到打印机
|
||||
mysocket.send(zpl_bytes) # 发送ZPL代码
|
||||
print("ZPL code sent to printer successfully.")
|
||||
except Exception as e:
|
||||
print(f"Error with the connection: {e}")
|
||||
finally:
|
||||
mysocket.close() # 关闭连接
|
||||
|
||||
def print_qr_code(self, lot_name, host, port):
|
||||
# 实现打印二维码的逻辑
|
||||
# 这里需要传入 lot_name 参数,因为我们不能直接访问 self.lot_id.name
|
||||
zpl_code = self.generate_zpl_code(lot_name)
|
||||
# 发送ZPL代码到打印机
|
||||
# host = "192.168.50.110" # 可以作为参数传入,或者在此配置
|
||||
# port = 9100 # 可以作为参数传入,或者在此配置
|
||||
self.send_to_printer(host, port, zpl_code)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from . import controllers
|
||||
@@ -1,40 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import json
|
||||
import base64
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class Manufacturing_Connect(http.Controller):
|
||||
|
||||
@http.route('/AutoDeviceApi/MachineToolGroup', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def get_maintenance_tool_groups_Info(self, **kw):
|
||||
"""
|
||||
机床刀具组接口
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
logging.info('get_maintenance_tool_groups_Info:%s' % kw)
|
||||
try:
|
||||
datas = request.httprequest.data
|
||||
ret = json.loads(datas)
|
||||
# ret = json.loads(ret['result'])
|
||||
logging.info('DeviceId:%s' % ret)
|
||||
tool_groups = request.env['sf.tool.groups'].sudo().search([])
|
||||
|
||||
res = {'Succeed': True, 'Datas': []}
|
||||
if tool_groups:
|
||||
for item in tool_groups:
|
||||
device_id = ''
|
||||
for equipment_id in item.equipment_ids:
|
||||
device_id = '%s,%s' % (device_id, equipment_id.name)
|
||||
res['Datas'].append({
|
||||
'GroupName': item.name,
|
||||
'DeviceId': device_id
|
||||
})
|
||||
except Exception as e:
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
||||
logging.info('get_maintenance_tool_groups_Info error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||