采购协议
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.cs.jikimo.com',
|
'website': 'https://www.sf.cs.jikimo.com',
|
||||||
'depends': ['sf_base', 'base_setup','sf_bf_connect','sf_sale'],
|
'depends': ['sf_base', 'base_setup','sf_bf_connect'],
|
||||||
'data': [
|
'data': [
|
||||||
'data/ir_cron_data.xml',
|
'data/ir_cron_data.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
|
|||||||
@@ -10,23 +10,18 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['sale', 'sale_management', 'web_widget_model_viewer', 'sf_base', 'account', 'purchase', 'delivery',
|
'depends': ['sale', 'sale_management', 'web_widget_model_viewer', 'sf_base', 'account', 'purchase', 'delivery'],
|
||||||
'purchase_requisition', 'purchase_requisition_stock', 'documents'],
|
|
||||||
'data': [
|
'data': [
|
||||||
'data/documents_data.xml',
|
|
||||||
'security/group_security.xml',
|
'security/group_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'wizard/sale_order_wizard_views.xml',
|
'wizard/sale_order_wizard_views.xml',
|
||||||
'wizard/purchase_order_wizard_views.xml',
|
'wizard/purchase_order_wizard_views.xml',
|
||||||
'wizard/upload_file_upload_view.xml',
|
|
||||||
'wizard/purchase_requisition_wizard_views.xml',
|
|
||||||
'data/cron_data.xml',
|
'data/cron_data.xml',
|
||||||
'views/sale_team.xml',
|
'views/sale_team.xml',
|
||||||
'views/sale_order_view.xml',
|
'views/sale_order_view.xml',
|
||||||
'views/res_partner_view.xml',
|
'views/res_partner_view.xml',
|
||||||
'views/purchase_order_view.xml',
|
'views/purchase_order_view.xml',
|
||||||
'views/quick_easy_order_view.xml',
|
'views/quick_easy_order_view.xml',
|
||||||
'views/purchase_requisition_view.xml',
|
|
||||||
'views/purchase_menu.xml'
|
'views/purchase_menu.xml'
|
||||||
],
|
],
|
||||||
'assets': {
|
'assets': {
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<data noupdate="1">
|
|
||||||
<!-- 创建采购合同文件夹 -->
|
|
||||||
<record id="documents_purchase_contracts_folder" model="documents.folder">
|
|
||||||
<field name="name">采购合同</field>
|
|
||||||
<field name="description">存放采购合同相关文件</field>
|
|
||||||
<field name="sequence">10</field>
|
|
||||||
</record>
|
|
||||||
<record id="documents_purchase_contracts_folder_1" model="documents.folder">
|
|
||||||
<field name="name">废弃</field>
|
|
||||||
<field name="parent_folder_id" ref="documents_purchase_contracts_folder"/>
|
|
||||||
</record>
|
|
||||||
<record id="documents_purchase_contracts_folder_2" model="documents.folder">
|
|
||||||
<field name="name">通过</field>
|
|
||||||
<field name="parent_folder_id" ref="documents_purchase_contracts_folder"/>
|
|
||||||
</record>
|
|
||||||
<record id="documents_purchase_contracts_folder_3" model="documents.folder">
|
|
||||||
<field name="name">待审</field>
|
|
||||||
<field name="parent_folder_id" ref="documents_purchase_contracts_folder"/>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Translation of Odoo Server.
|
|
||||||
# This file contains the translation of the following modules:
|
|
||||||
# * purchase_requisition
|
|
||||||
#
|
|
||||||
|
|
||||||
#. module: purchase_requisition
|
|
||||||
#: model:ir.actions.act_window,name:purchase_requisition.action_purchase_requisition
|
|
||||||
#: model:ir.ui.menu,name:purchase_requisition.menu_purchase_requisition_pro_mgt
|
|
||||||
msgid "Blanket Orders"
|
|
||||||
msgstr "采购协议"
|
|
||||||
@@ -4,4 +4,3 @@ from . import quick_easy_order_old
|
|||||||
from . import auto_quatotion_common
|
from . import auto_quatotion_common
|
||||||
from . import parser_and_calculate_work_time
|
from . import parser_and_calculate_work_time
|
||||||
from . import preload_datas_functions
|
from . import preload_datas_functions
|
||||||
from . import purchase_requisition
|
|
||||||
|
|||||||
@@ -1,210 +0,0 @@
|
|||||||
from odoo import models, fields, api, _
|
|
||||||
from odoo.exceptions import UserError, ValidationError
|
|
||||||
import logging
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseRequisition(models.Model):
|
|
||||||
_inherit = 'purchase.requisition'
|
|
||||||
|
|
||||||
partner_ref = fields.Char(string='合同名称', required=True)
|
|
||||||
contract_number = fields.Char(string='合同编码', size=20, required=True)
|
|
||||||
payment_term_id = fields.Many2one('account.payment.term', '付款条件',
|
|
||||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]",
|
|
||||||
required=True)
|
|
||||||
contract_summary = fields.Text(string='合同概况', required=True)
|
|
||||||
|
|
||||||
contract_document_id = fields.Many2one('documents.document', string='合同文件')
|
|
||||||
contract_file = fields.Binary(related='contract_document_id.datas', string='合同文件内容')
|
|
||||||
contract_file_name = fields.Char(related='contract_document_id.attachment_id.name', string='文件名')
|
|
||||||
|
|
||||||
# 是否已上传合同文件
|
|
||||||
is_upload_contract_file = fields.Boolean(string='是否已上传合同文件', default=False)
|
|
||||||
|
|
||||||
def upload_contract_file(self):
|
|
||||||
self.ensure_one()
|
|
||||||
action = {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': _('上传合同文件'),
|
|
||||||
'res_model': 'ir.attachment.upload', # 我们需要创建一个新的向导模型
|
|
||||||
'view_mode': 'form',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_res_model': self._name,
|
|
||||||
'default_res_id': self.id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return action
|
|
||||||
|
|
||||||
# 删除合同文件
|
|
||||||
def delete_contract_file(self):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.contract_document_id:
|
|
||||||
try:
|
|
||||||
document = self.contract_document_id
|
|
||||||
|
|
||||||
# 清空关联
|
|
||||||
self.write({
|
|
||||||
'contract_document_id': False,
|
|
||||||
'contract_file': False,
|
|
||||||
'contract_file_name': False
|
|
||||||
})
|
|
||||||
|
|
||||||
# 删除文档
|
|
||||||
if document:
|
|
||||||
document.with_context(no_attachment=True).sudo().unlink()
|
|
||||||
|
|
||||||
self.is_upload_contract_file = False
|
|
||||||
|
|
||||||
# 返回视图动作来刷新当前表单
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'res_model': 'purchase.requisition',
|
|
||||||
'res_id': self.id,
|
|
||||||
'view_mode': 'form',
|
|
||||||
'view_type': 'form',
|
|
||||||
'target': 'current',
|
|
||||||
'flags': {'mode': 'readonly'},
|
|
||||||
}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
_logger.error('删除合同文件时出错: %s', str(e))
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('错误'),
|
|
||||||
'message': _('删除文件时出现错误'),
|
|
||||||
'type': 'danger',
|
|
||||||
'sticky': True,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('提示'),
|
|
||||||
'message': _('没有需要删除的合同文件'),
|
|
||||||
'type': 'warning',
|
|
||||||
'sticky': False,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def action_in_progress(self):
|
|
||||||
self.ensure_one()
|
|
||||||
# 检查合同文件
|
|
||||||
if not self.contract_document_id:
|
|
||||||
raise ValidationError('* 必须点击上传合同文件')
|
|
||||||
if self.origin:
|
|
||||||
purchase_order = self.env['purchase.order'].search([('name', '=', self.origin)], limit=1)
|
|
||||||
if purchase_order:
|
|
||||||
if not purchase_order.requisition_id:
|
|
||||||
# 绑定采购协议
|
|
||||||
self.purchase_ids += purchase_order
|
|
||||||
else:
|
|
||||||
raise ValidationError('源单据已绑定采购协议,请手动清除源单据解绑。')
|
|
||||||
res = super(PurchaseRequisition, self).action_in_progress()
|
|
||||||
# 将合同文档移动到废弃
|
|
||||||
for requisition in self:
|
|
||||||
if requisition.contract_document_id:
|
|
||||||
workspace = self.update_documents_folder('通过')
|
|
||||||
requisition.contract_document_id.write({
|
|
||||||
'folder_id': workspace.id,
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
|
|
||||||
def action_cancel(self):
|
|
||||||
for requisition in self:
|
|
||||||
if requisition.purchase_ids:
|
|
||||||
raise ValidationError(_('已关联采购订单,不能取消该采购协议'))
|
|
||||||
res = super(PurchaseRequisition, self).action_cancel()
|
|
||||||
# 将合同文档移动到废弃
|
|
||||||
for requisition in self:
|
|
||||||
if requisition.contract_document_id:
|
|
||||||
workspace = self.update_documents_folder('废弃')
|
|
||||||
requisition.contract_document_id.write({
|
|
||||||
'folder_id': workspace.id,
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
|
|
||||||
def action_draft(self):
|
|
||||||
res = super(PurchaseRequisition, self).action_draft()
|
|
||||||
for requisition in self:
|
|
||||||
if requisition.contract_document_id:
|
|
||||||
workspace = self.update_documents_folder('待审')
|
|
||||||
requisition.contract_document_id.write({
|
|
||||||
'folder_id': workspace.id,
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
|
|
||||||
def update_documents_folder(self, documents_folder_name):
|
|
||||||
workspace_parent = self.env['documents.folder'].search([('name', '=', '采购合同')], limit=1)
|
|
||||||
workspace = self.env['documents.folder'].search(
|
|
||||||
[('name', '=', documents_folder_name), ('parent_folder_id', '=', workspace_parent.id)], limit=1)
|
|
||||||
return workspace
|
|
||||||
|
|
||||||
@api.constrains('line_ids')
|
|
||||||
def check_line_ids(self):
|
|
||||||
if self.origin:
|
|
||||||
purchase_order = self.env['purchase.order'].search([('name', '=', self.origin)], limit=1)
|
|
||||||
if purchase_order:
|
|
||||||
error_products = []
|
|
||||||
# 获取采购订单中的所有产品
|
|
||||||
purchase_order_products = purchase_order.order_line.mapped('product_id')
|
|
||||||
if self.line_ids:
|
|
||||||
for line in self.line_ids:
|
|
||||||
# 检查当前行的产品在采购订单中的数量
|
|
||||||
order_line = purchase_order.order_line.filtered(lambda ol: ol.product_id == line.product_id)
|
|
||||||
if order_line and line.product_qty < order_line.product_qty:
|
|
||||||
error_products.append(line.product_id.name) # 收集不符合条件的产品名称
|
|
||||||
else:
|
|
||||||
raise ValidationError(
|
|
||||||
_('采购协议的产品和数量应达超源单据的产品和数量,请修改产品数量或修改源单据。'))
|
|
||||||
|
|
||||||
# 检查采购订单中的产品是否都在采购协议中
|
|
||||||
for product in purchase_order_products:
|
|
||||||
if product not in self.line_ids.mapped('product_id'):
|
|
||||||
raise ValidationError(
|
|
||||||
_('采购协议的产品和数量应达超源单据的产品和数量,请修改产品数量或修改源单据。'))
|
|
||||||
if error_products:
|
|
||||||
raise ValidationError(
|
|
||||||
_('产品 %s 的数量不能小于源单据数量,当前无法保存。') % (', '.join(error_products)))
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseRequisitionLine(models.Model):
|
|
||||||
_inherit = 'purchase.requisition.line'
|
|
||||||
|
|
||||||
materials_id = fields.Many2one('sf.production.materials', string='材料', compute='_compute_product_info')
|
|
||||||
materials_type_id = fields.Many2one('sf.materials.model', string='规格型号', compute='_compute_product_info')
|
|
||||||
part_number = fields.Char(string='零件图号', compute='_compute_product_info')
|
|
||||||
delivery_date = fields.Date(string='交货时间')
|
|
||||||
|
|
||||||
@api.depends('product_id')
|
|
||||||
def _compute_product_info(self):
|
|
||||||
for line in self:
|
|
||||||
if line.product_id:
|
|
||||||
line.materials_id = line.product_id.materials_id
|
|
||||||
line.materials_type_id = line.product_id.materials_type_id
|
|
||||||
line.part_number = line.product_id.part_number
|
|
||||||
else:
|
|
||||||
line.materials_id = False
|
|
||||||
line.materials_type_id = False
|
|
||||||
line.part_number = False
|
|
||||||
|
|
||||||
@api.model_create_multi
|
|
||||||
def create(self, vals_list):
|
|
||||||
for vals in vals_list:
|
|
||||||
if 'product_qty' in vals and vals.get('product_qty') <= 0:
|
|
||||||
raise UserError('请对【产品】中的【数量】进行输入')
|
|
||||||
if 'price_unit' in vals and vals.get('price_unit') <= 0:
|
|
||||||
raise UserError('请对【产品】中的【单价】进行输入')
|
|
||||||
return super(PurchaseRequisitionLine, self).create(vals_list)
|
|
||||||
|
|
||||||
def write(self, vals):
|
|
||||||
if 'product_qty' in vals and vals.get('product_qty') <= 0:
|
|
||||||
raise UserError('请对【产品】中的【数量】进行输入')
|
|
||||||
if 'price_unit' in vals and vals.get('price_unit') <= 0:
|
|
||||||
raise UserError('请对【产品】中的【单价】进行输入')
|
|
||||||
return super(PurchaseRequisitionLine, self).write(vals)
|
|
||||||
@@ -303,39 +303,13 @@ class RePurchaseOrder(models.Model):
|
|||||||
string='采购类型', default='standard', store=True, compute='_compute_purchase_type')
|
string='采购类型', default='standard', store=True, compute='_compute_purchase_type')
|
||||||
|
|
||||||
# 合同编号
|
# 合同编号
|
||||||
contract_number = fields.Char(related='requisition_id.contract_number', string='合同编号', size=20)
|
contract_number = fields.Char(string='合同编号', size=20)
|
||||||
# 合同概况
|
# 合同概况
|
||||||
contract_summary = fields.Text(string='合同概况')
|
contract_summary = fields.Text(string='合同概况')
|
||||||
|
|
||||||
# 选择是否为紧急采购
|
# 选择是否为紧急采购
|
||||||
urgent_purchase = fields.Selection([('no', '否'), ('yes', '是')], string='紧急采购', default='no')
|
urgent_purchase = fields.Selection([('no', '否'), ('yes', '是')], string='紧急采购', default='no')
|
||||||
|
|
||||||
purchase_requisition_count = fields.Integer('采购协议数量', compute='_compute_purchase_requisition_count')
|
|
||||||
|
|
||||||
partner_ref = fields.Char(related='requisition_id.partner_ref')
|
|
||||||
payment_term_id = fields.Many2one(related='requisition_id.payment_term_id')
|
|
||||||
|
|
||||||
requisition_id = fields.Many2one('purchase.requisition', string='采购协议', copy=False, readonly=True)
|
|
||||||
show_create_requisition_button = fields.Boolean(string='显示创建采购协议按钮',
|
|
||||||
compute='_compute_show_create_requisition_button'
|
|
||||||
)
|
|
||||||
show_requisition_fields = fields.Boolean(string='显示协议按钮', compute='_compute_show_requisition_fields')
|
|
||||||
|
|
||||||
@api.depends('requisition_id')
|
|
||||||
def _compute_show_requisition_fields(self):
|
|
||||||
for order in self:
|
|
||||||
order.show_requisition_fields = bool(order.requisition_id and order.requisition_id.state == 'ongoing')
|
|
||||||
|
|
||||||
@api.depends('requisition_id')
|
|
||||||
def _compute_show_create_requisition_button(self):
|
|
||||||
for order in self:
|
|
||||||
purchase_requisition = self.env['purchase.requisition'].search_count([('origin', '=', order.name)])
|
|
||||||
order.show_create_requisition_button = purchase_requisition > 0
|
|
||||||
|
|
||||||
def _compute_purchase_requisition_count(self):
|
|
||||||
for record in self:
|
|
||||||
record.purchase_requisition_count = len(record.requisition_id)
|
|
||||||
|
|
||||||
@api.depends('origin')
|
@api.depends('origin')
|
||||||
def _compute_purchase_type(self):
|
def _compute_purchase_type(self):
|
||||||
for purchase in self:
|
for purchase in self:
|
||||||
@@ -370,26 +344,6 @@ class RePurchaseOrder(models.Model):
|
|||||||
for item in self:
|
for item in self:
|
||||||
if not item.order_line:
|
if not item.order_line:
|
||||||
raise UserError('该询价单未添加【产品】,请进行添加')
|
raise UserError('该询价单未添加【产品】,请进行添加')
|
||||||
missing_products = []
|
|
||||||
over_ordered_products = []
|
|
||||||
if item.requisition_id:
|
|
||||||
requisition_product_ids = item.requisition_id.line_ids.mapped('product_id.id')
|
|
||||||
for line in item.order_line:
|
|
||||||
if line.product_id.id not in requisition_product_ids:
|
|
||||||
missing_products.append(line.product_id.name)
|
|
||||||
else:
|
|
||||||
requisition_line = item.requisition_id.line_ids.filtered(
|
|
||||||
lambda r: r.product_id.id == line.product_id.id)
|
|
||||||
remaining_qty = requisition_line.product_qty - requisition_line.qty_ordered
|
|
||||||
if requisition_line and line.product_qty > remaining_qty:
|
|
||||||
over_ordered_products.append(
|
|
||||||
f'{line.product_id.name}:{remaining_qty}{requisition_line.product_uom_id.name}')
|
|
||||||
|
|
||||||
if missing_products:
|
|
||||||
raise UserError('关联协议不存在产品 %s ,无法保存。' % '、'.join(missing_products))
|
|
||||||
if over_ordered_products:
|
|
||||||
raise UserError('当前订购数量超过了关联协议的剩余数量,无法保存。\n涉及产品及剩余数量有:\n%s' % '\n'.join(
|
|
||||||
over_ordered_products))
|
|
||||||
for line in item.order_line:
|
for line in item.order_line:
|
||||||
if not line.product_id:
|
if not line.product_id:
|
||||||
raise UserError('【产品】未添加,请进行添加')
|
raise UserError('【产品】未添加,请进行添加')
|
||||||
@@ -445,21 +399,6 @@ class RePurchaseOrder(models.Model):
|
|||||||
# raise ValidationError('【%s】已存在,请勿重复添加' % product[-1].name)
|
# raise ValidationError('【%s】已存在,请勿重复添加' % product[-1].name)
|
||||||
|
|
||||||
def button_confirm(self):
|
def button_confirm(self):
|
||||||
over_ordered_products = []
|
|
||||||
for item in self:
|
|
||||||
if item.requisition_id:
|
|
||||||
requisition_product_ids = item.requisition_id.line_ids.mapped('product_id.id')
|
|
||||||
for line in item.order_line:
|
|
||||||
if line.product_id.id in requisition_product_ids:
|
|
||||||
requisition_line = item.requisition_id.line_ids.filtered(
|
|
||||||
lambda r: r.product_id.id == line.product_id.id)
|
|
||||||
remaining_qty = requisition_line.product_qty - requisition_line.qty_ordered
|
|
||||||
if requisition_line and line.product_qty > remaining_qty:
|
|
||||||
over_ordered_products.append(
|
|
||||||
f'{line.product_id.name}:{remaining_qty} {requisition_line.product_uom_id.name}')
|
|
||||||
if over_ordered_products:
|
|
||||||
raise UserError('当前订购数量超过了关联协议的剩余数量,无法保存。\n涉及产品及剩余数量有:\n%s' % '\n'.join(
|
|
||||||
over_ordered_products))
|
|
||||||
result = super(RePurchaseOrder, self).button_confirm()
|
result = super(RePurchaseOrder, self).button_confirm()
|
||||||
for item in self:
|
for item in self:
|
||||||
# 确认订单时,自动分配序列号
|
# 确认订单时,自动分配序列号
|
||||||
@@ -500,90 +439,6 @@ class RePurchaseOrder(models.Model):
|
|||||||
purchase_order_overdue.write({'delivery_warning': 'normal'})
|
purchase_order_overdue.write({'delivery_warning': 'normal'})
|
||||||
return last_overdue_order, last_warning_order
|
return last_overdue_order, last_warning_order
|
||||||
|
|
||||||
def button_create_requisition(self):
|
|
||||||
self.ensure_one()
|
|
||||||
line_ids = []
|
|
||||||
for order_line in self.order_line:
|
|
||||||
line_values = {
|
|
||||||
'product_id': order_line.product_id.id,
|
|
||||||
'product_uom_id': order_line.product_uom.id,
|
|
||||||
'product_qty': order_line.product_qty,
|
|
||||||
'price_unit': order_line.price_unit,
|
|
||||||
}
|
|
||||||
line_ids.append((0, 0, line_values))
|
|
||||||
initial_data = {
|
|
||||||
'vendor_id': self.partner_id.id,
|
|
||||||
'origin': self.name,
|
|
||||||
'line_ids': line_ids,
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'res_model': 'purchase.requisition',
|
|
||||||
'view_mode': 'form',
|
|
||||||
'target': 'current',
|
|
||||||
'context': {
|
|
||||||
'default_origin': initial_data['origin'],
|
|
||||||
'default_line_ids': initial_data['line_ids'],
|
|
||||||
'default_vendor_id': initial_data['vendor_id'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def button_link_requisition(self):
|
|
||||||
requisition_ids = self.env['purchase.requisition'].sudo().search(
|
|
||||||
[('state', '=', 'ongoing'), ('vendor_id', '=', self.partner_id.id),
|
|
||||||
('line_ids.product_id', 'in', self.order_line.mapped('product_id.id'))])
|
|
||||||
|
|
||||||
# 新增的逻辑:过滤出符合条件的requisition_ids
|
|
||||||
valid_requisition_ids = []
|
|
||||||
for requisition in requisition_ids:
|
|
||||||
for line in requisition.line_ids:
|
|
||||||
if line.product_id in self.order_line.mapped(
|
|
||||||
'product_id') and line.product_qty - line.qty_ordered >= self.order_line.filtered(
|
|
||||||
lambda ol: ol.product_id == line.product_id).product_qty:
|
|
||||||
valid_requisition_ids.append(requisition.id)
|
|
||||||
break
|
|
||||||
|
|
||||||
action = {
|
|
||||||
'res_model': 'purchase.requisition',
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': _("选择采购申请"),
|
|
||||||
'domain': [('id', 'in', valid_requisition_ids)],
|
|
||||||
'views': [[self.env.ref('sf_sale.purchase_requisition_wizard_tree_view').id, 'list']],
|
|
||||||
'target': 'new',
|
|
||||||
'context': {'purchase_order_id': self.id},
|
|
||||||
}
|
|
||||||
return action
|
|
||||||
|
|
||||||
def button_unlink_requisition(self):
|
|
||||||
self.ensure_one()
|
|
||||||
for line in self.order_line:
|
|
||||||
if self.requisition_id:
|
|
||||||
requisition_line = self.requisition_id.line_ids.filtered(lambda r: r.product_id.id == line.product_id.id)
|
|
||||||
if requisition_line:
|
|
||||||
self.requisition_id.origin = False
|
|
||||||
self.requisition_id.purchase_ids = [(3, self.id)]
|
|
||||||
|
|
||||||
|
|
||||||
def action_view_requisition(self):
|
|
||||||
self.ensure_one()
|
|
||||||
requisition_ids = self.requisition_id.ids
|
|
||||||
action = {
|
|
||||||
'res_model': 'purchase.requisition',
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
}
|
|
||||||
if len(requisition_ids) == 1:
|
|
||||||
action.update({
|
|
||||||
'view_mode': 'form',
|
|
||||||
'res_id': requisition_ids[0],
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
action.update({
|
|
||||||
'name': _("采购协议来源%s", self.name),
|
|
||||||
'domain': [('id', 'in', requisition_ids)],
|
|
||||||
'view_mode': 'tree,form',
|
|
||||||
})
|
|
||||||
return action
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderLine(models.Model):
|
class PurchaseOrderLine(models.Model):
|
||||||
_inherit = 'purchase.order.line'
|
_inherit = 'purchase.order.line'
|
||||||
|
|||||||
@@ -25,14 +25,6 @@
|
|||||||
data-hotkey="y" groups="stock.group_stock_user"/>
|
data-hotkey="y" groups="stock.group_stock_user"/>
|
||||||
<button name="button_cancel" states="draft,to approve,sent,purchase" string="取消" type="object"
|
<button name="button_cancel" states="draft,to approve,sent,purchase" string="取消" type="object"
|
||||||
data-hotkey="x"/>
|
data-hotkey="x"/>
|
||||||
<field name="show_create_requisition_button" invisible="1"/>
|
|
||||||
<field name="show_requisition_fields" invisible="1"/>
|
|
||||||
<button name="button_create_requisition" string="创建协议" type="object"
|
|
||||||
attrs="{'invisible': [('show_create_requisition_button', '!=', False)]}"/>
|
|
||||||
<button name="button_link_requisition" string="关联协议" type="object"
|
|
||||||
attrs="{'invisible': [('requisition_id', '!=', False),('show_requisition_fields', '=', False)]}"/>
|
|
||||||
<button name="button_unlink_requisition" string="解绑协议" type="object"
|
|
||||||
attrs="{'invisible': [('show_requisition_fields', '=', False)]}"/>
|
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//header/button[@name='button_cancel'][2]" position="attributes">
|
<xpath expr="//header/button[@name='button_cancel'][2]" position="attributes">
|
||||||
<attribute name="invisible">1</attribute>
|
<attribute name="invisible">1</attribute>
|
||||||
@@ -218,17 +210,6 @@
|
|||||||
<xpath expr="//sheet/group/group[2]/div[@name='date_planned_div']" position="attributes">
|
<xpath expr="//sheet/group/group[2]/div[@name='date_planned_div']" position="attributes">
|
||||||
<attribute name="invisible">1</attribute>
|
<attribute name="invisible">1</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//div[@name='button_box']" position="inside">
|
|
||||||
<button class="oe_stat_button" name="action_view_requisition" type="object" icon="fa-file"
|
|
||||||
attrs="{'invisible': [('purchase_requisition_count', '=', 0)]}">
|
|
||||||
<div class="o_field_widget o_stat_info">
|
|
||||||
<span class="o_stat_value">
|
|
||||||
<field name="purchase_requisition_count"/>
|
|
||||||
</span>
|
|
||||||
<span class="o_stat_text">采购协议</span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
<record model="ir.ui.view" id="view_purchase_requisition_form_inherit_sf">
|
|
||||||
<field name="name">purchase.requisition.form.inherit.sf</field>
|
|
||||||
<field name="model">purchase.requisition</field>
|
|
||||||
<field name="inherit_id" ref="purchase_requisition.view_purchase_requisition_form"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//header/button[@name='action_in_progress'][1]" position="after">
|
|
||||||
<field name="is_upload_contract_file" invisible="1"/>
|
|
||||||
<button name="upload_contract_file" string="上传合同" type="object" class="oe_highlight"
|
|
||||||
attrs="{'invisible': ['|', ('is_upload_contract_file', '=', True), ('state', 'not in', ['draft'])]}"/>
|
|
||||||
]}"/>
|
|
||||||
<button name="delete_contract_file" string="删除合同" type="object" class="oe_highlight"
|
|
||||||
attrs="{'invisible': ['|', ('is_upload_contract_file', '=', False), ('state', 'not in', ['draft'])]}"/>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//group" position="replace">
|
|
||||||
<group>
|
|
||||||
<group>
|
|
||||||
<field name="type_id" attrs="{'readonly': [('state','!=','draft')]}"/>
|
|
||||||
<field name="date_end"
|
|
||||||
attrs="{'readonly': [('state','not in',('draft','in_progress','open','ongoing'))]}"/>
|
|
||||||
<field name="ordering_date"
|
|
||||||
attrs="{'readonly': [('state','not in',('draft','in_progress','open','ongoing'))]}"/>
|
|
||||||
<field name="schedule_date"
|
|
||||||
attrs="{'readonly': [('state','not in',('draft','in_progress','open','ongoing'))]}"/>
|
|
||||||
<field name="origin" placeholder="e.g. PO0025"
|
|
||||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
|
||||||
<field name="picking_type_id" options="{'no_open': True, 'no_create': True}"
|
|
||||||
groups="stock.group_adv_location" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
|
||||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"
|
|
||||||
attrs="{'readonly': [('state','not in',('draft'))]}"/>
|
|
||||||
</group>
|
|
||||||
<group>
|
|
||||||
<field name="is_quantity_copy" invisible='1'/>
|
|
||||||
<field name="user_id"
|
|
||||||
attrs="{'readonly': [('state','not in',('draft','in_progress','open'))]}"
|
|
||||||
domain="[('share', '=', False)]"/>
|
|
||||||
<field name="vendor_id" context="{'res_partner_search_mode': 'supplier'}"
|
|
||||||
attrs="{'required': [('is_quantity_copy', '=', 'none')], 'readonly': [('state', 'in', ['ongoing','done'])]}"/>
|
|
||||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
|
||||||
<field name="partner_ref"/>
|
|
||||||
<field name="contract_number"/>
|
|
||||||
<field name="payment_term_id" options="{'no_create': True}"/>
|
|
||||||
<field name="contract_summary"/>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//page[@name='products']//tree//field[@name='product_id']" position="after">
|
|
||||||
<field name="materials_id"/>
|
|
||||||
<field name="materials_type_id"/>
|
|
||||||
<field name="part_number"/>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//page[@name='products']//tree//field[@name='price_unit']" position="after">
|
|
||||||
<field name="delivery_date"/>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//notebook/page[1]" position="before">
|
|
||||||
<page string="合同" name="contract_documents"
|
|
||||||
attrs="{'invisible': [('contract_document_id', '=', False)]}"
|
|
||||||
autofocus="autofocus">
|
|
||||||
<group>
|
|
||||||
<group>
|
|
||||||
<field name="contract_document_id" invisible="1"/>
|
|
||||||
<field name="contract_file_name" invisible="1"/>
|
|
||||||
<field name="contract_file"
|
|
||||||
widget="adaptive_viewer"
|
|
||||||
filename="contract_file_name"/>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
from . import sale_order_wizard
|
from . import sale_order_wizard
|
||||||
from . import purchase_order_wizard
|
from . import purchase_order_wizard
|
||||||
from . import upload_file_upload
|
|
||||||
from . import purchase_requisition_wizard
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
from odoo import models, fields, api, _
|
|
||||||
import logging
|
|
||||||
from odoo.exceptions import UserError
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseRequisition(models.Model):
|
|
||||||
_inherit = 'purchase.requisition'
|
|
||||||
|
|
||||||
def action_confirm(self):
|
|
||||||
purchase_order_id = self.env.context.get('purchase_order_id')
|
|
||||||
purchase_order = self.env['purchase.order'].sudo().search([('id', '=', purchase_order_id)])
|
|
||||||
if purchase_order.requisition_id.id == self.id:
|
|
||||||
raise UserError(_('该采购订单已绑定%s协议') % purchase_order.name)
|
|
||||||
if purchase_order.requisition_id:
|
|
||||||
# 先解绑
|
|
||||||
purchase_order.button_unlink_requisition()
|
|
||||||
purchase_order.write({'requisition_id': self.id})
|
|
||||||
self.purchase_ids += purchase_order
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<record model="ir.ui.view" id="purchase_requisition_wizard_tree_view">
|
|
||||||
<field name="name">purchase.requisition.wizard.tree.view</field>
|
|
||||||
<field name="model">purchase.requisition</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree create="false" delete="false">
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="partner_ref"/>
|
|
||||||
<field name="contract_number"/>
|
|
||||||
<field name="create_date"/>
|
|
||||||
<button string="关联" type="object" name="action_confirm" class="btn-primary"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
from odoo import models, fields, api, _
|
|
||||||
|
|
||||||
|
|
||||||
class IrAttachmentUpload(models.TransientModel):
|
|
||||||
_name = 'ir.attachment.upload'
|
|
||||||
_description = '文件上传向导'
|
|
||||||
|
|
||||||
attachment = fields.Binary(string='选择文件', required=True)
|
|
||||||
filename = fields.Char(string='文件名')
|
|
||||||
res_model = fields.Char()
|
|
||||||
res_id = fields.Integer()
|
|
||||||
|
|
||||||
def action_upload_file(self):
|
|
||||||
self.ensure_one()
|
|
||||||
# 获取当前用户的 partner_id
|
|
||||||
current_partner = self.env.user.partner_id
|
|
||||||
# 首先创建 ir.attachment
|
|
||||||
attachment = self.env['ir.attachment'].create({
|
|
||||||
'name': self.filename,
|
|
||||||
'type': 'binary',
|
|
||||||
'datas': self.attachment,
|
|
||||||
'res_model': self.res_model,
|
|
||||||
'res_id': self.res_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
# 获取默认的文档文件夹
|
|
||||||
workspace = self.env['purchase.requisition'].update_documents_folder('待审')
|
|
||||||
|
|
||||||
# 创建 documents.document 记录
|
|
||||||
document = self.env['documents.document'].create({
|
|
||||||
'name': self.filename,
|
|
||||||
'attachment_id': attachment.id,
|
|
||||||
'folder_id': workspace.id,
|
|
||||||
'res_model': self.res_model,
|
|
||||||
'res_id': self.res_id,
|
|
||||||
'partner_id': current_partner.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
# 更新采购订单的合同文档字段
|
|
||||||
purchase_requisition = self.env['purchase.requisition'].browse(self.res_id)
|
|
||||||
purchase_requisition.write({
|
|
||||||
'contract_document_id': document.id,
|
|
||||||
'is_upload_contract_file': True
|
|
||||||
})
|
|
||||||
|
|
||||||
# 显示成功消息并关闭向导
|
|
||||||
message = {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('成功'),
|
|
||||||
'message': _('文件上传成功'),
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': False, # 自动消失
|
|
||||||
'next': {
|
|
||||||
'type': 'ir.actions.act_window_close'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<record id="view_upload_file_upload_form" model="ir.ui.view">
|
|
||||||
<field name="name">ir.attachment.upload.form</field>
|
|
||||||
<field name="model">ir.attachment.upload</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="上传文件">
|
|
||||||
<group>
|
|
||||||
<field name="attachment" widget="binary" filename="filename" options="{'accepted_file_extensions': '.pdf,.doc,.docx,.jpg,.jpeg,.png'}"/>
|
|
||||||
<field name="filename" invisible="1"/>
|
|
||||||
<field name="res_model" invisible="1"/>
|
|
||||||
<field name="res_id" invisible="1"/>
|
|
||||||
</group>
|
|
||||||
<footer>
|
|
||||||
<button name="action_upload_file" string="确认上传" type="object" class="btn-primary"/>
|
|
||||||
<button string="取消" class="btn-secondary" special="cancel"/>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
</odoo>
|
|
||||||
Reference in New Issue
Block a user