Compare commits
4 Commits
feature/产品
...
2b7f4c3f06
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b7f4c3f06 | ||
|
|
26de811174 | ||
|
|
d023848c70 | ||
|
|
a109c0fb39 |
@@ -10,7 +10,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['web', 'purchase'],
|
'depends': ['web'],
|
||||||
'data': [
|
'data': [
|
||||||
|
|
||||||
],
|
],
|
||||||
@@ -22,22 +22,11 @@
|
|||||||
],
|
],
|
||||||
'web.assets_backend': [
|
'web.assets_backend': [
|
||||||
'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*',
|
'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*',
|
||||||
'jikimo_frontend/static/src/fields/Many2OneRadioField/*',
|
|
||||||
'jikimo_frontend/static/src/scss/custom_style.scss',
|
'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_nbCols.js',
|
||||||
'jikimo_frontend/static/src/views/list_nums/list_nums.xml',
|
'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_nums2.xml',
|
||||||
'jikimo_frontend/static/src/views/list_nums/list_nums3.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,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 img = event.target;
|
||||||
const close = img.nextSibling;
|
const close = img.nextSibling
|
||||||
|
|
||||||
// 实现放大图片逻辑
|
// 实现放大图片逻辑
|
||||||
// 比如使用 CSS 放大
|
// 比如使用 CSS 放大
|
||||||
img.parentElement.classList.add('zoomed');
|
img.parentElement.classList.add('zoomed');
|
||||||
close.classList.add('img_close');
|
close.classList.add('img_close')
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloseClick(event) {
|
onCloseClick(event) {
|
||||||
const close = event.target;
|
const close = event.target;
|
||||||
const img = close.previousSibling;
|
const img = close.previousSibling
|
||||||
img.parentElement.classList.remove('zoomed');
|
img.parentElement.classList.remove('zoomed')
|
||||||
close.classList.remove('img_close');
|
close.classList.remove('img_close')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget";
|
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget"
|
||||||
// MyCustomWidget.supportedTypes = ['many2many'];
|
// MyCustomWidget.supportedTypes = ['many2many'];
|
||||||
|
|
||||||
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);
|
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +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";
|
|
||||||
|
|
||||||
var Dialog = require('web.Dialog');
|
|
||||||
// var {patch} = require("web.utils") 这句话也行
|
|
||||||
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$(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('取消')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -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,36 +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';
|
|
||||||
|
|
||||||
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 (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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
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: 1.5rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-image div {
|
.my-image div {
|
||||||
|
|
||||||
width: 110px !important;
|
width: 110px !important;
|
||||||
height: 110px !important;
|
height: 110px !important;
|
||||||
}
|
}
|
||||||
@@ -79,9 +72,9 @@ td.o_required_modifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.oe_kanban_card.kanban_color_1 {
|
.oe_kanban_card.kanban_color_1 {
|
||||||
background-color: #fff !important;
|
background-color: #27FEA9 !important;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
color: #777;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oe_kanban_card.kanban_color_3 {
|
.oe_kanban_card.kanban_color_3 {
|
||||||
@@ -135,7 +128,7 @@ td.o_required_modifier {
|
|||||||
.text-truncate {
|
.text-truncate {
|
||||||
overflow: unset !important;
|
overflow: unset !important;
|
||||||
text-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) {
|
.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 {
|
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
//top: -52px;
|
top: -52px;
|
||||||
//left: -55px;
|
left: 3rem;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,16 +246,16 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
||||||
// position: absolute;
|
position: absolute;
|
||||||
// top: 55px;
|
top: 55px;
|
||||||
// right: 43.5%;
|
right: 43.5%;
|
||||||
//}
|
}
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
|
|
||||||
.test_model > .o_form_label {
|
.test_model > .o_form_label {
|
||||||
margin-left: 4px !important;
|
margin-left: 4px !important;
|
||||||
//line-height: 0 !important;
|
line-height: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1200px) {
|
@media screen and (min-width: 1200px) {
|
||||||
@@ -270,10 +263,10 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
|||||||
right: 52%;
|
right: 52%;
|
||||||
}
|
}
|
||||||
|
|
||||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||||
//
|
|
||||||
// left: -95px;
|
left: -4.4rem;
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -318,135 +311,27 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
|||||||
.o_horizontal_separator {
|
.o_horizontal_separator {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//.o_field_widget input[class='o_input'] {
|
.o_field_widget input[class='o_input'] {
|
||||||
//text-align: center
|
text-align: center
|
||||||
//}
|
}
|
||||||
|
|
||||||
div:has(.o_required_modifier) > label::before {
|
div:has(.o_required_modifier) > label::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -3px;
|
left: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
//.o_form_view .o_form_label {
|
.o_form_view .o_form_label {
|
||||||
// position: relative;
|
position: relative;
|
||||||
// width: 9rem;
|
width: 9rem;
|
||||||
// overflow: hidden;
|
overflow: hidden;
|
||||||
// text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
// white-space: nowrap;
|
white-space: nowrap;
|
||||||
// padding-left: 1rem;
|
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:hover {
|
||||||
// 2023-11-16 hy 新增
|
white-space: normal;
|
||||||
.o_kanban_card_content .btn-group {
|
overflow: visible;
|
||||||
position: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
const nbCols = this._super(...arguments);
|
||||||
return nbCols + 1;
|
return nbCols + 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<t t-name="og.web.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="extension">
|
<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">
|
<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>
|
</xpath>
|
||||||
</t>
|
</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,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 {
|
.o_form_view {
|
||||||
//background-color: unset !important;
|
background-color: unset !important;
|
||||||
min-height: unset !important;
|
min-height: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,9 @@
|
|||||||
<xpath expr="//field[@name='state']" position="after">
|
<xpath expr="//field[@name='state']" position="after">
|
||||||
<field name="production_state" invisible="1"/>
|
<field name="production_state" invisible="1"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<!-- <xpath expr="//button[@name='action_open_wizard']" position="after">-->
|
<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')]}"/>-->
|
<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>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ csv_internal_sep = ,
|
|||||||
data_dir = /var/lib/odoo
|
data_dir = /var/lib/odoo
|
||||||
db_host = 172.17.0.2
|
db_host = 172.17.0.2
|
||||||
db_maxconn = 64
|
db_maxconn = 64
|
||||||
db_name = sf_t2cs_003
|
db_name = sf_cs_dev937
|
||||||
db_password = sf
|
db_password = sf
|
||||||
db_port = 5432
|
db_port = 5432
|
||||||
db_sslmode = prefer
|
db_sslmode = prefer
|
||||||
db_template = template0
|
db_template = template0
|
||||||
db_user = sf
|
db_user = sf
|
||||||
dbfilter =
|
dbfilter =
|
||||||
without_demo = all
|
demo = {}
|
||||||
email_from = False
|
email_from = False
|
||||||
from_filter = False
|
from_filter = False
|
||||||
geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb
|
geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb
|
||||||
@@ -56,6 +56,7 @@ test_tags = None
|
|||||||
;transient_age_limit = 1.0
|
;transient_age_limit = 1.0
|
||||||
;translate_modules = ['all']
|
;translate_modules = ['all']
|
||||||
unaccent = False
|
unaccent = False
|
||||||
upgrade_path =
|
upgrade_path =
|
||||||
|
without_demo = False
|
||||||
workers = 0
|
workers = 0
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,10 @@
|
|||||||
<field name="model">quality.point</field>
|
<field name="model">quality.point</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form>
|
<form>
|
||||||
<header>
|
|
||||||
</header>
|
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box"/>
|
<div class="oe_button_box" name="button_box"/>
|
||||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger"
|
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||||
attrs="{'invisible': [('active', '=', True)]}"/>
|
<h2><field name="name" readonly="1"/></h2>
|
||||||
<h2>
|
|
||||||
<field name="name" readonly="1"/>
|
|
||||||
</h2>
|
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="active" invisible="1"/>
|
<field name="active" invisible="1"/>
|
||||||
@@ -38,14 +33,13 @@
|
|||||||
<field name="note" placeholder="Describe the quality check to do..."/>
|
<field name="note" placeholder="Describe the quality check to do..."/>
|
||||||
</page>
|
</page>
|
||||||
<page string="Notes" name="Notes">
|
<page string="Notes" name="Notes">
|
||||||
<field name="reason" string="Note"
|
<field name="reason" string="Note" placeholder="Describe why you need to perform this quality check..."/>
|
||||||
placeholder="Describe why you need to perform this quality check..."/>
|
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
<field name="message_follower_ids"/>
|
<field name="message_follower_ids"/>
|
||||||
<field name="message_ids"/>
|
<field name="message_ids"/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
@@ -91,18 +85,17 @@
|
|||||||
<filter name="filter_date_close" date="date_close"/>
|
<filter name="filter_date_close" date="date_close"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="Late Activities" name="activities_overdue"
|
<filter string="Late Activities" name="activities_overdue"
|
||||||
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||||
help="Show all records which has next action date is before today"/>
|
help="Show all records which has next action date is before today"/>
|
||||||
<filter string="Today Activities" name="activities_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"
|
<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">
|
<group expand="0" string="Group By">
|
||||||
<filter string="Stage" name="groupby_stage" domain="[]" context="{'group_by': 'stage_id'}"/>
|
<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="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="Root Cause" name="groupby_reason" domain="[]" context="{'group_by': 'reason_id'}"/>
|
||||||
<filter string="Creation Date" name="groupby_createmonth" domain="[]"
|
<filter string="Creation Date" name="groupby_createmonth" domain="[]" context="{'group_by': 'create_date'}"/>
|
||||||
context="{'group_by': 'create_date'}"/>
|
|
||||||
<filter string="Quality Team" name="groupby_team_id" domain="[]" context="{'group_by': 'team_id'}"/>
|
<filter string="Quality Team" name="groupby_team_id" domain="[]" context="{'group_by': 'team_id'}"/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
@@ -129,4 +122,4 @@
|
|||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- js stuff -->
|
<!-- js stuff -->
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -602,7 +602,6 @@
|
|||||||
<field name="model">quality.alert.team</field>
|
<field name="model">quality.alert.team</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form>
|
<form>
|
||||||
<header></header>
|
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<label for="name" string="Team Name"/>
|
<label for="name" string="Team Name"/>
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
from . import models
|
from . import models
|
||||||
from . import commons
|
from . import commons
|
||||||
from . import controllers
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['base', 'mrp_workorder', 'sale', 'purchase', 'sales_team'],
|
'depends': ['account', 'base', 'mrp_workorder', 'sale'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/group_security.xml',
|
'security/group_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
@@ -19,11 +19,9 @@
|
|||||||
'views/fixture_view.xml',
|
'views/fixture_view.xml',
|
||||||
'views/functional_fixture_view.xml',
|
'views/functional_fixture_view.xml',
|
||||||
'views/menu_view.xml',
|
'views/menu_view.xml',
|
||||||
'views/tool_views.xml',
|
"views/tool_views.xml",
|
||||||
'views/tool_basic_param.xml',
|
"views/tool_menu.xml",
|
||||||
'views/tool_menu.xml',
|
|
||||||
'views/menu_fixture_view.xml',
|
'views/menu_fixture_view.xml',
|
||||||
'views/change_base_view.xml',
|
|
||||||
|
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from . import common
|
from. import common
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from odoo import models
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
from odoo import models
|
|
||||||
|
|
||||||
|
|
||||||
class Common(models.Model):
|
class Common(models.Model):
|
||||||
_name = 'sf.sync.common'
|
_name = 'sf.sync.common'
|
||||||
_description = u'公用类'
|
_description = u'公用类'
|
||||||
|
|
||||||
def get_headers(self, token, secret_key):
|
def get_headers(self,token, secret_key):
|
||||||
'''
|
'''
|
||||||
获取requests中的heardes参数
|
获取requests中的heardes参数
|
||||||
'''
|
'''
|
||||||
@@ -20,12 +20,4 @@ class Common(models.Model):
|
|||||||
'checkstr': check_sf_str}
|
'checkstr': check_sf_str}
|
||||||
return headers
|
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
|
|
||||||
|
|||||||
@@ -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/MaintenanceToolGroups', 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)
|
|
||||||
@@ -3,5 +3,9 @@ from . import common
|
|||||||
from . import tool_base_new
|
from . import tool_base_new
|
||||||
from . import fixture
|
from . import fixture
|
||||||
from . import functional_fixture
|
from . import functional_fixture
|
||||||
from . import tool_other_features
|
|
||||||
from . import basic_parameters_fixture
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
import logging
|
||||||
import json
|
|
||||||
import requests
|
import requests
|
||||||
|
import json
|
||||||
from odoo import fields, models, api
|
from odoo import fields, models, api
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
@@ -9,14 +9,6 @@ from odoo.addons.sf_base.commons.common import Common
|
|||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SpindleTaperType(models.Model):
|
|
||||||
_name = 'spindle.taper.type'
|
|
||||||
_description = '主轴锥孔型号'
|
|
||||||
|
|
||||||
name = fields.Char('名称')
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
|
|
||||||
|
|
||||||
class MachineBrandTags(models.Model):
|
class MachineBrandTags(models.Model):
|
||||||
_name = 'sf.machine.brand.tags'
|
_name = 'sf.machine.brand.tags'
|
||||||
_description = '标签'
|
_description = '标签'
|
||||||
@@ -47,7 +39,7 @@ class MachineBrand(models.Model):
|
|||||||
remark = fields.Text('备注')
|
remark = fields.Text('备注')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
# 机床
|
# 机床
|
||||||
class MachineTool(models.Model):
|
class MachineTool(models.Model):
|
||||||
_name = 'sf.machine_tool'
|
_name = 'sf.machine_tool'
|
||||||
@@ -92,10 +84,9 @@ class MachineTool(models.Model):
|
|||||||
type_id = fields.Many2one('sf.machine_tool.type', '型号')
|
type_id = fields.Many2one('sf.machine_tool.type', '型号')
|
||||||
brand_id = fields.Many2one('sf.machine.brand', string='品牌')
|
brand_id = fields.Many2one('sf.machine.brand', string='品牌')
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
|
[("正常", "正常"), ("故障", "故障"), ("不可用", "不可用")],
|
||||||
("封存(报废)", "封存(报废)")],
|
|
||||||
default='正常', string="机床状态")
|
default='正常', string="机床状态")
|
||||||
# 0606新增字段
|
#0606新增字段
|
||||||
machine_tool_picture = fields.Binary('图片')
|
machine_tool_picture = fields.Binary('图片')
|
||||||
heightened_way = fields.Selection([
|
heightened_way = fields.Selection([
|
||||||
('sifudianji', '伺服电机驱动'),
|
('sifudianji', '伺服电机驱动'),
|
||||||
@@ -269,7 +260,7 @@ class MachineToolType(models.Model):
|
|||||||
default="", string="刀把类型")
|
default="", string="刀把类型")
|
||||||
number_of_knife_library = fields.Integer('刀库数量')
|
number_of_knife_library = fields.Integer('刀库数量')
|
||||||
rotate_speed = fields.Integer('转速')
|
rotate_speed = fields.Integer('转速')
|
||||||
# 0606新增字段
|
#0606新增字段
|
||||||
created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user)
|
created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user)
|
||||||
machine_tool_picture = fields.Binary('图片')
|
machine_tool_picture = fields.Binary('图片')
|
||||||
heightened_way = fields.Selection([
|
heightened_way = fields.Selection([
|
||||||
@@ -278,19 +269,31 @@ class MachineToolType(models.Model):
|
|||||||
('chilunjia', '齿轮架驱动')
|
('chilunjia', '齿轮架驱动')
|
||||||
], string="主轴加高方式", default='sifudianji')
|
], string="主轴加高方式", default='sifudianji')
|
||||||
workpiece_load = fields.Char('工件最大负载(kg)')
|
workpiece_load = fields.Char('工件最大负载(kg)')
|
||||||
|
lead_screw = fields.Char('丝杆')
|
||||||
workbench_L = fields.Char('工作台长度(mm)')
|
workbench_L = fields.Char('工作台长度(mm)')
|
||||||
workbench_W = fields.Char('工作台宽度(mm)')
|
workbench_W = fields.Char('工作台宽度(mm)')
|
||||||
|
guide_rail = fields.Char('导轨')
|
||||||
machine_tool_L = fields.Char('机床长度(mm)')
|
machine_tool_L = fields.Char('机床长度(mm)')
|
||||||
machine_tool_W = fields.Char('机床宽度(mm)')
|
machine_tool_W = fields.Char('机床宽度(mm)')
|
||||||
machine_tool_H = fields.Char('机床高度(mm)')
|
machine_tool_H = fields.Char('机床高度(mm)')
|
||||||
|
feed_speed = fields.Char('进给速度(mm/min)')
|
||||||
|
tool_speed = fields.Char('刀具速度(m/min)')
|
||||||
distance_min = fields.Char('主轴端面至工作台面距离MIN(mm)')
|
distance_min = fields.Char('主轴端面至工作台面距离MIN(mm)')
|
||||||
distance_max = fields.Char('主轴端面至工作台面距离MAX(mm)')
|
distance_max = fields.Char('主轴端面至工作台面距离MAX(mm)')
|
||||||
|
taper = fields.Char('主轴锥度(°)')
|
||||||
|
torque = fields.Char('主轴电机扭矩(n/m)')
|
||||||
|
motor_power = fields.Char('主轴电机功率(kw)')
|
||||||
tool_quality_max = fields.Char('刀具最大质量(kg)')
|
tool_quality_max = fields.Char('刀具最大质量(kg)')
|
||||||
tool_long_max = fields.Char('刀具最大长度(mm)')
|
tool_long_max = fields.Char('刀具最大长度(mm)')
|
||||||
|
tool_diameter_max = fields.Char('刀具刀径max(mm)')
|
||||||
|
tool_diameter_min = fields.Char('刀具刀径min(mm)')
|
||||||
machine_tool_category = fields.Many2one('sf.machine_tool.category', string='机床类型')
|
machine_tool_category = fields.Many2one('sf.machine_tool.category', string='机床类型')
|
||||||
|
|
||||||
# 多个型号对应一个机床
|
# 多个型号对应一个机床
|
||||||
machine_tool_id = fields.Many2one('sf.machine_tool', '机床')
|
machine_tool_id = fields.Many2one('sf.machine_tool', '机床')
|
||||||
|
number_of_axles = fields.Selection(
|
||||||
|
[("三轴", "三轴"), ("四轴", "四轴"), ("五轴", "五轴")],
|
||||||
|
default="", string="轴数")
|
||||||
# 加工进程
|
# 加工进程
|
||||||
x_axis = fields.Integer('X轴')
|
x_axis = fields.Integer('X轴')
|
||||||
y_axis = fields.Integer('Y轴')
|
y_axis = fields.Integer('Y轴')
|
||||||
@@ -298,79 +301,13 @@ class MachineToolType(models.Model):
|
|||||||
b_axis = fields.Integer('B轴')
|
b_axis = fields.Integer('B轴')
|
||||||
c_axis = fields.Integer('C轴')
|
c_axis = fields.Integer('C轴')
|
||||||
remark = fields.Char('备注')
|
remark = fields.Char('备注')
|
||||||
|
precision_min = fields.Float('X轴定位精度min(mm)', digits=(12, 3))
|
||||||
|
precision_max = fields.Float('X轴定位精度max(mm)', digits=(12, 3))
|
||||||
control_system_id = fields.Many2one('sf.machine.control_system',
|
control_system_id = fields.Many2one('sf.machine.control_system',
|
||||||
string="控制系统")
|
string="控制系统")
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
code = fields.Char('编码')
|
code = fields.Char('编码')
|
||||||
|
|
||||||
# 1212修改后的字段
|
|
||||||
number_of_axles = fields.Selection(
|
|
||||||
[("三轴", "三轴"), ("四轴", "四轴"), ("五轴", "五轴"), ("六轴", "六轴")],
|
|
||||||
default="", string="轴数")
|
|
||||||
|
|
||||||
# 1212新增字段
|
|
||||||
a_axis = fields.Integer('a轴')
|
|
||||||
function_type = fields.Selection(
|
|
||||||
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
|
|
||||||
default="", string="功能类型")
|
|
||||||
T_trough_num = fields.Integer('槽数')
|
|
||||||
T_trough_wide = fields.Float('槽宽(mm)')
|
|
||||||
T_trough_distance = fields.Float('槽距(mm)')
|
|
||||||
|
|
||||||
taper_type_id = fields.Many2one('spindle.taper.type', string='主轴锥孔型号')
|
|
||||||
spindle_center_distance = fields.Float('主轴中心至立柱滑轨面距离(mm)')
|
|
||||||
spindle_continuous_power = fields.Float('主轴持续功率(kw)')
|
|
||||||
spindle_peak_power = fields.Float('主轴峰值功率(kw)')
|
|
||||||
spindle_sustained_torque = fields.Float('主轴持续扭矩(n/m)')
|
|
||||||
spindle_peak_torque = fields.Float('主轴峰值扭矩(n/m)')
|
|
||||||
linear_axis_guides_type = fields.Char('直线轴导轨类型')
|
|
||||||
axis_driven_type = fields.Char('坐标轴驱动类型')
|
|
||||||
|
|
||||||
X_axis_rapid_traverse_speed = fields.Char('X轴快速进给速度(mm/min)')
|
|
||||||
Y_axis_rapid_traverse_speed = fields.Char('Y轴快速进给速度(mm/min)')
|
|
||||||
Z_axis_rapid_traverse_speed = fields.Char('Z轴快速进给速度(mm/min)')
|
|
||||||
a_axis_rapid_traverse_speed = fields.Char('a轴快速进给速度(mm/min)')
|
|
||||||
b_axis_rapid_traverse_speed = fields.Char('b轴快速进给速度(mm/min)')
|
|
||||||
c_axis_rapid_traverse_speed = fields.Char('c轴快速进给速度(mm/min)')
|
|
||||||
straight_cutting_feed_rate = fields.Char('直线切削进给速度(mm/min)')
|
|
||||||
rotary_cutting_feed_rate = fields.Char('回转切削进给速度(mm/min)')
|
|
||||||
|
|
||||||
X_precision = fields.Float('X轴定位精度(mm)', digits=(12, 3))
|
|
||||||
X_precision_repeat = fields.Float('X轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
Y_precision = fields.Float('Y轴定位精度(mm)', digits=(12, 3))
|
|
||||||
Y_precision_repeat = fields.Float('Y轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
Z_precision = fields.Float('Z轴定位精度(mm)', digits=(12, 3))
|
|
||||||
Z_precision_repeat = fields.Float('Z轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
a_precision = fields.Float('a轴定位精度(mm)', digits=(12, 3))
|
|
||||||
a_precision_repeat = fields.Float('a轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
b_precision = fields.Float('b轴定位精度(mm)', digits=(12, 3))
|
|
||||||
b_precision_repeat = fields.Float('b轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
c_precision = fields.Float('c轴定位精度(mm)', digits=(12, 3))
|
|
||||||
c_precision_repeat = fields.Float('c轴重复定位精度(mm)', digits=(12, 3))
|
|
||||||
|
|
||||||
tool_full_diameter_max = fields.Float('刀具满刀最大直径(mm)')
|
|
||||||
tool_perimeter_diameter_max = fields.Float('刀具邻空刀最大直径(mm)')
|
|
||||||
T_tool_time = fields.Integer('T-T换刀时间(s)')
|
|
||||||
C_tool_time = fields.Integer('C-C换刀时间(s)')
|
|
||||||
|
|
||||||
jg_image_id = fields.Many2many('maintenance.equipment.image', 'jg_equipment_id', string='加工能力',
|
|
||||||
domain="[('type', '=', '加工能力')]")
|
|
||||||
lq_image_id = fields.Many2many('maintenance.equipment.image', 'lq_equipment_id', string='冷却方式',
|
|
||||||
domain="[('type', '=', '冷却方式')]")
|
|
||||||
|
|
||||||
# 待删除字段
|
|
||||||
precision_min = fields.Float('X轴定位精度min(mm)', digits=(12, 3))
|
|
||||||
precision_max = fields.Float('X轴定位精度max(mm)', digits=(12, 3))
|
|
||||||
lead_screw = fields.Char('丝杆')
|
|
||||||
guide_rail = fields.Char('导轨')
|
|
||||||
feed_speed = fields.Char('进给速度(mm/min)')
|
|
||||||
tool_speed = fields.Char('刀具速度(m/min)')
|
|
||||||
torque = fields.Char('主轴点击扭矩(n/m)')
|
|
||||||
motor_power = fields.Char('主轴电机功率(kw)')
|
|
||||||
taper = fields.Char('主轴锥度(°)')
|
|
||||||
tool_diameter_max = fields.Char('刀具刀径max(mm)')
|
|
||||||
tool_diameter_min = fields.Char('刀具刀径min(mm)')
|
|
||||||
|
|
||||||
def _get_ids(self, machine_tool_type_code):
|
def _get_ids(self, machine_tool_type_code):
|
||||||
machine_tool_type_ids = []
|
machine_tool_type_ids = []
|
||||||
for item in machine_tool_type_code:
|
for item in machine_tool_type_code:
|
||||||
@@ -389,4 +326,5 @@ class MachineToolCategory(models.Model):
|
|||||||
remark = fields.Text('备注')
|
remark = fields.Text('备注')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
|
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
|
||||||
default='shukong')
|
default='shukong')
|
||||||
|
|
||||||
|
|||||||
@@ -1,252 +0,0 @@
|
|||||||
from odoo import models, fields
|
|
||||||
|
|
||||||
|
|
||||||
class BasicParametersFixture(models.Model):
|
|
||||||
_name = 'sf.fixture.materials.basic.parameters'
|
|
||||||
_description = '夹具物料基本参数'
|
|
||||||
|
|
||||||
fixture_model_id = fields.Many2one('sf.fixture.model', '夹具型号')
|
|
||||||
name = fields.Char('物料号', size=20)
|
|
||||||
length = fields.Float('长度(mm)', digits=(16, 2))
|
|
||||||
width = fields.Float('宽度(mm)', digits=(16, 2))
|
|
||||||
height = fields.Float('高度(mm)', digits=(16, 2))
|
|
||||||
diameter = fields.Float('直径(mm)', digits=(16, 2))
|
|
||||||
|
|
||||||
# '零点卡盘' 字段
|
|
||||||
weight = fields.Float('重量(mm)', digits=(16, 2))
|
|
||||||
orientation_dish_diameter = fields.Float('定位盘直径(mm)', digits=(16, 2))
|
|
||||||
clamping_diameter = fields.Float('装夹直径(mm)', digits=(16, 2))
|
|
||||||
clamping_num = fields.Selection([('1', '1'), ('2', '2'), ('4', '4'), ('6', '6'), ('8', '8')], string='装夹单元数')
|
|
||||||
chucking_power_max = fields.Float('最大夹持力(KN)', digits=(16, 2))
|
|
||||||
repeated_positioning_accuracy = fields.Char('重复定位精度(mm)', size=20)
|
|
||||||
boolean_transposing_hole = fields.Boolean('是否有转位孔')
|
|
||||||
unlocking_method = fields.Selection(
|
|
||||||
[('手动', '手动'), ('气动', '气动'), ('液压', '液压'), ('电动', '电动'), ('其他', '其他')], string='解锁方式')
|
|
||||||
boolean_chip_blowing_function = fields.Boolean('是否有吹屑功能')
|
|
||||||
carrying_capacity_max = fields.Float('最大承载重量(kg)', digits=(16, 2))
|
|
||||||
rigidity = fields.Integer('硬度HRC')
|
|
||||||
materials_model_id = fields.Many2one('sf.materials.model', '夹具材质')
|
|
||||||
machine_tool_type_id = fields.Many2one('sf.machine_tool.type', '适用机床型号')
|
|
||||||
|
|
||||||
# ’零点托盘‘ 字段
|
|
||||||
connector_diameter = fields.Selection([('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('8', '8')],
|
|
||||||
string='连接头直径(mm)')
|
|
||||||
way_to_install = fields.Selection(
|
|
||||||
[('接口式', '接口式'), ('螺栓固定', '螺栓固定'), ('磁吸式', '磁吸式'), ('其他', '其他')], string='安装方式')
|
|
||||||
type_of_drive = fields.Selection(
|
|
||||||
[('气动式', '气动式'), ('液压式', '液压式'), ('机械式', '机械式'), ('电动式', '电动式'), ('其他', '其他')],
|
|
||||||
string='驱动方式')
|
|
||||||
|
|
||||||
# ’气动夹具‘ 字段
|
|
||||||
gripper_length_min = fields.Float('夹持工件最小长度(mm)', digits=(16, 2))
|
|
||||||
gripper_width_min = fields.Float('夹持工件最小宽度(mm)', digits=(16, 2))
|
|
||||||
gripper_height_min = fields.Float('夹持工件最小高度(mm)', digits=(16, 2))
|
|
||||||
gripper_diameter_min = fields.Float('夹持工件最小直径(mm)', digits=(16, 2))
|
|
||||||
gripper_length_max = fields.Float('夹持工件最大长度(mm)', digits=(16, 2))
|
|
||||||
gripper_width_max = fields.Float('夹持工件最大宽度(mm)', digits=(16, 2))
|
|
||||||
gripper_height_max = fields.Float('夹持工件最大高度(mm)', digits=(16, 2))
|
|
||||||
gripper_diameter_max = fields.Float('夹持工件最大直径(mm)', digits=(16, 2))
|
|
||||||
rated_air_pressure = fields.Float('额定气压(Mpa)', digits=(16, 2))
|
|
||||||
interface_materials_model_id = fields.Many2one('sf.materials.model', '接口类型')
|
|
||||||
|
|
||||||
# ‘虎钳夹具' 字段
|
|
||||||
transverse_groove = fields.Float('横向配合槽n(mm)', digits=(16, 2))
|
|
||||||
longitudinal_fitting_groove = fields.Float('纵向配合槽l(mm)', digits=(16, 2))
|
|
||||||
|
|
||||||
# '磁吸夹具' 字段
|
|
||||||
height_tolerance_value = fields.Char('高度公差(mm)')
|
|
||||||
rated_adsorption_force = fields.Float('额定吸附力(N/cm²)', digits=(16, 2))
|
|
||||||
magnetic_field_height = fields.Float('磁场高度(mm)', digits=(16, 2))
|
|
||||||
magnetic_pole_plate_grinding_allowance = fields.Float('磁极板磨削余量(mm)', digits=(16, 2))
|
|
||||||
|
|
||||||
# '转接板(锁板)夹具' 字段
|
|
||||||
screw_size = fields.Float('螺牙大小(mm)', digits=(16, 2))
|
|
||||||
via_hole_diameter = fields.Float('过孔直径(mm)', digits=(16, 2))
|
|
||||||
|
|
||||||
# '三爪卡盘' 字段
|
|
||||||
mounting_hole_depth = fields.Float('安装孔深度(mm)', digits=(16, 2))
|
|
||||||
centering_diameter = fields.Float('定心直径(mm)', digits=(16, 2))
|
|
||||||
|
|
||||||
def _json_zero_chuck_param(self, obj):
|
|
||||||
zero_chuck_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'diameter': obj['diameter'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'orientation_dish_diameter': obj['orientation_dish_diameter'],
|
|
||||||
'clamping_diameter': obj['clamping_diameter'],
|
|
||||||
'clamping_num': obj['clamping_num'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
|
|
||||||
'boolean_transposing_hole': obj['boolean_transposing_hole'],
|
|
||||||
'unlocking_method': obj['unlocking_method'],
|
|
||||||
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'machine_tool_type_id': self.env['sf.machine_tool.type'].sudo().search(
|
|
||||||
[('code', '=', obj['machine_tool_type_id']), ('active', '=', True)]).id,
|
|
||||||
})
|
|
||||||
return zero_chuck_param_str
|
|
||||||
|
|
||||||
def _json_zero_tray_param(self, obj):
|
|
||||||
zero_tray_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'diameter': obj['diameter'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'clamping_diameter': obj['clamping_diameter'],
|
|
||||||
'connector_diameter': obj['connector_diameter'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
|
|
||||||
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
|
|
||||||
'way_to_install': obj['way_to_install'],
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
})
|
|
||||||
return zero_tray_param_str
|
|
||||||
|
|
||||||
def _json_pneumatic_fixture_param(self, obj):
|
|
||||||
pneumatic_fixture_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'gripper_length_min': obj['gripper_length_min'],
|
|
||||||
'gripper_width_min': obj['gripper_width_min'],
|
|
||||||
'gripper_height_min': obj['gripper_height_min'],
|
|
||||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
|
||||||
'gripper_length_max': obj['gripper_length_max'],
|
|
||||||
'gripper_width_max': obj['gripper_width_max'],
|
|
||||||
'gripper_height_max': obj['gripper_height_max'],
|
|
||||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'rated_air_pressure': obj['rated_air_pressure'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
})
|
|
||||||
return pneumatic_fixture_param_str
|
|
||||||
|
|
||||||
def _json_jaw_vice_fixture_param(self, obj):
|
|
||||||
jaw_vice_fixture_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'gripper_length_min': obj['gripper_length_min'],
|
|
||||||
'gripper_width_min': obj['gripper_width_min'],
|
|
||||||
'gripper_height_min': obj['gripper_height_min'],
|
|
||||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
|
||||||
'gripper_length_max': obj['gripper_length_max'],
|
|
||||||
'gripper_width_max': obj['gripper_width_max'],
|
|
||||||
'gripper_height_max': obj['gripper_height_max'],
|
|
||||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'transverse_groove': obj['transverse_groove'],
|
|
||||||
'longitudinal_fitting_groove': obj['longitudinal_fitting_groove'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
})
|
|
||||||
return jaw_vice_fixture_param_str
|
|
||||||
|
|
||||||
def _json_magnet_fixture_param(self, obj):
|
|
||||||
magnet_fixture_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'height_tolerance_value': obj['height_tolerance_value'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'gripper_length_min': obj['gripper_length_min'],
|
|
||||||
'gripper_width_min': obj['gripper_width_min'],
|
|
||||||
'gripper_height_min': obj['gripper_height_min'],
|
|
||||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
|
||||||
'gripper_length_max': obj['gripper_length_max'],
|
|
||||||
'gripper_width_max': obj['gripper_width_max'],
|
|
||||||
'gripper_height_max': obj['gripper_height_max'],
|
|
||||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
|
||||||
'rated_adsorption_force': obj['rated_adsorption_force'],
|
|
||||||
'magnetic_field_height': obj['magnetic_field_height'],
|
|
||||||
'magnetic_pole_plate_grinding_allowance': obj['magnetic_pole_plate_grinding_allowance'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
})
|
|
||||||
return magnet_fixture_param_str
|
|
||||||
|
|
||||||
def _json_adapter_board_fixture_param(self, obj):
|
|
||||||
adapter_board_fixture_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'gripper_length_min': obj['gripper_length_min'],
|
|
||||||
'gripper_width_min': obj['gripper_width_min'],
|
|
||||||
'gripper_height_min': obj['gripper_height_min'],
|
|
||||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
|
||||||
'gripper_length_max': obj['gripper_length_max'],
|
|
||||||
'gripper_width_max': obj['gripper_width_max'],
|
|
||||||
'gripper_height_max': obj['gripper_height_max'],
|
|
||||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'screw_size': obj['screw_size'],
|
|
||||||
'via_hole_diameter': obj['via_hole_diameter'],
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
})
|
|
||||||
return adapter_board_fixture_param_str
|
|
||||||
|
|
||||||
def _json_scroll_chuck_param(self, obj):
|
|
||||||
scroll_chuck_param_str = (0, '', {
|
|
||||||
'name': obj['name'],
|
|
||||||
'length': obj['length'],
|
|
||||||
'width': obj['width'],
|
|
||||||
'height': obj['height'],
|
|
||||||
'diameter': obj['diameter'],
|
|
||||||
'weight': obj['weight'],
|
|
||||||
'gripper_length_min': obj['gripper_length_min'],
|
|
||||||
'gripper_width_min': obj['gripper_width_min'],
|
|
||||||
'gripper_height_min': obj['gripper_height_min'],
|
|
||||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
|
||||||
'gripper_length_max': obj['gripper_length_max'],
|
|
||||||
'gripper_width_max': obj['gripper_width_max'],
|
|
||||||
'gripper_height_max': obj['gripper_height_max'],
|
|
||||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
|
||||||
'chucking_power_max': obj['chucking_power_max'],
|
|
||||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
|
||||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
|
||||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
|
||||||
'rigidity': obj['rigidity'],
|
|
||||||
'mounting_hole_depth': obj['mounting_hole_depth'],
|
|
||||||
'centering_diameter': obj['centering_diameter'],
|
|
||||||
'type_of_drive': obj['type_of_drive'],
|
|
||||||
})
|
|
||||||
return scroll_chuck_param_str
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
import logging
|
||||||
|
from odoo import fields, models
|
||||||
|
import requests
|
||||||
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from odoo import fields, models, api
|
|
||||||
from odoo.exceptions import UserError
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -19,7 +19,29 @@ class MrsProductionMaterials(models.Model):
|
|||||||
remark = fields.Text("备注")
|
remark = fields.Text("备注")
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
# def open_url_action(self):
|
||||||
|
# base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||||
|
# # url = 'http://192.168.50.202:8080/api'
|
||||||
|
# url = 'https://bfw.jikimo.com/'
|
||||||
|
# # data = {
|
||||||
|
# # 'key' : 'value'
|
||||||
|
# # }
|
||||||
|
#
|
||||||
|
# response = requests.get(url)
|
||||||
|
# response.raise_for_status()
|
||||||
|
# return {
|
||||||
|
# 'type': 'ir.actions.act_url',
|
||||||
|
# 'url': response.url,
|
||||||
|
# 'target': 'new'
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def open_url_action(self):
|
def open_url_action(self):
|
||||||
|
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||||
|
# token = sf_sync_config['token']
|
||||||
|
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||||
|
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||||
url = 'http://192.168.50.127:8081'
|
url = 'http://192.168.50.127:8081'
|
||||||
params = {
|
params = {
|
||||||
'user_id': self._uid
|
'user_id': self._uid
|
||||||
@@ -46,12 +68,12 @@ class MrsMaterialModel(models.Model):
|
|||||||
density = fields.Float("密度(kg/m³)")
|
density = fields.Float("密度(kg/m³)")
|
||||||
materials_id = fields.Many2one('sf.production.materials', "材料名")
|
materials_id = fields.Many2one('sf.production.materials', "材料名")
|
||||||
tensile_strength = fields.Char("拉伸强度(n/mm²)")
|
tensile_strength = fields.Char("拉伸强度(n/mm²)")
|
||||||
standards_id = fields.Many2one('sf.international.standards', '执行标准')
|
standards_id = fields.Many2one('sf.international.standards', '制造标准')
|
||||||
alloy_code = fields.Char('合金牌号')
|
alloy_code = fields.Char('合金牌号')
|
||||||
price = fields.Float('单价/kg')
|
price = fields.Float('单价/kg')
|
||||||
apply = fields.Many2many('material.apply', string='材料应用')
|
apply = fields.Many2many('material.apply', string='材料应用')
|
||||||
materials_code = fields.Char('材料代号')
|
materials_code = fields.Char('材料代号')
|
||||||
hardness = fields.Integer("硬度(hrc)")
|
hardness = fields.Float("硬度(hrc)")
|
||||||
rough_machining = fields.Float("粗加工Vc(m/min)")
|
rough_machining = fields.Float("粗加工Vc(m/min)")
|
||||||
finish_machining = fields.Float("精加工Vc(m/min)")
|
finish_machining = fields.Float("精加工Vc(m/min)")
|
||||||
remark = fields.Text("备注")
|
remark = fields.Text("备注")
|
||||||
@@ -61,14 +83,6 @@ class MrsMaterialModel(models.Model):
|
|||||||
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
|
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
@api.constrains('supplier_ids')
|
|
||||||
def _check_gain_way(self):
|
|
||||||
if not self.gain_way:
|
|
||||||
raise UserError("请输入获取方式")
|
|
||||||
if self.gain_way in ['外协', '采购']:
|
|
||||||
if not self.supplier_ids:
|
|
||||||
raise UserError("请添加供应商")
|
|
||||||
|
|
||||||
|
|
||||||
class MrsProductionProcessCategory(models.Model):
|
class MrsProductionProcessCategory(models.Model):
|
||||||
_name = 'sf.production.process.category'
|
_name = 'sf.production.process.category'
|
||||||
@@ -118,7 +132,6 @@ class MrsProcessingOrder(models.Model):
|
|||||||
index=True, string='加工工艺')
|
index=True, string='加工工艺')
|
||||||
production_process_id = fields.Many2one('sf.production.process', string="表面工艺")
|
production_process_id = fields.Many2one('sf.production.process', string="表面工艺")
|
||||||
|
|
||||||
|
|
||||||
class SupplierSort(models.Model):
|
class SupplierSort(models.Model):
|
||||||
_name = 'sf.supplier.sort'
|
_name = 'sf.supplier.sort'
|
||||||
_description = '供应商排序'
|
_description = '供应商排序'
|
||||||
|
|||||||
@@ -26,65 +26,66 @@ class FixtureModel(models.Model):
|
|||||||
_name = 'sf.fixture.model'
|
_name = 'sf.fixture.model'
|
||||||
_description = "夹具型号"
|
_description = "夹具型号"
|
||||||
|
|
||||||
name = fields.Char(string="名称", size=50, required=True)
|
name = fields.Char(string="名称", size=15)
|
||||||
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", required=True)
|
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", )
|
||||||
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name')
|
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name', store=True)
|
||||||
multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型", required=True)
|
multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型")
|
||||||
brand_id = fields.Many2one('sf.machine.brand', string="品牌")
|
brand_id = fields.Many2one('sf.machine.brand', string="品牌", domain="[('tag_ids.name', 'ilike', '夹具')]")
|
||||||
model_file = fields.Binary(string="图片")
|
clamping_way = fields.Char(string="装夹方式")
|
||||||
status = fields.Boolean('状态')
|
port_type = fields.Char(string="接口类型")
|
||||||
active = fields.Boolean('有效', default=False)
|
model_file = fields.Binary(string="3D模型图")
|
||||||
|
|
||||||
|
length = fields.Char(string="长度(mm)")
|
||||||
|
width = fields.Char(string="宽度(mm)")
|
||||||
|
height = fields.Char(string="高度(mm)")
|
||||||
|
weight = fields.Char(string="重量(kg)")
|
||||||
|
clamp_workpiece_length_max = fields.Integer(string="夹持工件长度max(mm)")
|
||||||
|
clamp_workpiece_width_max = fields.Integer(string="夹持工件宽度max(mm)")
|
||||||
|
clamp_workpiece_height_max = fields.Integer(string="夹持工件高度max(mm)")
|
||||||
|
clamp_workpiece_diameter_max = fields.Float(string="夹持工件直径max(mm)")
|
||||||
|
maximum_carrying_weight = fields.Float(string="最大承载重量(kg)")
|
||||||
|
maximum_clamping_force = fields.Integer(string="最大夹持力(n)")
|
||||||
|
|
||||||
|
materials_model_id = fields.Many2one('sf.materials.model', string="材料型号")
|
||||||
|
driving_way = fields.Selection([('气动', '气动'), ('液压', '液压'), ('机械', '机械')], string="驱动方式")
|
||||||
|
apply_machine_tool_type_ids = fields.Many2many('sf.machine_tool.type', 'rel_fixture_model_machine_tool_type',
|
||||||
|
string="适用机床型号")
|
||||||
|
through_hole_size = fields.Integer(string="过孔大小[mm]")
|
||||||
|
screw_size = fields.Integer(string="螺牙大小[mm]")
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
def _get_code(self, fixture_model_type_code):
|
||||||
|
fixture_model = self.env['sf.fixture.model'].sudo().search(
|
||||||
|
[('code', 'ilike', fixture_model_type_code)],
|
||||||
|
limit=1,
|
||||||
|
order="id desc")
|
||||||
|
if not fixture_model:
|
||||||
|
num = "%03d" % 1
|
||||||
|
else:
|
||||||
|
m = int(fixture_model.code[-3:]) + 1
|
||||||
|
num = "%03d" % m
|
||||||
|
return "%s%s" % (fixture_model_type_code, num)
|
||||||
|
|
||||||
zero_chuck_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='零点卡盘基本参数')
|
|
||||||
zero_tray_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='零点托盘基本参数')
|
|
||||||
pneumatic_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='气动夹具基本参数')
|
|
||||||
jaw_vice_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='虎钳夹具基本参数')
|
|
||||||
magnet_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='磁吸夹具基本参数')
|
|
||||||
adapter_board_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='转接板(锁板)夹具基本参数')
|
|
||||||
scroll_chuck_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
|
||||||
string='三爪卡盘基本参数')
|
|
||||||
code = fields.Char(string='编码', readonly=True)
|
code = fields.Char(string='编码', readonly=True)
|
||||||
|
|
||||||
# def _get_code(self, fixture_model_type_code):
|
def _onchange_fixture_material_id(self, fixture_material_id):
|
||||||
# fixture_model = self.env['sf.fixture.model'].sudo().search(
|
if fixture_material_id:
|
||||||
# [('code', 'ilike', fixture_model_type_code)],
|
if fixture_material_id.name == "气动夹具":
|
||||||
# limit=1,
|
code = self._get_code("JKM-C-JJWL-QDJJ-")
|
||||||
# order="id desc")
|
elif fixture_material_id.name == "转接板(锁板)夹具":
|
||||||
# if not fixture_model:
|
code = self._get_code("JKM-C-JJWL-ZJBJJ-")
|
||||||
# num = "%03d" % 1
|
elif fixture_material_id.name == "磁吸夹具":
|
||||||
# else:
|
code = self._get_code("JKM-C-JJWL-CXJJ-")
|
||||||
# m = int(fixture_model.code[-3:]) + 1
|
elif fixture_material_id.name == "虎钳夹具":
|
||||||
# num = "%03d" % m
|
code = self._get_code("JKM-C-JJWL-HQJJ-")
|
||||||
# return "%s%s" % (fixture_model_type_code, num)
|
else:
|
||||||
#
|
code = self._get_code("JKM-C-JJWL-LDKP-")
|
||||||
# def _onchange_fixture_material_id(self, fixture_material_id):
|
return code
|
||||||
# if fixture_material_id:
|
|
||||||
# if self.fixture_material_id.name == "气动夹具":
|
@api.model_create_multi
|
||||||
# code = self._get_code("JKM-C-JJWL-QDJJ-")
|
def create(self, vals):
|
||||||
# elif self.fixture_material_id.name == "转接板(锁板)夹具":
|
obj = super(FixtureModel, self).create(vals)
|
||||||
# code = self._get_code("JKM-C-JJWL-ZJJJ-")
|
if obj.fixture_material_id:
|
||||||
# elif self.fixture_material_id.name == "磁吸夹具":
|
code = self._onchange_fixture_material_id(obj.fixture_material_id)
|
||||||
# code = self._get_code("JKM-C-JJWL-CXJJ-")
|
obj.code = code
|
||||||
# elif self.fixture_material_id.name == "虎钳夹具":
|
return obj
|
||||||
# code = self._get_code("JKM-C-JJWL-HQJJ-")
|
|
||||||
# elif self.fixture_material_id.name == "零点托盘":
|
|
||||||
# code = self._get_code("JKM-C-JJWL-LDTP-")
|
|
||||||
# elif self.fixture_material_id.name == "三爪卡盘":
|
|
||||||
# code = self._get_code("JKM-C-JJWL-SZKP-")
|
|
||||||
# else:
|
|
||||||
# code = self._get_code("JKM-C-JJWL-LDKP-")
|
|
||||||
# return code
|
|
||||||
#
|
|
||||||
# @api.model_create_multi
|
|
||||||
# def create(self, vals):
|
|
||||||
# obj = super(FixtureModel, self).create(vals)
|
|
||||||
# if obj.fixture_material_id:
|
|
||||||
# code = self._onchange_fixture_material_id(obj.fixture_material_id)
|
|
||||||
# obj.code = code
|
|
||||||
# return obj
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import json
|
|
||||||
import requests
|
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class FunctionalFixtureType(models.Model):
|
class FunctionalFixtureType(models.Model):
|
||||||
@@ -62,8 +62,7 @@ class FunctionalFixture(models.Model):
|
|||||||
def _get_name(self):
|
def _get_name(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
if record.type:
|
if record.type:
|
||||||
if not record.transfer_tray_model_ids and not record.pneumatic_tray_model_ids and \
|
if not record.transfer_tray_model_ids and not record.pneumatic_tray_model_ids and not record.magnetic_tray_model_ids and not record.vice_tray_model_ids:
|
||||||
not record.magnetic_tray_model_ids and not record.vice_tray_model_ids:
|
|
||||||
record.name = ''
|
record.name = ''
|
||||||
if record.transfer_tray_model_ids:
|
if record.transfer_tray_model_ids:
|
||||||
for i in record.transfer_tray_model_ids:
|
for i in record.transfer_tray_model_ids:
|
||||||
|
|||||||
304
sf_base/models/tool_base.py
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from odoo import fields, models, api
|
||||||
|
# from odoo.exceptions import UserError
|
||||||
|
# # from odoo.addons import sf_base, sf_common
|
||||||
|
# from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
# 功能刀具物料
|
||||||
|
class CuttingToolMaterial(models.Model):
|
||||||
|
_name = 'sf.cutting.tool.material'
|
||||||
|
_description = '刀具物料'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
# 功能刀具
|
||||||
|
class FunctionalCuttingTool(models.Model):
|
||||||
|
_name = 'sf.functional.cutting.tool'
|
||||||
|
_description = '功能刀具'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
functional_model_number = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
||||||
|
integral_model_number = fields.Many2one('sf.integral.cutting.tool', string='整体式刀具型号')
|
||||||
|
blade_model_number = fields.Many2one('sf.blade', string='刀片型号')
|
||||||
|
cutterbar_model_number = fields.Many2one('sf.cutter.bar', string='刀杆型号')
|
||||||
|
cutterpad_model_number = fields.Many2one('sf.cutter.pad', string='刀盘型号')
|
||||||
|
handle_model_number = fields.Many2one('sf.handle', string='刀柄型号')
|
||||||
|
chuck_model_number = fields.Many2one('sf.chuck', string='夹头型号')
|
||||||
|
diameter = fields.Float('直径(mm)')
|
||||||
|
tool_grade = fields.Selection([('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'P4'), ('5', 'P5'), ('6', 'P6')],
|
||||||
|
string='刀具等级')
|
||||||
|
machining_accuracy = fields.Float('加工精度(mm)')
|
||||||
|
tool_length = fields.Float('装刀长')
|
||||||
|
blade_number = fields.Integer('刃数')
|
||||||
|
integral_blade_length = fields.Float('整体刃长(mm)')
|
||||||
|
effective_blade_length = fields.Float('有效刃长(mm)')
|
||||||
|
max_life = fields.Float('最大寿命值')
|
||||||
|
is_standard = fields.Boolean('是否标准刀')
|
||||||
|
applicable_range = fields.Char('适用范围')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
# 功能刀具类型
|
||||||
|
class FunctionalCuttingToolModel(models.Model):
|
||||||
|
_name = 'sf.functional.cutting.tool.model'
|
||||||
|
_description = '功能刀具类型'
|
||||||
|
|
||||||
|
name = fields.Char('名称')
|
||||||
|
code = fields.Char('编码')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
# 整体式刀具
|
||||||
|
class IntegralCuttingTool(models.Model):
|
||||||
|
_name = 'sf.integral.cutting.tool'
|
||||||
|
_description = '整体式刀具'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 整体式刀具类型字段,关联整体式刀具类型对象
|
||||||
|
integral_model_number = fields.Many2one('sf.integral.cutting.tool.model', '整体式刀具类型')
|
||||||
|
# 增加品牌、总长度(mm)、柄部长度(mm)、刃部长度(mm)、直径(mm)、刃数、前角(°)、后角(°)、主偏角(°)、材料型号、配对螺母(mm)、适用夹头型号、适用范围、图片、创建人、创建时间等字段
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌', domain="[('tag_ids.name', 'ilike', '刀具')]")
|
||||||
|
total_length = fields.Float('总长度(mm)')
|
||||||
|
shank_length = fields.Float('柄部长度(mm)')
|
||||||
|
blade_length = fields.Float('刃部长度(mm)')
|
||||||
|
diameter = fields.Float('直径(mm)')
|
||||||
|
blade_number = fields.Integer('刃数')
|
||||||
|
front_angle = fields.Float('前角(°)')
|
||||||
|
rear_angle = fields.Float('后角(°)')
|
||||||
|
main_included_angle = fields.Float('主偏角(°)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
nut = fields.Float('配对螺母(mm)')
|
||||||
|
# 适用夹头型号可以多选
|
||||||
|
chuck_model = fields.Many2many('sf.chuck', string='适用夹头型号')
|
||||||
|
scope = fields.Char('适用范围')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
# 整体式刀具类型
|
||||||
|
class IntegralCuttingToolModel(models.Model):
|
||||||
|
_name = 'sf.integral.cutting.tool.model'
|
||||||
|
_description = '整体式刀具类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀片
|
||||||
|
class Blade(models.Model):
|
||||||
|
_name = 'sf.blade'
|
||||||
|
_description = '刀片'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 刀片类型字段,关联刀片类型对象
|
||||||
|
blade_model_number = fields.Many2one('sf.blade.model', '刀片类型')
|
||||||
|
# 编码、型号名称、刀片类型、品牌、长度L(mm)、宽度D(mm)、高度T(mm)、顶角(°)、前角(°)、后角(°)、主偏角(°)、R角(°)、材料型号、加工硬度、配对螺母(mm)、适用刀杆/刀盘型号、刀尖半径(mm)、图片、创建人、创建时间字段
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌', )
|
||||||
|
length = fields.Float('长度L(mm)')
|
||||||
|
width = fields.Float('宽度D(mm)')
|
||||||
|
height = fields.Float('高度T(mm)')
|
||||||
|
top_angle = fields.Float('顶角(°)')
|
||||||
|
front_angle = fields.Float('前角(°)')
|
||||||
|
rear_angle = fields.Float('后角(°)')
|
||||||
|
main_included_angle = fields.Float('主偏角(°)')
|
||||||
|
r_angle = fields.Float('R角(°)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
hardness = fields.Char('加工硬度')
|
||||||
|
nut = fields.Float('配对螺母(mm)')
|
||||||
|
# 适用刀杆型号可以多选
|
||||||
|
cutter_bar = fields.Many2many('sf.cutter.bar', string='适用刀杆型号')
|
||||||
|
# 适用刀盘型号可以多选
|
||||||
|
cutter_pad = fields.Many2many('sf.cutter.pad', string='适用刀盘型号')
|
||||||
|
radius = fields.Float('刀尖半径(mm)')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀片类型
|
||||||
|
class BladeModel(models.Model):
|
||||||
|
_name = 'sf.blade.model'
|
||||||
|
_description = '刀片类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 刀片类型字段,关联刀片对象
|
||||||
|
blade_ids = fields.One2many('sf.blade', 'blade_model_number', '刀片类型')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀杆
|
||||||
|
class CutterBar(models.Model):
|
||||||
|
_name = 'sf.cutter.bar'
|
||||||
|
_description = '刀杆'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 刀杆类型字段,关联刀杆类型对象
|
||||||
|
cutter_bar_model_number = fields.Many2one('sf.cutter.bar.model', '刀杆类型')
|
||||||
|
# 品牌、C柄径(mm)、L总长(mm)、材料型号、刃数、D刃径(mm)、适用刀片型号、配对扳手(mm)、配备螺丝(mm)、刀尖圆角半径、精度等级、硬度(°)、适用范围、图片、创建人、创建时间
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||||
|
c_diameter = fields.Float('C柄径(mm)')
|
||||||
|
total_length = fields.Float('L总长(mm)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
blade_number = fields.Integer('刃数')
|
||||||
|
d_diameter = fields.Float('D刃径(mm)')
|
||||||
|
blade = fields.Many2many('sf.blade', string='适用刀片型号')
|
||||||
|
wrench = fields.Float('配对扳手(mm)')
|
||||||
|
screw = fields.Float('配备螺丝(mm)')
|
||||||
|
radius = fields.Float('刀尖圆角半径')
|
||||||
|
accuracy = fields.Char('精度等级')
|
||||||
|
hardness = fields.Char('硬度(°)')
|
||||||
|
scope = fields.Char('适用范围')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀杆类型
|
||||||
|
class CutterBarModel(models.Model):
|
||||||
|
_name = 'sf.cutter.bar.model'
|
||||||
|
_description = '刀杆类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀盘
|
||||||
|
class CutterPad(models.Model):
|
||||||
|
_name = 'sf.cutter.pad'
|
||||||
|
_description = '刀盘'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 刀盘类型字段,关联刀盘类型对象
|
||||||
|
cutter_pad_model_number = fields.Many2one('sf.cutter.pad.model', '刀盘类型')
|
||||||
|
# 增加品牌、C柄径(mm)、L总长(mm)、材料型号、刃数、D刃径(mm)、适用刀片型号、配对扳手(mm)、配备螺丝(mm)、刀尖圆角半径、精度等级、硬度(°)、适用范围、图片、创建人、创建时间
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||||
|
c_diameter = fields.Float('C柄径(mm)')
|
||||||
|
total_length = fields.Float('L总长(mm)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
blade_number = fields.Integer('刃数')
|
||||||
|
d_diameter = fields.Float('D刃径(mm)')
|
||||||
|
blade = fields.Many2many('sf.blade', string='适用刀片型号')
|
||||||
|
wrench = fields.Float('配对扳手(mm)')
|
||||||
|
screw = fields.Float('配备螺丝(mm)')
|
||||||
|
radius = fields.Float('刀尖圆角半径')
|
||||||
|
accuracy = fields.Char('精度等级')
|
||||||
|
hardness = fields.Char('硬度(°)')
|
||||||
|
scope = fields.Char('适用范围')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀盘类型
|
||||||
|
class CutterPadModel(models.Model):
|
||||||
|
_name = 'sf.cutter.pad.model'
|
||||||
|
_description = '刀盘类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀柄
|
||||||
|
class Handle(models.Model):
|
||||||
|
_name = 'sf.handle'
|
||||||
|
_description = '刀柄'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 刀柄类型字段,关联刀柄类型对象
|
||||||
|
handle_model_number = fields.Many2one('sf.handle.model', '刀柄类型')
|
||||||
|
# 增加、刀柄类型、品牌、L(mm)、L1(mm)、D1(mm)、重量(kg)、材料型号、本体精度(mm)、配对螺母(mm)、适用夹头型号、夹持范围(mm)、检测精度、检测硬度、标准转速、图片、创建人、创建时间
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||||
|
length = fields.Float('L(mm)')
|
||||||
|
length1 = fields.Float('L1(mm)')
|
||||||
|
diameter1 = fields.Float('D1(mm)')
|
||||||
|
weight = fields.Float('重量(kg)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
body_accuracy = fields.Float('本体精度(mm)')
|
||||||
|
nut = fields.Float('配对螺母(mm)')
|
||||||
|
chuck_model = fields.Many2many('sf.chuck.model', string='适用夹头型号')
|
||||||
|
clamping_range = fields.Float('夹持范围(mm)')
|
||||||
|
detection_accuracy = fields.Float('检测精度')
|
||||||
|
detection_hardness = fields.Char('检测硬度')
|
||||||
|
standard_speed = fields.Float('标准转速')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
|
||||||
|
|
||||||
|
# 刀柄类型
|
||||||
|
class HandleModel(models.Model):
|
||||||
|
_name = 'sf.handle.model'
|
||||||
|
_description = '刀柄类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
remark = fields.Char('备注')
|
||||||
|
|
||||||
|
|
||||||
|
# 夹头对象(夹头型号对象)
|
||||||
|
class Chuck(models.Model):
|
||||||
|
_name = 'sf.chuck'
|
||||||
|
_description = '夹头'
|
||||||
|
_rec_name = 'code'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('型号名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
# 夹头类型字段,关联夹头类型对象
|
||||||
|
chuck_model_number = fields.Many2one('sf.chuck.model', '夹头类型')
|
||||||
|
# 增加品牌、精度(mm)、外径(mm)、内径(mm)、高度(mm)、材料型号、配对螺母(mm)、适用刀柄型号、夹持范围(mm)、特性、图片、创建人、创建时间
|
||||||
|
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||||
|
accuracy = fields.Float('精度(mm)')
|
||||||
|
diameter = fields.Float('外径(mm)')
|
||||||
|
inner_diameter = fields.Float('内径(mm)')
|
||||||
|
height = fields.Float('高度(mm)')
|
||||||
|
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
nut = fields.Float('配对螺母(mm)')
|
||||||
|
handle_model = fields.Many2many('sf.handle.model', string='适用刀柄型号')
|
||||||
|
clamping_range = fields.Float('夹持范围(mm)')
|
||||||
|
feature = fields.Char('特性')
|
||||||
|
image = fields.Binary('图片')
|
||||||
|
|
||||||
|
|
||||||
|
# 夹头类型
|
||||||
|
class ChuckModel(models.Model):
|
||||||
|
_name = 'sf.chuck.model'
|
||||||
|
_description = '夹头类型'
|
||||||
|
|
||||||
|
code = fields.Char('编码')
|
||||||
|
name = fields.Char('名称')
|
||||||
|
# 关联刀具物料
|
||||||
|
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
|
remark = fields.Char('备注')
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
|
||||||
import requests
|
|
||||||
from odoo import fields, models, api
|
from odoo import fields, models, api
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
|
||||||
|
|
||||||
|
|
||||||
|
# from datetime import datetime
|
||||||
|
# from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
# 刀具物料
|
||||||
class CuttingToolMaterial(models.Model):
|
class CuttingToolMaterial(models.Model):
|
||||||
_name = 'sf.cutting.tool.material'
|
_name = 'sf.cutting.tool.material'
|
||||||
_description = '刀具物料'
|
_description = '刀具物料'
|
||||||
@@ -25,7 +26,58 @@ class FunctionalCuttingTool(models.Model):
|
|||||||
name = fields.Char('名称')
|
name = fields.Char('名称')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
||||||
mrs_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号')
|
mrs_cutting_tool_model_id = fields.Many2one('sf.cutting.tool.model', string='刀具型号')
|
||||||
|
|
||||||
|
# # 整体式刀具型号
|
||||||
|
# mrs_cutting_tool_integral_model_ids = fields.Many2many('sf.cutting.tool.model', 'rel_integral_model_functional_sf',
|
||||||
|
# string='整体式刀具型号', domain=
|
||||||
|
# [('cutting_tool_type', '=', '整体式刀具')])
|
||||||
|
# # 刀片型号
|
||||||
|
# mrs_cutting_tool_blade_model_ids = fields.Many2many('sf.cutting.tool.model', 'rel_blade_model_functional_sf',
|
||||||
|
# string='刀片型号', domain=
|
||||||
|
# [('cutting_tool_type', '=', '刀片')])
|
||||||
|
# # 刀杆型号
|
||||||
|
# mrs_cutting_tool_cutterbar_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||||
|
# 'rel_cutterbar_model_functional_sf',
|
||||||
|
# string='刀杆型号', domain=
|
||||||
|
# [('cutting_tool_type', '=', '刀杆')])
|
||||||
|
# # 刀盘型号
|
||||||
|
# mrs_cutting_tool_cutterpad_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||||
|
# 'rel_cutterpad_model_functional_sf',
|
||||||
|
# string='刀盘型号', domain=
|
||||||
|
# [('cutting_tool_type', '=', '刀盘')])
|
||||||
|
# # 刀柄型号
|
||||||
|
# mrs_cutting_tool_cutterhandle_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||||
|
# 'rel_cutterhandle_model_functional_sf',
|
||||||
|
# string='刀柄型号',
|
||||||
|
# domain=
|
||||||
|
# [('cutting_tool_type', '=', '刀柄')])
|
||||||
|
# # 夹头型号
|
||||||
|
# mrs_cutting_tool_cutterhead_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||||
|
# 'rel_cutterhead_model_functional_sf',
|
||||||
|
# string='夹头型号', domain=
|
||||||
|
# [('cutting_tool_type', '=', '夹头')])
|
||||||
|
#
|
||||||
|
# diameter = fields.Float('直径(mm)')
|
||||||
|
# tool_grade = fields.Selection([('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'P4'), ('5', 'P5'), ('6', 'P6')],
|
||||||
|
# string='刀具等级')
|
||||||
|
# machining_accuracy = fields.Float('加工精度(mm)')
|
||||||
|
# tool_length = fields.Float('装刀长')
|
||||||
|
# blade_number = fields.Integer('刃数')
|
||||||
|
# integral_blade_length = fields.Float('整体刃长(mm)')
|
||||||
|
# effective_blade_length = fields.Float('有效刃长(mm)')
|
||||||
|
# max_life = fields.Float('最大寿命值')
|
||||||
|
# is_standard = fields.Boolean('是否标准刀')
|
||||||
|
# applicable_range = fields.Char('适用范围')
|
||||||
|
# image = fields.Binary('图片')
|
||||||
|
# active = fields.Boolean('有效', default=True)
|
||||||
|
#
|
||||||
|
# def _get_functional_tool_model_ids(self, functional_tool_model_code):
|
||||||
|
# functional_tool_model_ids = []
|
||||||
|
# for item in functional_tool_model_code:
|
||||||
|
# functional_tool_model = self.env['sf.cutting.tool.model'].search([('code', '=', item)])
|
||||||
|
# functional_tool_model_ids.append(functional_tool_model.id)
|
||||||
|
# return [(6, 0, functional_tool_model_ids)]
|
||||||
|
|
||||||
|
|
||||||
# 功能刀具类型
|
# 功能刀具类型
|
||||||
@@ -39,6 +91,133 @@ class FunctionalCuttingToolModel(models.Model):
|
|||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
# 刀具型号
|
||||||
|
class CuttingToolModel(models.Model):
|
||||||
|
_name = 'sf.cutting.tool.model'
|
||||||
|
_description = '刀具型号'
|
||||||
|
|
||||||
|
name = fields.Char('名称')
|
||||||
|
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', string='刀具物料')
|
||||||
|
cutting_tool_type = fields.Char(string="刀具物料类型", related='cutting_tool_material_id.name', store=True)
|
||||||
|
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', string='刀具类型',
|
||||||
|
)
|
||||||
|
brand_id = fields.Many2one('sf.machine.brand', '品牌', domain="[('tag_ids.name', 'ilike', '刀具')]")
|
||||||
|
tool_length = fields.Integer('长度(mm)')
|
||||||
|
tool_width = fields.Integer('宽度(mm)')
|
||||||
|
tool_height = fields.Integer('高度(mm)')
|
||||||
|
tool_thickness = fields.Integer('厚度(mm)')
|
||||||
|
tool_weight = fields.Float('重量(kg)')
|
||||||
|
coating_material = fields.Char('涂层材质')
|
||||||
|
|
||||||
|
# 整体式刀具参数
|
||||||
|
total_length = fields.Float('总长度(mm)')
|
||||||
|
shank_length = fields.Float('柄部长度(mm)')
|
||||||
|
blade_length = fields.Float('刃部长度(mm)')
|
||||||
|
diameter = fields.Float('直径(mm)')
|
||||||
|
blade_number = fields.Integer('刃数')
|
||||||
|
front_angle = fields.Float('前角(°)')
|
||||||
|
rear_angle = fields.Float('后角(°)')
|
||||||
|
main_included_angle = fields.Float('主偏角(°)')
|
||||||
|
material_model_id = fields.Many2one('sf.materials.model', '材料型号')
|
||||||
|
nut = fields.Float('配对螺母(mm)')
|
||||||
|
# 适用夹头型号可以多选
|
||||||
|
chuck_ids = fields.Many2many(
|
||||||
|
'sf.cutting.tool.model',
|
||||||
|
relation='cutting_tool_model_handle_chuck_rel',
|
||||||
|
column1='model_id_1',
|
||||||
|
column2='model_id_2',
|
||||||
|
domain="[('cutting_tool_type', '=', '夹头')]",
|
||||||
|
string='适用夹头型号')
|
||||||
|
# 刀片参数
|
||||||
|
top_angle = fields.Float('顶角(°)')
|
||||||
|
jump_accuracy = fields.Float('径跳精度(um)')
|
||||||
|
working_hardness = fields.Char('加工硬度(hrc)')
|
||||||
|
cutter_bar_ids = fields.Many2many(
|
||||||
|
'sf.cutting.tool.model',
|
||||||
|
relation='cutting_tool_model_blade_cutter_bar_rel',
|
||||||
|
column1='model_id_1',
|
||||||
|
column2='model_id_2',
|
||||||
|
domain="[('cutting_tool_type', '=', '刀杆')]",
|
||||||
|
string='适用刀杆型号'
|
||||||
|
)
|
||||||
|
cutter_pad_ids = fields.Many2many(
|
||||||
|
'sf.cutting.tool.model',
|
||||||
|
relation='cutting_tool_model_blade_cutter_pad_rel',
|
||||||
|
column1='model_id_1',
|
||||||
|
column2='model_id_2',
|
||||||
|
domain="[('cutting_tool_type', '=', '刀盘')]",
|
||||||
|
string='适用刀盘型号' # 使用空列表作为默认值
|
||||||
|
)
|
||||||
|
# 刀杆/参数
|
||||||
|
blade_diameter = fields.Float('刃径(mm)')
|
||||||
|
blade_ids = fields.Many2many(
|
||||||
|
'sf.cutting.tool.model',
|
||||||
|
relation='cutting_tool_model_pad_blade_rel',
|
||||||
|
column1='model_id_1',
|
||||||
|
column2='model_id_2',
|
||||||
|
domain="[('cutting_tool_type', '=', '刀片')]",
|
||||||
|
string='适用刀片型号' # 使用空列表作为默认值
|
||||||
|
)
|
||||||
|
wrench = fields.Float('配对扳手(mm)')
|
||||||
|
screw = fields.Float('配备螺丝(mm)')
|
||||||
|
accuracy_level = fields.Char('精度等级')
|
||||||
|
# 刀柄参数
|
||||||
|
diameter_max = fields.Float('最大直径(mm)')
|
||||||
|
clamping_diameter = fields.Float('夹持直径(mm)')
|
||||||
|
flange_length = fields.Float('法兰柄长度(mm)')
|
||||||
|
flange_diameter = fields.Float('法兰直径(mm)')
|
||||||
|
# 夹头参数
|
||||||
|
outer_diameter = fields.Float('外径(mm)')
|
||||||
|
inner_diameter = fields.Float('内径(mm)')
|
||||||
|
handle_ids = fields.Many2many(
|
||||||
|
'sf.cutting.tool.model',
|
||||||
|
relation='cutting_tool_model_chuck_handle_rel',
|
||||||
|
column1='model_id_1',
|
||||||
|
column2='model_id_2',
|
||||||
|
domain="[('cutting_tool_type', '=', '刀柄')]",
|
||||||
|
string='适用刀柄型号'
|
||||||
|
)
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
def _get_code(self, cutting_tool_type_code):
|
||||||
|
cutting_tool_model = self.search(
|
||||||
|
[('code', 'ilike', cutting_tool_type_code)],
|
||||||
|
limit=1,
|
||||||
|
order="id desc")
|
||||||
|
if not cutting_tool_model:
|
||||||
|
num = "%03d" % 1
|
||||||
|
else:
|
||||||
|
m = int(cutting_tool_model.code[-3:]) + 1
|
||||||
|
num = "%03d" % m
|
||||||
|
return "%s%s" % (cutting_tool_type_code, num)
|
||||||
|
|
||||||
|
code = fields.Char(string='编码', readonly=True)
|
||||||
|
|
||||||
|
def _onchange_cutting_tool_material_id(self, cutting_tool_material_id):
|
||||||
|
if cutting_tool_material_id:
|
||||||
|
if cutting_tool_material_id.name == "整体式刀具":
|
||||||
|
code = self._get_code("JKM-T-DJWL-ZTDJ-")
|
||||||
|
elif cutting_tool_material_id.name == "刀片":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DPIA-")
|
||||||
|
elif cutting_tool_material_id.name == "刀杆":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DGAN-")
|
||||||
|
elif cutting_tool_material_id.name == "刀盘":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DPAN-")
|
||||||
|
elif cutting_tool_material_id.name == "夹头":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DJIA-")
|
||||||
|
else:
|
||||||
|
code = self._get_code("JKM-T-DJWL-DBIN-")
|
||||||
|
return code
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals):
|
||||||
|
obj = super(CuttingToolModel, self).create(vals)
|
||||||
|
if obj.cutting_tool_material_id:
|
||||||
|
code = self._onchange_cutting_tool_material_id(obj.cutting_tool_material_id)
|
||||||
|
obj.code = code
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
# 刀具类型
|
# 刀具类型
|
||||||
class CuttingToolType(models.Model):
|
class CuttingToolType(models.Model):
|
||||||
_name = 'sf.cutting.tool.type'
|
_name = 'sf.cutting.tool.type'
|
||||||
@@ -50,243 +229,3 @@ class CuttingToolType(models.Model):
|
|||||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||||
remark = fields.Char('备注')
|
remark = fields.Char('备注')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
# 刀具标准库
|
|
||||||
class CuttingToolModel(models.Model):
|
|
||||||
_name = 'sf.cutting_tool.standard.library'
|
|
||||||
_description = '刀具标准库'
|
|
||||||
|
|
||||||
code = fields.Char(string='编码')
|
|
||||||
name = fields.Char('名称')
|
|
||||||
# 关联刀具物料
|
|
||||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料', required=True)
|
|
||||||
# 刀具物料类型
|
|
||||||
cutting_tool_type = fields.Char(related='cutting_tool_material_id.name', string='刀具物料类型',
|
|
||||||
store=True)
|
|
||||||
# 关联刀具类型
|
|
||||||
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', '类型',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', cutting_tool_type)]")
|
|
||||||
brand_id = fields.Many2one('sf.machine.brand', '品牌')
|
|
||||||
status = fields.Boolean(string='状态', default=False)
|
|
||||||
image = fields.Binary('图片')
|
|
||||||
|
|
||||||
# 整体式刀具参数
|
|
||||||
material_model_id = fields.Many2one('mrs.materials.model', '刀具材质')
|
|
||||||
tool_hardness = fields.Integer('刀具硬度(hrc)')
|
|
||||||
coating_material = fields.Char('涂层材质')
|
|
||||||
blade_type = fields.Char('刃部类型')
|
|
||||||
integral_coarse_medium_fine = fields.Selection([('粗', '粗'), ('中', '中'), ('精', '精')], '粗/中/精')
|
|
||||||
integral_run_out_accuracy_max = fields.Char('整体式刀具端跳精度max')
|
|
||||||
integral_run_out_accuracy_min = fields.Char('整体式刀具端跳精度min')
|
|
||||||
ramping_angle_ids = fields.One2many('sf.ramping.angle', 'standard_library_id', '坡铣角度',
|
|
||||||
domain=lambda self: [('standard_library_id', '=', self.id)])
|
|
||||||
|
|
||||||
fit_blade_shape_id = fields.Many2one('maintenance.equipment.image',
|
|
||||||
'适配刀片形状', domain=[('type', '=', '刀片形状')])
|
|
||||||
suitable_machining_method_ids = fields.Many2many('maintenance.equipment.image',
|
|
||||||
'suitable_machining_method_library_rel',
|
|
||||||
'适合加工方式', domain=[('type', '=', '加工能力')])
|
|
||||||
blade_tip_characteristics_id = fields.Many2one('maintenance.equipment.image',
|
|
||||||
'刀尖特征', domain=[('type', '=', '刀尖特征')])
|
|
||||||
handle_type_id = fields.Many2one('maintenance.equipment.image',
|
|
||||||
'柄部类型', domain=[('type', '=', '柄部类型')])
|
|
||||||
cutting_direction_ids = fields.Many2many('maintenance.equipment.image', 'cutting_direction_library_rel',
|
|
||||||
'走刀方向', domain=[('type', '=', '走刀方向')])
|
|
||||||
suitable_coolant_ids = fields.Many2many('maintenance.equipment.image', 'suitable_coolants_library_rel',
|
|
||||||
'适合冷却方式', domain=[('type', '=', '冷却方式')])
|
|
||||||
compaction_way_id = fields.Many2one('maintenance.equipment.image',
|
|
||||||
'压紧方式', domain=[('type', '=', '压紧方式')])
|
|
||||||
integral_tool_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='整体式刀具基本参数')
|
|
||||||
blade_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='刀片基本参数')
|
|
||||||
cutter_bar_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='刀杆基本参数')
|
|
||||||
cutter_head_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='刀盘基本参数')
|
|
||||||
knife_handle_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='刀柄基本参数')
|
|
||||||
chuck_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
|
||||||
'standard_library_id', string='夹头基本参数')
|
|
||||||
cutting_speed_ids = fields.One2many('sf.cutting.speed', 'standard_library_id', string='切削速度Vc')
|
|
||||||
feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(整体式刀具)')
|
|
||||||
feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(刀片)')
|
|
||||||
material_model_id = fields.Many2one('sf.materials.model', '材料型号')
|
|
||||||
# 适用夹头型号可以多选
|
|
||||||
# chuck_ids = fields.Many2many(
|
|
||||||
# 'sf.cutting_tool.standard.library',
|
|
||||||
# relation='cutting_tool_type_library_handle_chuck_rel',
|
|
||||||
# column1='model_id_1',
|
|
||||||
# column2='model_id_2',
|
|
||||||
# domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
|
||||||
# string='适用夹头型号')
|
|
||||||
|
|
||||||
chuck_id = fields.Many2one(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
|
||||||
string='适用夹头型号')
|
|
||||||
cutter_bar_ids = fields.Many2many(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
relation='cutting_tool_type_library_cutter_bar_rel',
|
|
||||||
column1='model_id_1',
|
|
||||||
column2='model_id_2',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '刀杆')]",
|
|
||||||
string='适用刀杆型号'
|
|
||||||
)
|
|
||||||
cutter_pad_ids = fields.Many2many(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
relation='cutting_tool_type_library_cutter_pad_rel',
|
|
||||||
column1='model_id_1',
|
|
||||||
column2='model_id_2',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '刀盘')]",
|
|
||||||
string='适用刀盘型号' # 使用空列表作为默认值
|
|
||||||
)
|
|
||||||
# 刀杆/参数
|
|
||||||
# blade_ids = fields.Many2many(
|
|
||||||
# 'sf.cutting_tool.standard.library',
|
|
||||||
# relation='cutting_tool_type_library_pad_blade_rel',
|
|
||||||
# column1='model_id_1',
|
|
||||||
# column2='model_id_2',
|
|
||||||
# domain="[('cutting_tool_material_id.name', '=', '刀片')]",
|
|
||||||
# string='适用刀片型号' # 使用空列表作为默认值
|
|
||||||
# )
|
|
||||||
|
|
||||||
handle_id = fields.Many2one(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '刀柄')]",
|
|
||||||
string='适用刀柄型号'
|
|
||||||
)
|
|
||||||
# handle_ids = fields.Many2many(
|
|
||||||
# 'sf.cutting_tool.standard.library',
|
|
||||||
# relation='cutting_tool_type_library_chuck_handle_rel',
|
|
||||||
# column1='model_id_1',
|
|
||||||
# column2='model_id_2',
|
|
||||||
# domain="[('cutting_tool_material_id.name', '=', '刀柄')]",
|
|
||||||
# string='适用刀柄型号'
|
|
||||||
# )
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
is_cloud = fields.Boolean('云端数据', default=False)
|
|
||||||
|
|
||||||
def _get_ids(self, cutting_tool_type_code, factory_short_name):
|
|
||||||
cutting_tool_type_ids = []
|
|
||||||
for item in cutting_tool_type_code:
|
|
||||||
cutting_tool_type = self.search([('code', '=', item.replace("JKM", factory_short_name))])
|
|
||||||
if cutting_tool_type:
|
|
||||||
cutting_tool_type_ids.append(cutting_tool_type.id)
|
|
||||||
return [(6, 0, cutting_tool_type_ids)]
|
|
||||||
|
|
||||||
|
|
||||||
class MaintenanceStandardImage(models.Model):
|
|
||||||
_name = 'maintenance.equipment.image'
|
|
||||||
_description = '能力特征库'
|
|
||||||
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
name = fields.Char('名称')
|
|
||||||
image = fields.Binary(string='图文')
|
|
||||||
type = fields.Selection(
|
|
||||||
[('加工能力', '加工能力'), ('刀尖特征', '刀尖特征'), ('柄部类型', '柄部类型'), ('走刀方向', '走刀方向'),
|
|
||||||
('压紧方式', '压紧方式'), ('刀片形状', '刀片形状'), ('冷却方式', '冷却方式')],
|
|
||||||
string='特征')
|
|
||||||
equipment_id = fields.Many2many('maintenance.equipment', 'image_id', string='设备')
|
|
||||||
equipment_lq_id = fields.Many2many('maintenance.equipment', 'image_lq_id', string='设备')
|
|
||||||
jg_equipment_id = fields.Many2many('sf.machine_tool.type', 'jg_image_id', string='机床型号')
|
|
||||||
lq_equipment_id = fields.Many2many('sf.machine_tool.type', 'lq_image_id', string='机床型号')
|
|
||||||
|
|
||||||
def _get_ids(self, name_arr):
|
|
||||||
ability_feature_ids = []
|
|
||||||
for item in name_arr:
|
|
||||||
ability_feature = self.search([('name', '=', item)])
|
|
||||||
if ability_feature:
|
|
||||||
ability_feature_ids.append(ability_feature.id)
|
|
||||||
return [(6, 0, ability_feature_ids)]
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
|
||||||
# 调用父类的name_search方法,获取原始的结果列表
|
|
||||||
res = super().name_search(name, args, operator, limit)
|
|
||||||
# 定义一个空字典用来存储id和name的映射关系
|
|
||||||
name_dict = {}
|
|
||||||
# 遍历结果列表,将id和name存入字典中
|
|
||||||
for item in res:
|
|
||||||
id = item[0]
|
|
||||||
name = item[1]
|
|
||||||
name_dict[id] = name
|
|
||||||
# 根据id列表搜索符合条件的记录
|
|
||||||
records = self.browse(name_dict.keys())
|
|
||||||
# 定义一个新的结果列表用来存储修改后的结果
|
|
||||||
new_res = []
|
|
||||||
# 遍历每条记录
|
|
||||||
for record in records:
|
|
||||||
# 获取记录的id,name和image属性
|
|
||||||
id = record.id
|
|
||||||
name = name_dict[id]
|
|
||||||
image = record.image
|
|
||||||
# 如果image不为空,将其转换为data URI scheme
|
|
||||||
if image:
|
|
||||||
data_uri = f"data:image/png;base64,{image.decode('utf-8')}"
|
|
||||||
else:
|
|
||||||
data_uri = ""
|
|
||||||
# 将这三个属性组成一个数组,并添加到结果列表中 result.append([id, name, data_uri]) # 返回结果列表 return result
|
|
||||||
new_res.append([id, name, data_uri])
|
|
||||||
# 返回新的结果列表
|
|
||||||
return new_res
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
|
|
||||||
# 调用原生的search_read方法获取记录
|
|
||||||
records = super(MaintenanceStandardImage, self).search_read(domain, fields, offset, limit, order)
|
|
||||||
# 遍历每条记录,添加image数据
|
|
||||||
for record in records:
|
|
||||||
image_field = self.browse(record['id']).image
|
|
||||||
if image_field:
|
|
||||||
record['image'] = f"data:image/png;base64,{image_field.decode('utf-8')}"
|
|
||||||
else:
|
|
||||||
record['image'] = ""
|
|
||||||
return records
|
|
||||||
|
|
||||||
|
|
||||||
class ToolGroups(models.Model):
|
|
||||||
_name = 'sf.tool.groups'
|
|
||||||
_description = '刀具组'
|
|
||||||
|
|
||||||
name = fields.Char('名称')
|
|
||||||
equipment_ids = fields.Many2many('maintenance.equipment', 'ref_maintenance_equipment', string='机台号')
|
|
||||||
remark = fields.Char('备注', size=50)
|
|
||||||
|
|
||||||
# ==========机床刀具组接口==========
|
|
||||||
def _register_tool_groups(self, obj):
|
|
||||||
create_url = '/AutoDeviceApi/MaintenanceToolGroups'
|
|
||||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
|
||||||
token = sf_sync_config['token']
|
|
||||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
|
||||||
headers = Common.get_headers(obj, token, sf_secret_key)
|
|
||||||
strurl = sf_sync_config['sf_url'] + create_url
|
|
||||||
device_id = ''
|
|
||||||
name = None
|
|
||||||
if obj:
|
|
||||||
for equipment_id in obj.equipment_ids:
|
|
||||||
device_id = '%s,%s' % (device_id, equipment_id.name)
|
|
||||||
name = obj.name
|
|
||||||
val = {
|
|
||||||
'DeviceId': device_id,
|
|
||||||
'GroupName': name,
|
|
||||||
}
|
|
||||||
kw = json.dumps(val, ensure_ascii=False)
|
|
||||||
r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
|
||||||
ret = r.json()
|
|
||||||
if r == 200:
|
|
||||||
return "机床刀具组发送成功"
|
|
||||||
else:
|
|
||||||
raise ValidationError("机床刀具组发送失败")
|
|
||||||
|
|
||||||
# def write(self, vals):
|
|
||||||
# obj = super().write(vals)
|
|
||||||
# self._register_tool_groups(self)
|
|
||||||
# return obj
|
|
||||||
#
|
|
||||||
# @api.model_create_multi
|
|
||||||
# def create(self, vals_list):
|
|
||||||
# records = super(ToolGroups, self).create(vals_list)
|
|
||||||
# self._register_tool_groups(records)
|
|
||||||
# return records
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
diff a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py (rejected hunks)
|
|
||||||
@@ -108,6 +108,4 @@
|
|
||||||
cutting_speed_ids = fields.One2many('sf.cutting.speed', 'standard_library_id', string='切削速度Vc')
|
|
||||||
- feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
|
|
||||||
- domain=[('cutting_speed', '!=', False)])
|
|
||||||
- feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
|
|
||||||
- domain=[('cutting_speed', '!=', False)])
|
|
||||||
+ feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')
|
|
||||||
+ feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')
|
|
||||||
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
from odoo import fields, models, api
|
|
||||||
|
|
||||||
|
|
||||||
class ToolMaterialsBasicParameters(models.Model):
|
|
||||||
_name = 'sf.tool.materials.basic.parameters'
|
|
||||||
_description = '刀具物料基本参数'
|
|
||||||
|
|
||||||
name = fields.Char('物料号', size=50)
|
|
||||||
code = fields.Char('编码', size=50)
|
|
||||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具标准库')
|
|
||||||
cutting_tool_type = fields.Char(related='standard_library_id.cutting_tool_type', string='刀具物料类型',
|
|
||||||
store=True)
|
|
||||||
|
|
||||||
# 整体式刀具参数
|
|
||||||
total_length = fields.Float('总长度(mm)')
|
|
||||||
blade_number = fields.Selection(
|
|
||||||
[('0', '0'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8')],
|
|
||||||
string='刃数(个)', default='0')
|
|
||||||
neck_diameter = fields.Float('颈部直径(mm)')
|
|
||||||
neck_length = fields.Float('颈部长度(mm)')
|
|
||||||
handle_diameter = fields.Float('柄部直径(mm)')
|
|
||||||
handle_length = fields.Float('柄部长度(mm)')
|
|
||||||
blade_tip_diameter = fields.Integer('刀尖直径(mm)')
|
|
||||||
blade_tip_working_size = fields.Char('刀尖处理尺寸(R半径mm/倒角)', size=20)
|
|
||||||
blade_tip_taper = fields.Integer('刀尖锥度(°)')
|
|
||||||
blade_diameter = fields.Float('刃部直径(mm)')
|
|
||||||
blade_length = fields.Float('刃部长度(mm)')
|
|
||||||
blade_helix_angle = fields.Integer('刃部螺旋角(°)')
|
|
||||||
blade_width = fields.Float('刃部宽度(mm)')
|
|
||||||
blade_depth = fields.Float('刃部深度(mm)')
|
|
||||||
pitch = fields.Float('牙距(mm)')
|
|
||||||
cutting_depth = fields.Float('切削深度(mm)')
|
|
||||||
# 刀片参数
|
|
||||||
length = fields.Float('长度(mm)')
|
|
||||||
thickness = fields.Float('厚度(mm)')
|
|
||||||
width = fields.Float('宽度(mm)')
|
|
||||||
cutting_blade_length = fields.Float('切削刃长(mm)')
|
|
||||||
relief_angle = fields.Integer('后角(°)')
|
|
||||||
blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20)
|
|
||||||
inscribed_circle_diameter = fields.Float('内接圆直径(mm)')
|
|
||||||
install_aperture_diameter = fields.Float('安装孔直径(mm)')
|
|
||||||
chip_breaker_groove = fields.Selection([('无', '无'), ('单面', '单面'), ('双面', '双面')],
|
|
||||||
string='有无断屑槽')
|
|
||||||
chip_breaker_type_code = fields.Char('断屑槽型代号')
|
|
||||||
blade_teeth_model = fields.Selection(
|
|
||||||
[('无', '无'), ('V牙型', 'V牙型'), ('米制全牙型', '米制全牙型'), ('美制全牙型', '美制全牙型'),
|
|
||||||
('惠氏全牙型', '惠氏全牙型'), ('BSPT全牙型', 'BSPT全牙型'), ('NPT全牙型', 'NPT全牙型'),
|
|
||||||
('UNJ全牙型', 'UNJ全牙型'), ('DIN405圆牙型', 'DIN405圆牙型'), ('ACME梯形', 'ACME梯形'),
|
|
||||||
('石油管螺纹刀片', '石油管螺纹刀片'), ('矮牙ACME梯形', '矮牙ACME梯形'),
|
|
||||||
('Trapeze30° 103', 'Trapeze30° 103')], string='刀片牙型', default='无')
|
|
||||||
blade_blade_number = fields.Selection(
|
|
||||||
[('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'),
|
|
||||||
('9', '9'), ('10', '10')],
|
|
||||||
string='刀片的刃数(个)', default='0')
|
|
||||||
main_included_angle = fields.Integer('主偏角(°)')
|
|
||||||
top_angle = fields.Integer('顶角(°)')
|
|
||||||
thread_model = fields.Selection([('无', '无'), ('外螺纹', '外螺纹'), ('内螺纹', '内螺纹')], string='螺纹类型',
|
|
||||||
default='无')
|
|
||||||
thread_num = fields.Float('每英寸螺纹数(tpi)')
|
|
||||||
blade_tip_height_tolerance = fields.Char('刀尖高度公差(mm)', size=20)
|
|
||||||
inscribed_circle_tolerance = fields.Char('内接圆公差(mm)', size=20)
|
|
||||||
thickness_tolerance = fields.Char('厚度公差(mm)', size=20)
|
|
||||||
# 刀杆参数
|
|
||||||
height = fields.Float('高度(mm)')
|
|
||||||
blade_height = fields.Float('刃部高度(mm)')
|
|
||||||
knife_head_height = fields.Float('刀头高度(mm)')
|
|
||||||
knife_head_width = fields.Float('刀头宽度(mm)')
|
|
||||||
knife_head_length = fields.Float('刀头长度(mm)')
|
|
||||||
cut_depth_max = fields.Float('最大切削深度(mm)')
|
|
||||||
cutter_arbor_diameter = fields.Float('刀杆直径(mm)')
|
|
||||||
min_machining_aperture = fields.Integer('最小加工孔径(mm)')
|
|
||||||
install_blade_tip_num = fields.Integer('可装刀片数/齿数(个)')
|
|
||||||
cutting_blade_model = fields.Char('切削类型', size=20)
|
|
||||||
is_cooling_hole = fields.Boolean('有无冷却孔')
|
|
||||||
locating_slot_code = fields.Char('定位槽代号', size=20)
|
|
||||||
installing_structure = fields.Char('安装结构', size=20)
|
|
||||||
blade_id = fields.Many2one(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '刀片')]",
|
|
||||||
string='适配刀片型号' # 使用空列表作为默认值
|
|
||||||
)
|
|
||||||
tool_shim = fields.Char('适配刀垫型号', size=50)
|
|
||||||
cotter_pin = fields.Char('适配销钉型号', size=50)
|
|
||||||
pressing_plate = fields.Char('适配压板型号', size=50)
|
|
||||||
screw = fields.Char('适配螺钉型号', size=50)
|
|
||||||
spanner = fields.Char('适配扳手型号', size=50)
|
|
||||||
# 刀盘参数
|
|
||||||
cutter_head_diameter = fields.Float('刀盘直径(mm)')
|
|
||||||
interface_diameter = fields.Float('接口直径(mm)')
|
|
||||||
# 刀柄参数
|
|
||||||
flange_shank_length = fields.Float('法兰长(mm)')
|
|
||||||
flange_diameter = fields.Float('法兰直径(mm)')
|
|
||||||
fit_chuck_size = fields.Char('适配夹头尺寸')
|
|
||||||
handle_external_diameter = fields.Float('柄部外径(mm)')
|
|
||||||
handle_inside_diameter = fields.Float('柄部内径(mm)')
|
|
||||||
dynamic_balance_class = fields.Char('动平衡等级')
|
|
||||||
min_clamping_diameter = fields.Float('最小夹持直径(mm)')
|
|
||||||
max_clamping_diameter = fields.Float('最大夹持直径(mm)')
|
|
||||||
clamping_mode = fields.Char('夹持方式', size=20)
|
|
||||||
max_load_capacity = fields.Float('最大负载能力(kg)')
|
|
||||||
taper = fields.Integer('锥度(°)')
|
|
||||||
shank_length = fields.Float('刀柄长度(mm)', digits=(3, 2))
|
|
||||||
shank_diameter = fields.Float('刀柄直径(mm)')
|
|
||||||
tool_changing_time = fields.Integer('换刀时间(s)')
|
|
||||||
standard_rotate_speed = fields.Integer('标准转速(n/min)')
|
|
||||||
max_rotate_speed = fields.Integer('最大转速(n/min)')
|
|
||||||
diameter_slip_accuracy = fields.Char('径跳精度(mm)', size=20)
|
|
||||||
cooling_model = fields.Char('冷却类型', size=20)
|
|
||||||
taper_shank_model = fields.Char('锥柄型号')
|
|
||||||
is_quick_cutting = fields.Boolean('可高速切削', default=False)
|
|
||||||
is_safe_lock = fields.Boolean('有无安全锁', default=False)
|
|
||||||
chuck_id = fields.Many2one(
|
|
||||||
'sf.cutting_tool.standard.library',
|
|
||||||
domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
|
||||||
string='适配夹头型号' # 使用空列表作为默认值
|
|
||||||
)
|
|
||||||
nut = fields.Char('适配锁紧螺母型号')
|
|
||||||
|
|
||||||
# 夹头参数
|
|
||||||
er_size_model = fields.Char('ER尺寸型号', size=20)
|
|
||||||
outer_diameter = fields.Float('外径(mm)')
|
|
||||||
inner_diameter = fields.Float('内径(mm)')
|
|
||||||
run_out_accuracy = fields.Char('跳动精度(mm)', size=20)
|
|
||||||
top_diameter = fields.Float('顶部直径(mm)')
|
|
||||||
weight = fields.Float('重量(kg)')
|
|
||||||
clamping_length = fields.Float('夹持长度(mm)')
|
|
||||||
clamping_tolerance = fields.Char('夹持公差(mm)', size=20)
|
|
||||||
cooling_jacket = fields.Char('适用冷却套型号', size=50)
|
|
||||||
active = fields.Boolean(string='有效', default=True)
|
|
||||||
|
|
||||||
|
|
||||||
class CuttingSpeed(models.Model):
|
|
||||||
_name = 'sf.cutting.speed'
|
|
||||||
_description = '切削速度Vc'
|
|
||||||
|
|
||||||
name = fields.Char('名称')
|
|
||||||
product_template_id = fields.Many2one('product.template')
|
|
||||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='标准库')
|
|
||||||
|
|
||||||
execution_standard_id = fields.Many2one('sf.international.standards', string='执行标准', store=True)
|
|
||||||
material_code = fields.Char('材料代号')
|
|
||||||
material_name_id = fields.Many2one('sf.materials.model', '材料名称',
|
|
||||||
domain="[('standards_id', '=', execution_standard_id)]")
|
|
||||||
material_grade = fields.Char('材料牌号')
|
|
||||||
tensile_strength = fields.Char('拉伸强度 (N/mm²)')
|
|
||||||
hardness = fields.Integer('硬度(hrc)')
|
|
||||||
ability_feature_library = fields.Many2one('maintenance.equipment.image', '加工方式',
|
|
||||||
domain="[('type', '=', '加工能力')]")
|
|
||||||
cutting_width_depth_id = fields.Many2one('sf.cutting.width.depth', '切削宽度和深度')
|
|
||||||
process_capability = fields.Selection([('粗加工', '粗加工'), ('精加工', '精加工')], string='粗/精加工')
|
|
||||||
cutting_speed = fields.Char('切削速度', required=True)
|
|
||||||
cutting_speed_max = fields.Float('最大值')
|
|
||||||
cutting_speed_min = fields.Float('最小值')
|
|
||||||
|
|
||||||
application = fields.Selection([('主应用', '主应用'), ('次应用', '次应用')], '主/次应用')
|
|
||||||
active = fields.Boolean(string='有效', default=True)
|
|
||||||
|
|
||||||
|
|
||||||
class FeedPerTooth(models.Model):
|
|
||||||
_name = 'sf.feed.per.tooth'
|
|
||||||
_description = '每齿走刀量fz'
|
|
||||||
_order = 'blade_diameter,cutting_width_depth_id,materials_type_id'
|
|
||||||
|
|
||||||
name = fields.Char('名称')
|
|
||||||
product_template_id = fields.Many2one('product.template')
|
|
||||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='标准库')
|
|
||||||
blade_diameter = fields.Integer('刃部直径(mm)', readonly=True)
|
|
||||||
materials_type_id = fields.Many2one('sf.materials.model', string='材料名称', readonly=True)
|
|
||||||
cutting_width_depth_id = fields.Many2one('sf.cutting.width.depth', '切削宽度和深度', readonly=True)
|
|
||||||
feed_per_tooth = fields.Char('每齿走刀量 (mm/z)', size=20)
|
|
||||||
active = fields.Boolean(string='有效', default=True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# @api.depends('product_template_id')
|
|
||||||
# def _compute_product_template_id(self):
|
|
||||||
# if self.product_template_id is not None:
|
|
||||||
# self.blade_diameter = self.product_template_id.cutting_tool_blade_diameter
|
|
||||||
|
|
||||||
|
|
||||||
class CuttingWidthDepth(models.Model):
|
|
||||||
_name = 'sf.cutting.width.depth'
|
|
||||||
_description = '切削宽度和深度'
|
|
||||||
|
|
||||||
name = fields.Char('名称')
|
|
||||||
|
|
||||||
|
|
||||||
class RampingAngle(models.Model):
|
|
||||||
_name = 'sf.ramping.angle'
|
|
||||||
_description = '坡铣角度'
|
|
||||||
|
|
||||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', '刀具标准库')
|
|
||||||
|
|
||||||
name = fields.Char('坡铣角度')
|
|
||||||