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"/> - - -