diff --git a/yuthon_property_approval/models/inherit_yuthon_property.py b/yuthon_property_approval/models/inherit_yuthon_property.py
index 9872a9ec7..83937d5bb 100644
--- a/yuthon_property_approval/models/inherit_yuthon_property.py
+++ b/yuthon_property_approval/models/inherit_yuthon_property.py
@@ -77,7 +77,7 @@ class PropertyBankStatements(models.Model):
'remark':None,
})
penalty_records = self.env['property.accounts.receivable'].search([
- ('payout_date', '=', start_date),
+ ('due_date', '=', start_date),
('lessee_id', '=', tenant_id),
('contract_id', 'in', rec.contract_ids.ids),
('property_id', 'in', rec.property_ids.ids),
@@ -222,7 +222,7 @@ class PropertyBankStatements(models.Model):
# 跳过已处理的合同
if contract_id and contract_id in processed_contracts:
continue
- # 获取合同的实际开始日期作为到期日
+ # 获取合同的实际结束日期作为到期日
due_date = False
if contract_id:
due_date = sub_record.contract_id.actual_start_time
diff --git a/yuthon_property_approval/wizard/property_reconciliation_wizard.py b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
index 151b02620..9c5889213 100644
--- a/yuthon_property_approval/wizard/property_reconciliation_wizard.py
+++ b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
@@ -31,18 +31,90 @@ class PropertyReconciliationWizard(models.Model):
# else:
# rec.amount_reconciled = 0.0
- @api.onchange('actual_total', 'actual_date')
+ @api.onchange('actual_total')
def _onchange_reconciliation_line_ids(self):
- if not self.reconciliation_line_ids:
- return
-
- # 提取已存在的违约金行用于去重判断
- existing_penalty_lines = [
- line for line in self.reconciliation_line_ids
- if line.collection_type == 'penalty'
- ]
-
new_lines = []
+ # 违约金生成
+ for contract_id in self.bank_id.contract_ids:
+ if not contract_id.lease_ids:
+ continue
+ last_lease_line = contract_id.lease_ids[-1]
+ property_id = last_lease_line.address_id.id if last_lease_line.address_id else False
+
+ start_time = self.bank_id.start_time
+ first_day_of_last_month = (start_time.replace(day=1) - relativedelta(months=1))
+ last_day_of_last_month = start_time.replace(day=1) - relativedelta(days=1)
+ contract_receivables = self.env['property.accounts.receivable'].search([
+ ('contract_id', '=', contract_id.id),
+ ('property_id', '=', property_id),
+ ('due_date', '>=', first_day_of_last_month.strftime('%Y-%m-%d')),
+ ('due_date', '<=', last_day_of_last_month.strftime('%Y-%m-%d')),
+ ('management_type_id.name', '=', '租金')
+ ], limit=1)
+ # 计算应收日期的下月1号
+ next_month_first = (fields.Date.from_string(contract_receivables.due_date) +
+ relativedelta(months=1)).replace(day=1)
+ # 检查是否产生违约
+ if fields.Date.from_string(self.actual_date) > next_month_first:
+ # 计算违约天数和违约金
+ late_days = (fields.Date.from_string(self.actual_date) - next_month_first).days + 1
+ penalty_amount = late_days * round(
+ contract_id.rent * float(contract_id.percentage_liquidated_damages.name), 2
+ )
+ start_date_str = fields.Date.to_string(next_month_first)
+ end_date_str = self.actual_date
+ contract_penalties = []
+
+ # 1. 处理新产生的违约金
+ if penalty_amount > 0:
+ contract_penalties.append({
+ 'property_id': property_id,
+ 'contract_id': contract_id.id,
+ 'rent_month': 0,
+ 'due_date': self.actual_date,
+ 'rent': penalty_amount,
+ 'amount': 0,
+ 'collection_type': 'penalty',
+ 'remake': f'违约金({start_date_str}至{end_date_str},共{late_days}天)',
+ })
+
+ # 2. 处理上月未对账的违约金延续
+ receivable_penalties = self.env['property.accounts.receivable'].search([
+ ('property_id', '=', property_id),
+ ('contract_id', '=', contract_id.id),
+ ('is_reconciliation', '=', False),
+ ('management_type_id.name', '=', '违约金')
+ ])
+
+ for penalty in receivable_penalties:
+ exists = any(p['rent'] == penalty.submitted and
+ p['due_date'] == penalty.due_date and
+ p['contract_id'] == penalty.contract_id.id
+ for p in contract_penalties)
+ if not exists:
+ contract_penalties.append({
+ 'property_id': penalty.property_id.id,
+ 'contract_id': penalty.contract_id.id,
+ 'rent_month': 0,
+ 'due_date': penalty.due_date,
+ 'rent': penalty.submitted,
+ 'amount': 0,
+ 'collection_type': 'penalty',
+ 'remake': penalty.remark,
+ })
+
+ # 3. 添加到总列表
+ for vals in contract_penalties:
+ new_lines.append((0, 0, vals))
+ if new_lines:
+ keep_lines = [
+ (4, line.id) for line in self.reconciliation_line_ids
+ if line.collection_type != 'penalty'
+ ]
+ self.reconciliation_line_ids = keep_lines + new_lines
+ if self.reconciliation_line_ids:
+ self.reconciliation_line_ids.sorted(key=lambda r: r.sequence)
+
remaining_amount = self.actual_total
# 检查是否有单行的rent等于实际金额
@@ -88,73 +160,6 @@ class PropertyReconciliationWizard(models.Model):
line.amount = assign_amount
remaining_amount -= assign_amount
- # 检查是否违约并创建违约金行(带去重)
- if (line.due_date and self.actual_date and line.collection_type != 'deposit'):
- # 计算应收日期的下月1号
- next_month_first = (fields.Date.from_string(line.due_date) + relativedelta(months=1)).replace(day=1)
- # 如果实收日期晚于下月1号,产生违约
- if fields.Date.from_string(self.actual_date) > next_month_first:
- # 计算违约天数
- late_days = (fields.Date.from_string(self.actual_date) - next_month_first).days + 1
- # 计算违约金
- penalty_amount = late_days * round(
- line.rent * float(line.contract_id.percentage_liquidated_damages.name), 2
- )
- start_date_str = fields.Date.to_string(next_month_first)
- end_date_str = self.actual_date
- if penalty_amount > 0:
- # 检查是否已存在相同条件的违约金行
- is_duplicate = any(
- pl.contract_id.id == line.contract_id.id
- and pl.property_id.id == line.property_id.id
- and pl.due_date == self.actual_date
- and pl.collection_type == 'penalty'
- for pl in existing_penalty_lines
- )
- if not is_duplicate:
- # 创建新的违约金记录
- penalty_line_vals = {
- 'property_id': line.property_id.id,
- 'contract_id': line.contract_id.id,
- 'rent_month': 0,
- 'due_date': self.actual_date,
- 'rent': penalty_amount,
- 'amount': 0,
- 'collection_type': 'penalty',
- 'remake': f'违约金({start_date_str}至{end_date_str},共{late_days}天)',
- 'sequence': int(line.sequence) + 1,
- }
- new_lines.append((0, 0, penalty_line_vals))
- # 上月违约金未对账延续
- receivable_penalties = self.env['property.accounts.receivable'].search([
- ('property_id', 'in', self.bank.property_ids.ids),
- ('contract_id', 'in', self.bank.contract_ids.ids),
- ('is_reconciliation', '=', False),
- ('management_type_id.name', '=', '违约金')
- ])
- for penalty in receivable_penalties:
- receivable_line_vals = {
- 'property_id': penalty.property_id.id,
- 'contract_id': penalty.contract_id.id,
- 'rent_month': 0,
- 'due_date': penalty.due_date,
- 'rent': penalty.submitted,
- 'amount': 0,
- 'collection_type': 'penalty',
- 'remake': penalty.remark,
- 'sequence': int(line.sequence) + 2,
- }
- new_lines.append((0, 0, receivable_line_vals))
-
- if new_lines:
- keep_lines = [
- (4, line.id) for line in self.reconciliation_line_ids
- if line.collection_type != 'penalty'
- ]
- self.reconciliation_line_ids = keep_lines + new_lines
- if self.reconciliation_line_ids:
- self.reconciliation_line_ids.sorted(key=lambda r: r.sequence)
-
def confirm(self):
for rec in self:
bank_lines = self.env['property.bank.line'].search([
diff --git a/yuthon_purchase/__manifest__.py b/yuthon_purchase/__manifest__.py
index 4a46e0157..60322f295 100644
--- a/yuthon_purchase/__manifest__.py
+++ b/yuthon_purchase/__manifest__.py
@@ -6,14 +6,11 @@
'category': 'zhou',
'version': '0.1',
'license': 'LGPL-3',
- 'depends': ['base', 'soong_workflow', 'hr', 'product', 'documents', 'purchase', 'contacts'],
+ 'depends': ['base', 'soong_workflow', 'hr', 'product', 'documents', 'purchase'],
'data': [
'security/ir.model.access.csv',
'data/purchase_data.xml',
- 'views/purchase_fixed_assets_views.xml',
- 'views/purchase_low_orders_views.xml',
- 'views/inherit_res_partner_views.xml',
- 'views/purchase_service_orders_views.xml',
+ 'views/purchase_workflow_views.xml',
'views/menu.xml',
],
'installable': True,
diff --git a/yuthon_purchase/models/__init__.py b/yuthon_purchase/models/__init__.py
index b3fff6b0b..d9805b309 100644
--- a/yuthon_purchase/models/__init__.py
+++ b/yuthon_purchase/models/__init__.py
@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
-from . import purchase_fixed_assets
-from . import purchase_low_orders
-from . import purchase_service_orders
from . import inherit_purchase_order
-# from . import inherit_res_partner
+from . import purchase_workflow
\ No newline at end of file
diff --git a/yuthon_purchase/models/inherit_res_partner.py b/yuthon_purchase/models/inherit_res_partner.py
deleted file mode 100644
index fc27c18d5..000000000
--- a/yuthon_purchase/models/inherit_res_partner.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import api, fields, models
-
-
-class InheritResPartner(models.Model):
- _inherit = 'res.partner'
-
- partner_category = fields.Selection([('party', '乙方'), ('suppliers', '供应商')], string='类型')
diff --git a/yuthon_purchase/models/purchase_fixed_assets.py b/yuthon_purchase/models/purchase_fixed_assets.py
deleted file mode 100644
index cf3d71c25..000000000
--- a/yuthon_purchase/models/purchase_fixed_assets.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import api, fields, models
-
-
-class PurchaseFixedAssets(models.Model):
- _name = 'purchase.fixed.assets'
- _description = '固定资产采购单'
- _inherit = ['soong.workflow.mixin']
-
- code = fields.Char(string="流水号",
- default=lambda self: self.env['ir.sequence'].next_by_code('purchase_order_sequence_code'))
- name = fields.Char(string="名称")
- company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
- user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user)
- department_id = fields.Many2one(related='user_id.employee_id.department_id', string="部门")
- partner_id = fields.Many2one('res.partner', string="供应商")
- date_order = fields.Datetime(string="订单日期")
- date_planned = fields.Datetime(string="预计到货日期")
- start_date = fields.Date(string="申请日期", default=fields.Date.today)
- reason_text = fields.Text(string='申请事由')
- document_ids = fields.Many2many('ir.attachment', string="附件")
- urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
- default='normal')
- active = fields.Boolean('Active', default=True, tracking=True)
- pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string='付款方式', default='onetime')
- purchase_order_models_ids = fields.One2many('purchase.order.pay.line', 'purchase_id', string="付款详情")
- fixed_ids = fields.One2many('purchase.fixed.line', 'purchase_id', string="采购明细")
- work_end = fields.Boolean(string="结束")
-
- def _get_default_name_title(self):
- return self._description if self._description else self._name
-
- name_title = fields.Char(default=_get_default_name_title, string="标题")
-
- def end_approval(self):
- for rec in self:
- purchase_order = self.env['purchase.order'].create({
- 'partner_id': rec.partner_id.id,
- 'date_order': rec.date_order if rec.date_order else None,
- 'date_planned': rec.date_planned if rec.date_planned else None,
- 'company_id': rec.company_id.id,
- 'user_id': rec.user_id.id,
- })
- order_lines = []
- for fixed_line in rec.fixed_ids:
- if not fixed_line.product_id:
- continue
- order_lines.append((0, 0, {
- 'order_id': purchase_order.id,
- 'product_id': fixed_line.product_id.id,
- 'product_qty': fixed_line.number,
- 'name': fixed_line.name,
- 'price_unit':fixed_line.price_unit,
- 'product_packaging_id': fixed_line.product_packaging_id.id,
- 'taxes_id': fixed_line.taxes_id,
- }))
- if order_lines:
- purchase_order.order_line = order_lines
-
-
-class PurchaseOrderPayLine(models.Model):
- _name = "purchase.order.pay.line"
- _description = "付款详情"
-
- purchase_id = fields.Many2one('purchase.fixed.assets', string="关联采购单")
- low_id = fields.Many2one('purchase.low.orders', string="关联低值易耗采购单")
- service_id = fields.Many2one('purchase.service.orders', string="关联服务采购单")
- payment_stage = fields.Char(string="付款阶段")
- amount = fields.Char(string="比例/金额")
- payment_date = fields.Date(string="付款日期")
- remake = fields.Char(string="条件")
-
-
-class PurchaseFixedLine(models.Model):
- _name = 'purchase.fixed.line'
- _description = '固定资产采购单明细'
-
- purchase_id = fields.Many2one('purchase.fixed.assets', string="关联采购单")
- product_id = fields.Many2one('product.product', string="物品名称")
- brand = fields.Char(string="品牌")
- specs = fields.Char(string="规格")
- number = fields.Integer(string="数量")
- name = fields.Text(string="描述")
- product_packaging_id = fields.Many2one('product.packaging', string="包装")
- taxes_id = fields.Many2one('account.tax', string='税项')
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- price = fields.Float(related='product_id.standard_price', string="单价", stroe=True)
\ No newline at end of file
diff --git a/yuthon_purchase/models/purchase_low_orders.py b/yuthon_purchase/models/purchase_low_orders.py
deleted file mode 100644
index 5083f56f8..000000000
--- a/yuthon_purchase/models/purchase_low_orders.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import api, fields, models
-from datetime import datetime
-
-
-class PurchaseLowOrders(models.Model):
- _name = 'purchase.low.orders'
- _description = '低值易耗采购单'
- _inherit = ['soong.workflow.mixin']
-
- name = fields.Char(string="标题")
- code = fields.Char(string="合同编号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_low_orders_code'))
- user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
- date_application = fields.Date(string="申请日期", default=fields.Date.today())
- company_id = fields.Many2one('res.company', string='公司', index=True, default=lambda self: self.env.company)
- reason_application = fields.Text(string="申请事由")
- department_id = fields.Many2one(related='user_id.employee_id.department_id', string="申请部门")
- party_id = fields.Many2one('res.partner', string="乙方")
- document_ids = fields.Many2many('ir.attachment', string="附件")
- pay_way = fields.Selection([('staging', '分期'), ('full', '一次性')], string='付款方式', default='full')
- total = fields.Float(string="合计")
- urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
- default='normal')
- work_end = fields.Boolean(string="结束")
- active = fields.Boolean('Active', default=True, tracking=True)
- low_line_ids = fields.One2many('purchase.low.line', 'purchase_id', string="采购明细")
- purchase_ids = fields.One2many('purchase.order.pay.line', 'low_id', string="采购单")
-
- def _get_default_name_title(self):
- return self._description if self._description else self._name
-
- name_title = fields.Char(default=_get_default_name_title)
-
- def end_approval(self):
- for rec in self:
- date_with_time = datetime.combine(
- fields.Date.from_string(rec.date_application),
- datetime.min.time().replace(hour=0)
- )
- purchase_order = self.env['purchase.order'].create({
- 'partner_id': rec.party_id.id,
- 'date_order': date_with_time,
- 'company_id': rec.company_id.id,
- 'user_id': rec.user_id.id,
- })
- order_lines = []
- for low_line in rec.low_line_ids:
- if not low_line.product_id:
- continue
- order_lines.append((0, 0, {
- 'order_id': purchase_order.id,
- 'product_id': low_line.product_id.id,
- 'product_qty': low_line.number,
- 'product_uom': low_line.unit_id.id,
- 'price_unit': low_line.price,
- 'name': low_line.name,
- 'product_packaging_id': low_line.product_packaging_id.id,
- 'taxes_id': low_line.taxes_id,
- }))
- if order_lines:
- purchase_order.order_line = order_lines
-
-
-
-class PurchaseLowLine(models.Model):
- _name = 'purchase.low.line'
- _description = '低值易耗采购单明细'
-
- purchase_id = fields.Many2one('purchase.low.orders', string="关联采购单")
- product_id = fields.Many2one('product.product', string="物品名称")
- brand = fields.Char(string="品牌")
- specs = fields.Char(string="规格")
- name = fields.Text(string="描述")
- product_packaging_id = fields.Many2one('product.packaging', string="包装")
- taxes_id = fields.Many2one('account.tax', string='税项')
- number = fields.Integer(string="数量")
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- price = fields.Float(related='product_id.standard_price', string="单价")
-
-
-
diff --git a/yuthon_purchase/models/purchase_service_orders.py b/yuthon_purchase/models/purchase_service_orders.py
deleted file mode 100644
index 9763786bf..000000000
--- a/yuthon_purchase/models/purchase_service_orders.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import api, fields, models
-from datetime import datetime
-
-
-class PurchaseServiceOrders(models.Model):
- _name = 'purchase.service.orders'
- _description = '服务采购单'
- _inherit = ['soong.workflow.mixin']
-
- name = fields.Char(string="标题")
- code = fields.Char(string="合同编号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_service_orders_code'))
- user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
- date_application = fields.Date(string="申请日期", default=fields.Date.today())
- company_id = fields.Many2one('res.company', string='公司', index=True, default=lambda self: self.env.company)
- reason_application = fields.Text(string="申请事由")
- service_content = fields.Text(string="服务内容")
- service_start_date = fields.Date(string="服务开始日期")
- service_end_date = fields.Date(string="服务结束日期")
- service_year = fields.Char(string="服务年限")
- department_id = fields.Many2one(related='user_id.employee_id.department_id', string="申请部门")
- party_id = fields.Many2one('res.partner', string="乙方")
- license_id = fields.Many2one('ir.attachment', string='营业执照')
- aptitude_id = fields.Many2one('ir.attachment', string='资质')
- contract_id = fields.Many2one('ir.attachment', string='合同')
- other_id = fields.Many2one('ir.attachment', string='其他')
- pay_way = fields.Selection([('staging', '分期'), ('full', '一次性')], string='付款方式', default='full')
- total = fields.Float(string="合计")
- urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
- default='normal')
- work_end = fields.Boolean(string="结束")
- active = fields.Boolean('Active', default=True, tracking=True)
- service_line_ids = fields.One2many('purchase.service.line', 'service_id', string="采购明细")
- purchase_ids = fields.One2many('purchase.order.pay.line', 'service_id', string="采购单")
-
- def _get_default_name_title(self):
- return self._description if self._description else self._name
-
- name_title = fields.Char(default=_get_default_name_title)
-
-
- def end_approval(self):
- for rec in self:
- date_with_time = datetime.combine(
- fields.Date.from_string(rec.date_application),
- datetime.min.time().replace(hour=0)
- )
- purchase_order = self.env['purchase.order'].create({
- 'partner_id': rec.party_id.id,
- 'date_order': date_with_time,
- 'company_id': rec.company_id.id,
- 'user_id': rec.user_id.id,
- })
- order_lines = []
- for service_line in rec.service_line_ids:
- if not service_line.product_id:
- continue
- order_lines.append((0, 0, {
- 'order_id': purchase_order.id,
- 'product_id': service_line.product_id.id,
- 'name': service_line.name,
- 'product_packaging_id': service_line.product_packaging_id.id,
- 'taxes_id': service_line.taxes_id,
- 'price_unit': service_line.price,
- }))
- if order_lines:
- purchase_order.order_line = order_lines
-
-
-class PurchaseServiceLine(models.Model):
- _name = 'purchase.service.line'
- _description = '服务采购单明细'
-
- service_id = fields.Many2one('purchase.service.orders', string="关联采购单")
- product_id = fields.Many2one('product.product', string="服务项目")
- frequency = fields.Char(string='频次')
- fee = fields.Float(string="费用")
- name = fields.Text(string="描述")
- product_packaging_id = fields.Many2one('product.packaging', string="包装")
- taxes_id = fields.Many2one('account.tax', string='税项')
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- party_id = fields.Many2one('res.partner', string="供应商")
- price = fields.Float(related='product_id.standard_price', string="单价")
-
-
-
-
diff --git a/yuthon_purchase/models/purchase_workflow.py b/yuthon_purchase/models/purchase_workflow.py
new file mode 100644
index 000000000..26372e22e
--- /dev/null
+++ b/yuthon_purchase/models/purchase_workflow.py
@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+from odoo import api, fields, models
+
+
+class PurchaseWorkflow(models.Model):
+ _name = 'purchase.workflow'
+ _description = '采购工作流'
+
+ code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_order_sequence_code'))
+ name = fields.Char(string="标题")
+ name_title = fields.Char(string="默认标题", default=lambda self: self._description, readonly=True)
+ user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user, required=True)
+ department_id = fields.Many2one(related='user_id.employee_id.department_id', string="申请部门", store=True,
+ readonly=True)
+ company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company, required=True)
+ start_date = fields.Date(string="申请日期", default=fields.Date.today(), required=True)
+ date_order = fields.Datetime(string="订单日期")
+ date_planned = fields.Datetime(string="预计到货日期")
+ date_application = fields.Date(string="申请日期", default=fields.Date.today(), readonly=True)
+ partner_id = fields.Many2one('res.partner', string="供应商/乙方", required=True)
+ reason_text = fields.Text(string="申请事由")
+ urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string="紧急度",
+ default='normal', required=True)
+ pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string="付款方式", default='onetime',
+ required=True)
+ total = fields.Float(string="合计金额", readonly=True)
+ document_ids = fields.Many2many('ir.attachment', string="附件")
+ active = fields.Boolean('启用', default=True, tracking=True)
+ work_end = fields.Boolean(string="审批结束", default=False, tracking=True)
+
+ purchase_type = fields.Selection([('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务')],
+ string="采购类型", required=True, default='fixed')
+
+ service_content = fields.Text(string="服务内容")
+ service_start_date = fields.Date(string="服务开始日期")
+ service_end_date = fields.Date(string="服务结束日期")
+ service_year = fields.Char(string="服务年限")
+ license_id = fields.Many2one('ir.attachment', string='营业执照')
+ aptitude_id = fields.Many2one('ir.attachment', string='资质')
+ contract_id = fields.Many2one('ir.attachment', string='合同')
+ fixed_line_ids = fields.One2many('purchase.fixed.line', 'purchase_id', string="固定资产明细")
+ low_line_ids = fields.One2many('purchase.low.line', 'purchase_id', string="低值易耗明细")
+ service_line_ids = fields.One2many('purchase.service.line', 'service_id', string="服务明细")
+ pay_line_ids = fields.One2many('purchase.order.pay.line', 'purchase_id', string="付款详情")
+
+ @api.onchange('purchase_type')
+ def _onchange_purchase_type(self):
+ if self.purchase_type == 'fixed':
+ self.low_line_ids = [(5, 0, 0)]
+ self.service_line_ids = [(5, 0, 0)]
+ elif self.purchase_type == 'low':
+ self.fixed_line_ids = [(5, 0, 0)]
+ self.service_line_ids = [(5, 0, 0)]
+ elif self.purchase_type == 'service':
+ self.fixed_line_ids = [(5, 0, 0)]
+ self.low_line_ids = [(5, 0, 0)]
+
+ def end_approval(self):
+ for rec in self:
+ purchase_order = self.env['purchase.order'].create({
+ 'partner_id': rec.partner_id.id,
+ 'date_order': rec.date_order,
+ 'date_planned': rec.date_planned,
+ 'company_id': rec.company_id.id,
+ 'user_id': rec.user_id.id,
+ 'origin': f"{rec.code}({dict(rec._fields['purchase_type'].selection).get(rec.purchase_type)})"
+ })
+ order_lines = []
+ if rec.purchase_type == 'fixed':
+ for line in rec.fixed_line_ids:
+ if not line.product_id:
+ continue
+ order_lines.append((0, 0, {
+ 'product_id': line.product_id.id,
+ 'product_qty': line.number,
+ 'name': line.name,
+ 'price_unit': line.price_unit,
+ 'product_packaging_id': line.product_packaging_id.id,
+ 'taxes_id': [(6, 0, line.taxes_id.ids)] if line.taxes_id else False
+ }))
+ elif rec.purchase_type == 'low':
+ for line in rec.low_line_ids:
+ if not line.product_id:
+ continue
+ order_lines.append((0, 0, {
+ 'product_id': line.product_id.id,
+ 'product_qty': line.number,
+ 'product_uom': line.unit_id.id,
+ 'name': line.name,
+ 'price_unit': line.price,
+ 'product_packaging_id': line.product_packaging_id.id,
+ 'taxes_id': [(6, 0, line.taxes_id.ids)] if line.taxes_id else False
+ }))
+ elif rec.purchase_type == 'service':
+ for line in rec.service_line_ids:
+ if not line.product_id:
+ continue
+ order_lines.append((0, 0, {
+ 'product_id': line.product_id.id,
+ 'name': line.name,
+ 'price_unit': line.price,
+ 'product_packaging_id': line.product_packaging_id.id,
+ 'taxes_id': [(6, 0, line.taxes_id.ids)] if line.taxes_id else False
+ }))
+ if order_lines:
+ purchase_order.order_line = order_lines
+
+
+class PurchaseOrderPayLine(models.Model):
+ _name = "purchase.order.pay.line"
+ _description = "付款详情"
+
+ purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+ payment_stage = fields.Char(string="付款阶段")
+ amount = fields.Char(string="比例/金额")
+ payment_date = fields.Date(string="付款日期")
+ remake = fields.Char(string="条件")
+
+
+class PurchaseFixedLine(models.Model):
+ _name = 'purchase.fixed.line'
+ _description = '固定资产采购明细'
+
+ purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+ product_id = fields.Many2one('product.product', string="物品名称")
+ brand = fields.Char(string="品牌")
+ specs = fields.Char(string="规格")
+ number = fields.Integer(string="数量",)
+ name = fields.Text(string="描述")
+ product_packaging_id = fields.Many2one('product.packaging', string="包装")
+ taxes_id = fields.Many2one('account.tax', string='税项')
+ unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
+ price_unit = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ total = fields.Float(string="合计", compute='_compute_total', store=True, )
+
+ @api.depends('price_unit', 'number')
+ def _compute_total(self):
+ for line in self:
+ line.total = round(line.price_unit * line.number, 2)
+
+class PurchaseLowLine(models.Model):
+ _name = 'purchase.low.line'
+ _description = '低值易耗采购明细'
+ purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+ product_id = fields.Many2one('product.product', string="物品名称")
+ brand = fields.Char(string="品牌")
+ specs = fields.Char(string="规格")
+ name = fields.Text(string="描述")
+ product_packaging_id = fields.Many2one('product.packaging', string="包装")
+ taxes_id = fields.Many2one('account.tax', string='税项')
+ number = fields.Integer(string="数量")
+ unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
+ price = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ total = fields.Float(string="合计", compute='_compute_total', store=True)
+
+ @api.depends('price', 'number')
+ def _compute_total(self):
+ for line in self:
+ line.total = round(line.price * line.number, 2)
+
+
+class PurchaseServiceLine(models.Model):
+ _name = 'purchase.service.line'
+ _description = '服务采购明细'
+
+ service_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+ product_id = fields.Many2one('product.product', string="服务项目")
+ frequency = fields.Integer(string='频次')
+ fee = fields.Float(string="费用")
+ name = fields.Text(string="描述")
+ product_packaging_id = fields.Many2one('product.packaging', string="包装")
+ taxes_id = fields.Many2one('account.tax', string='税项')
+ unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
+ price = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ total = fields.Float(string="合计", compute='_compute_total', store=True)
+
+ @api.depends('price', 'frequency')
+ def _compute_total(self):
+ for line in self:
+ line.total = round(line.price * line.frequency, 2)
+
+class PurchaseFixedAssets(models.Model):
+ _name = 'purchase.fixed.assets'
+
+class PurchaseServiceOrders(models.Model):
+ _name = 'purchase.service.orders'
+
+class PurchaseLowOrders(models.Model):
+ _name = 'purchase.low.orders'
\ No newline at end of file
diff --git a/yuthon_purchase/security/ir.model.access.csv b/yuthon_purchase/security/ir.model.access.csv
index f301afc11..b5211b5e2 100644
--- a/yuthon_purchase/security/ir.model.access.csv
+++ b/yuthon_purchase/security/ir.model.access.csv
@@ -1,8 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_purchase_fixed_assets,purchase_fixed_assets,model_purchase_fixed_assets,,1,1,1,1
access_purchase_fixed_line, purchase_fixed_line,model_purchase_fixed_line,,1,1,1,1
access_purchase_order_pay_line,purchase_order_pay_line,model_purchase_order_pay_line,,1,1,1,1
-access_purchase_low_orders, purchase_low_orders,model_purchase_low_orders,,1,1,1,1
-access_purchase_service_orders, purchase_service_orders,model_purchase_service_orders,,1,1,1,1
access_purchase_low_line, purchase_low_line,model_purchase_low_line,,1,1,1,1
-access_purchase_service_line, purchase_service_line,model_purchase_service_line,,1,1,1,1
\ No newline at end of file
+access_purchase_service_line, purchase_service_line,model_purchase_service_line,,1,1,1,1
+access_purchase_workflow, purchase_workflow,model_purchase_workflow,,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_purchase/views/inherit_res_partner_views.xml b/yuthon_purchase/views/inherit_res_partner_views.xml
deleted file mode 100644
index f7a14737a..000000000
--- a/yuthon_purchase/views/inherit_res_partner_views.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- res.partner.form.inherit
- res.partner
-
-
-
-
-
-
-
-
- res.partner.search.inherit
- res.partner
-
-
-
-
-
-
-
-
diff --git a/yuthon_purchase/views/purchase_fixed_assets_views.xml b/yuthon_purchase/views/purchase_fixed_assets_views.xml
deleted file mode 100644
index d582f8563..000000000
--- a/yuthon_purchase/views/purchase_fixed_assets_views.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
- purchase.fixed.assets.tree
- purchase.fixed.assets
-
-
-
-
-
-
-
-
-
-
-
- purchase.fixed.assets.form
- purchase.fixed.assets
-
-
-
-
-
- 固定资产采购单
- purchase.fixed.assets
- tree,form
-
-
diff --git a/yuthon_purchase/views/purchase_low_orders_views.xml b/yuthon_purchase/views/purchase_low_orders_views.xml
deleted file mode 100644
index 31453a718..000000000
--- a/yuthon_purchase/views/purchase_low_orders_views.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
- purchase.low.orders.tree
- purchase.low.orders
-
-
-
-
-
-
-
-
-
-
-
-
- purchase.low.orders.form
- purchase.low.orders
-
-
-
-
-
- 低值易耗品采购单
- purchase.low.orders
- tree,form
-
-
diff --git a/yuthon_purchase/views/purchase_service_orders_views.xml b/yuthon_purchase/views/purchase_service_orders_views.xml
deleted file mode 100644
index 1c9a79460..000000000
--- a/yuthon_purchase/views/purchase_service_orders_views.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
- purchase.service.orders.tree
- purchase.service.orders
-
-
-
-
-
-
-
-
-
-
-
-
- purchase.service.orders.form
- purchase.service.orders
-
-
-
-
-
- 服务采购单
- purchase.service.orders
- tree,form
-
-
-
-
-
-
diff --git a/yuthon_purchase/views/purchase_workflow_views.xml b/yuthon_purchase/views/purchase_workflow_views.xml
new file mode 100644
index 000000000..9a69f6b79
--- /dev/null
+++ b/yuthon_purchase/views/purchase_workflow_views.xml
@@ -0,0 +1,144 @@
+
+
+
+ purchase.workflow.tree
+ purchase.workflow
+
+
+
+
+
+
+
+
+
+
+
+ purchase.workflow.form
+ purchase.workflow
+
+
+
+
+
+ 采购申请单
+ purchase.workflow
+ tree,form
+
+
diff --git a/yuthon_work_brand/views/purchase_menus.xml b/yuthon_work_brand/views/purchase_menus.xml
index a75f2bcf5..93bc35a9d 100644
--- a/yuthon_work_brand/views/purchase_menus.xml
+++ b/yuthon_work_brand/views/purchase_menus.xml
@@ -18,21 +18,11 @@
parent="purchase_menus_order_root"
action="purchase.purchase_form_action"
sequence="5"/>
-
-
-