v3-annual
This commit is contained in:
parent
767f0048a4
commit
a2f3f75ea9
|
|
@ -9,8 +9,10 @@ class AnnualAddendum(models.Model):
|
|||
_order = "create_date desc"
|
||||
|
||||
name = fields.Char(string="Reference", default=lambda self: self.env['ir.sequence'].next_by_code('odx.annual.addendum'), readonly=True, copy=False)
|
||||
agreement_id = fields.Many2one('purchase.requisition', string="Agreement", required=True, domain=[('type_id.code','=','blanket_order')])
|
||||
vendor_id = fields.Many2one(related='agreement_id.vendor_id', store=True, readonly=True)
|
||||
agreement_id = fields.Many2one('purchase.requisition', string="Agreement", required=True)
|
||||
annual_request_id = fields.Many2one('odx.annual.request', string="Annual Request", index=True, ondelete='cascade')
|
||||
vendor_id = fields.Many2one(related='annual_request_id.vendor_id', store=True, readonly=True)
|
||||
|
||||
department_id = fields.Many2one('hr.department', string="Department")
|
||||
purpose = fields.Char(string="Purpose")
|
||||
note = fields.Text(string="Notes")
|
||||
|
|
@ -23,6 +25,9 @@ class AnnualAddendum(models.Model):
|
|||
('cancel','Cancelled'),
|
||||
], default='draft', tracking=True)
|
||||
line_ids = fields.One2many('odx.annual.addendum.line', 'addendum_id', string="Lines")
|
||||
ssd_approve = fields.Boolean(string="SSD Approve", default=False)
|
||||
seo_approve = fields.Boolean(string="SEO Approve", default=False)
|
||||
recommendation = fields.Boolean(string="Recommendation", default=False)
|
||||
|
||||
def _check_lines(self):
|
||||
for rec in self:
|
||||
|
|
@ -69,6 +74,43 @@ class AnnualAddendumLine(models.Model):
|
|||
product_id = fields.Many2one('product.product', string="Product", required=True, domain=[('purchase_ok','=',True)])
|
||||
description = fields.Char(string="Description")
|
||||
quantity = fields.Float(string="Quantity", default=1.0)
|
||||
uom_id = fields.Many2one('uom.uom', string="UoM", related='product_id.uom_po_id', readonly=False)
|
||||
price_unit = fields.Monetary(string="Unit Price", currency_field='currency_id', groups="purchase_requisition_custom.committe_member")
|
||||
currency_id = fields.Many2one('res.currency', related='addendum_id.agreement_id.company_id.currency_id', readonly=True, store=True)
|
||||
uom_id = fields.Many2one('uom.uom', string="UoM", related='product_id.uom_po_id')
|
||||
price_unit = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency',
|
||||
related='addendum_id.agreement_id.company_id.currency_id',
|
||||
readonly=True, store=True
|
||||
)
|
||||
addendum_company_id = fields.Many2one(
|
||||
'res.company',
|
||||
related='addendum_id.agreement_id.company_id',
|
||||
readonly=True, store=True
|
||||
)
|
||||
taxes_id = fields.Many2many(
|
||||
'account.tax', string="Taxes",
|
||||
domain="[('type_tax_use','=','purchase'), ('company_id','=', addendum_company_id)]"
|
||||
)
|
||||
price_subtotal = fields.Monetary(
|
||||
string="Subtotal", currency_field='currency_id',
|
||||
compute='_compute_amounts', store=True, readonly=True
|
||||
)
|
||||
|
||||
@api.depends('quantity', 'price_unit', 'taxes_id', 'currency_id', 'product_id')
|
||||
def _compute_amounts(self):
|
||||
for rec in self:
|
||||
qty = rec.quantity or 0.0
|
||||
price_unit = rec.price_unit or 0.0
|
||||
currency = rec.currency_id
|
||||
|
||||
taxes = rec.taxes_id
|
||||
if rec.addendum_company_id:
|
||||
taxes = taxes.filtered(lambda t: t.company_id == rec.addendum_company_id)
|
||||
|
||||
res = taxes.compute_all(
|
||||
price_unit,
|
||||
currency=currency,
|
||||
quantity=qty,
|
||||
product=rec.product_id,
|
||||
partner=None
|
||||
)
|
||||
rec.price_subtotal = res['total_excluded']
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class AnnualPurchaseRequest(models.Model):
|
|||
note = fields.Text(string="Notes")
|
||||
state = fields.Selection(selection=STATES, default='draft', tracking=True)
|
||||
line_ids = fields.One2many('odx.annual.request.line', 'request_id', string="Products")
|
||||
agreement_id = fields.Many2one('purchase.requisition', string="Purchase Agreement", readonly=True, tracking=True)
|
||||
vendor_id = fields.Many2one('res.partner', string="Selected Vendor", domain=[('supplier_rank','>',0)], tracking=True)
|
||||
agreement_id = fields.Many2one('purchase.requisition', string="Purchase Agreement", readonly=True)
|
||||
vendor_id = fields.Many2one('res.partner', string="Selected Vendor", domain=[('supplier_rank','>',0)])
|
||||
currency_id = fields.Many2one('res.currency', string="Currency", default=lambda self: self.env.company.currency_id.id)
|
||||
technical_notes = fields.Html(string="Technical Notes")
|
||||
financial_notes = fields.Html(string="Financial Notes", groups="purchase_requisition_custom.committe_member")
|
||||
|
|
@ -46,13 +46,13 @@ class AnnualPurchaseRequest(models.Model):
|
|||
('rejected','Rejected by Committee'),
|
||||
('recommended','Recommended'),
|
||||
('approved','Approved by Committee'),
|
||||
], default='none', tracking=True)
|
||||
], default='none')
|
||||
|
||||
product_category_ids = fields.Many2many('product.category', string='Items Categories',
|
||||
compute='_compute_product_category_ids',
|
||||
store=True)
|
||||
|
||||
committee_enabled = fields.Boolean(string="Require Committee Review", default=False, tracking=True)
|
||||
committee_enabled = fields.Boolean(string="Require Committee Review", default=False)
|
||||
ssd_approve = fields.Boolean(string="SSD Approve", default=False)
|
||||
seo_approve = fields.Boolean(string="SEO Approve", default=False)
|
||||
|
||||
|
|
@ -78,33 +78,71 @@ class AnnualPurchaseRequest(models.Model):
|
|||
store=False,
|
||||
readonly=True,
|
||||
)
|
||||
addendum_count = fields.Integer(string='Addendums', compute='_compute_addendum_count', readonly=True)
|
||||
def _compute_addendum_count(self):
|
||||
Addendum = self.env['odx.annual.addendum']
|
||||
for rec in self:
|
||||
rec.addendum_count = Addendum.search_count([('annual_request_id', '=', rec.id)])
|
||||
|
||||
def action_open_addendums(self):
|
||||
self.ensure_one()
|
||||
domain = [('annual_request_id', '=', self.id)]
|
||||
return {
|
||||
'name': _('Addendums'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'odx.annual.addendum',
|
||||
'view_mode': 'tree,form',
|
||||
'domain': domain,
|
||||
'context': {
|
||||
'default_annual_request_id': self.id,
|
||||
'default_agreement_id': self.agreement_id.id if self.agreement_id else False,
|
||||
'default_department_id': self.department_id.id if self.department_id else False,
|
||||
'default_purpose': self.purpose or False,
|
||||
},
|
||||
'target': 'current',
|
||||
}
|
||||
def _compute_attach_no(self):
|
||||
Attachment = self.env['ir.attachment']
|
||||
for rec in self:
|
||||
rec.attach_no = Attachment.search_count([
|
||||
count_self = Attachment.search_count([
|
||||
('res_model', '=', rec._name),
|
||||
('res_id', '=', rec.id)
|
||||
])
|
||||
|
||||
purchase_orders = self.env['purchase.order'].search([('annual_request_id', '=', rec.id)])
|
||||
count_po = 0
|
||||
if purchase_orders:
|
||||
count_po = Attachment.search_count([
|
||||
('res_model', '=', 'purchase.order'),
|
||||
('res_id', 'in', purchase_orders.ids)
|
||||
])
|
||||
|
||||
rec.attach_no = count_self + count_po
|
||||
|
||||
def get_attachments(self):
|
||||
self.ensure_one()
|
||||
Attachment = self.env['ir.attachment']
|
||||
|
||||
purchase_orders = self.env['purchase.order'].search([('annual_request_id', '=', self.id)])
|
||||
|
||||
domain = ['|',
|
||||
'&', ('res_model', '=', self._name), ('res_id', 'in', self.ids),
|
||||
'&', ('res_model', '=', 'purchase.order'), ('res_id', 'in', purchase_orders.ids)
|
||||
]
|
||||
|
||||
return {
|
||||
'name': "Documents",
|
||||
'name': _("Documents"),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'ir.attachment',
|
||||
'view_mode': 'kanban,tree,form',
|
||||
'domain': [
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', self.ids)
|
||||
],
|
||||
'domain': domain,
|
||||
'context': {
|
||||
'default_res_model': self._name,
|
||||
'default_res_id': self.id,
|
||||
|
||||
},
|
||||
'target': 'current',
|
||||
}
|
||||
|
||||
def copy(self, default=None):
|
||||
default = dict(default or {})
|
||||
|
||||
|
|
@ -219,6 +257,7 @@ class AnnualPurchaseRequest(models.Model):
|
|||
self._check_lines()
|
||||
order_line_vals = []
|
||||
for line in self.line_ids:
|
||||
line.sudo()
|
||||
order_line_vals.append((0, 0, {
|
||||
'product_id': line.product_id.id,
|
||||
'name': line.description or line.product_id.description_purchase or line.product_id.name,
|
||||
|
|
@ -294,13 +333,21 @@ class AnnualPurchaseRequest(models.Model):
|
|||
if manager.user_id.id == rec.env.uid :
|
||||
rec.write({'state': 'procurement'})
|
||||
else:
|
||||
raise Warning(_("Sorry, The Approval For The Direct Manager '%s' Only !")%(rec.employee_id.parent_id.name))
|
||||
raise UserError(_("Sorry, The Approval For The Direct Manager '%s' Only !")%(rec.employee_id.parent_id.name))
|
||||
else:
|
||||
rec.write({'state': 'procurement'})
|
||||
|
||||
def action_manager_reject(self, reason=False):
|
||||
self.message_post(body=_("Rejected by Manager: %s") % (reason or ''))
|
||||
self.write({'state': 'rejected'})
|
||||
for rec in self:
|
||||
manager = rec.sudo().employee_id.parent_id
|
||||
if manager:
|
||||
if manager.user_id.id == rec.env.uid :
|
||||
rec.write({'state': 'rejected'})
|
||||
else:
|
||||
raise UserError(_("Sorry, The Approval For The Direct Manager '%s' Only !")%(rec.employee_id.parent_id.name))
|
||||
else:
|
||||
rec.write({'state': 'rejected'})
|
||||
|
||||
|
||||
def action_send_to_committee(self):
|
||||
self.write({'sent_to_commitee': True})
|
||||
|
|
@ -381,10 +428,10 @@ class AnnualPurchaseRequestLine(models.Model):
|
|||
_description = "Annual Purchase Request Line"
|
||||
|
||||
request_id = fields.Many2one('odx.annual.request', string="Request", required=True, ondelete='cascade')
|
||||
product_id = fields.Many2one('product.product', string="Product", required=True, domain=[('purchase_ok','=',True)])
|
||||
product_id = fields.Many2one('product.product', string="Product", required=True)
|
||||
description = fields.Char(string="Technical Description")
|
||||
quantity = fields.Float(string="Quantity", default=1.0)
|
||||
uom_id = fields.Many2one('uom.uom', string="UoM", related='product_id.uom_po_id', readonly=False)
|
||||
price_unit = fields.Monetary(string="Unit Price", currency_field='currency_id', groups="purchase_requisition_custom.committe_member")
|
||||
uom_id = fields.Many2one('uom.uom', string="UoM", related='product_id.uom_po_id')
|
||||
price_unit = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
||||
currency_id = fields.Many2one('res.currency', related='request_id.currency_id', readonly=True, store=True)
|
||||
technical_spec = fields.Text(string="Technical Specification")
|
||||
|
|
@ -9,13 +9,16 @@ class PurchaseOrder(models.Model):
|
|||
department_id = fields.Many2one('hr.department', string="Department")
|
||||
purpose = fields.Char(string="Purpose")
|
||||
is_recommended = fields.Boolean(string="Recommended by Committee")
|
||||
|
||||
# حقول محسوبة من الاحتياج السنوي
|
||||
annual_purchase_commitee = fields.Boolean(
|
||||
string='Annual Committee?',
|
||||
compute='_compute_annual_committee_fields',
|
||||
store=True
|
||||
technical_attachment_id = fields.Many2one(
|
||||
'ir.attachment',
|
||||
string="Technical Offer Attachment",
|
||||
)
|
||||
# حقول محسوبة من الاحتياج السنوي
|
||||
# annual_purchase_commitee = fields.Boolean(
|
||||
# string='Annual Committee?',
|
||||
# compute='_compute_annual_committee_fields',
|
||||
# store=True
|
||||
# )
|
||||
annual_can_committee_vote = fields.Boolean(
|
||||
compute='_compute_annual_can_committee_vote'
|
||||
)
|
||||
|
|
@ -24,7 +27,20 @@ class PurchaseOrder(models.Model):
|
|||
string='Is Technical Committee',
|
||||
store=False
|
||||
)
|
||||
show_send_purchase_manager = fields.Boolean(compute='_compute_show_send_purchase_manager')
|
||||
|
||||
cancel_reason = fields.Text(string="Cancel Reason")
|
||||
@api.depends('state', 'requisition_state', 'requisition_type_exclusive','requisition_id', 'is_purchase_budget')
|
||||
def _compute_show_send_purchase_manager(self):
|
||||
for record in self:
|
||||
if (
|
||||
(record.state == 'sent' and not record.is_purchase_budget and not record.requisition_id)
|
||||
or
|
||||
(record.state == 'wait' and not record.is_purchase_budget and not record.requisition_id)
|
||||
):
|
||||
record.show_send_purchase_manager = False # يظهر الزر
|
||||
else:
|
||||
record.show_send_purchase_manager = True # يخفي الزر
|
||||
|
||||
@api.depends(
|
||||
'requisition_id', 'requisition_id.state', 'requisition_id.purchase_commitee',
|
||||
|
|
@ -168,7 +184,30 @@ class PurchaseOrder(models.Model):
|
|||
'context': {'default_order_id': self.id}
|
||||
}
|
||||
|
||||
def _fill_annual_prices_from_po(self):
|
||||
|
||||
for po in self:
|
||||
annual = po.annual_request_id
|
||||
if not annual:
|
||||
continue
|
||||
|
||||
for rline in annual.line_ids:
|
||||
pol = po.order_line.filtered(lambda l: l.product_id == rline.product_id)[:1]
|
||||
if not pol:
|
||||
continue
|
||||
|
||||
price = pol.price_unit
|
||||
|
||||
if po.currency_id != annual.currency_id:
|
||||
convert_date = po.date_order.date() if po.date_order else fields.Date.context_today(self)
|
||||
price = po.currency_id._convert(
|
||||
price, annual.currency_id, po.company_id, convert_date
|
||||
)
|
||||
|
||||
if pol.product_uom and rline.uom_id and pol.product_uom != rline.uom_id:
|
||||
price = pol.product_uom._compute_price(price, rline.uom_id)
|
||||
|
||||
rline.price_unit = price
|
||||
|
||||
def action_sign(self):
|
||||
if self.annual_request_id and self.annual_request_id.committee_enabled:
|
||||
|
|
@ -187,6 +226,7 @@ class PurchaseOrder(models.Model):
|
|||
for order in other_orders:
|
||||
order.action_unsign()
|
||||
self.annual_request_id.vendor_id = self.partner_id.id
|
||||
self._fill_annual_prices_from_po()
|
||||
if self.annual_request_id.ssd_approve:
|
||||
self.annual_request_id.state = 'ssd'
|
||||
elif self.annual_request_id.seo_approve:
|
||||
|
|
|
|||
|
|
@ -27,16 +27,25 @@
|
|||
<button name="action_cancel" string="Cancel" type="object" states="draft,ssd,gm"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,ssd,gm,approved,rejected,cancel"/>
|
||||
</header>
|
||||
|
||||
<sheet>
|
||||
<div class="oe_title" name="title">
|
||||
<h2>
|
||||
<field name="name" readonly="1" style=" font-size:24px; "/>
|
||||
</h2>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="agreement_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="purpose"/>
|
||||
<field name="recommendation" />
|
||||
<field name="vendor_id" readonly="1"/>
|
||||
<!-- <field name="recommendation"/>-->
|
||||
<!-- <field name="agreement_id"/>-->
|
||||
<!-- <field name="department_id"/>-->
|
||||
<!-- <field name="purpose"/>-->
|
||||
</group>
|
||||
<group>
|
||||
<field name="vendor_id" readonly="1"/>
|
||||
<field name="ssd_approve" />
|
||||
<field name="seo_approve" />
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
|
|
@ -51,13 +60,6 @@
|
|||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Notes">
|
||||
<field name="note"/>
|
||||
</page>
|
||||
<page string="Chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@
|
|||
icon="fa-file-text-o">
|
||||
<field name="attach_no" widget="statinfo" string="Documents"/>
|
||||
</button>
|
||||
<!-- <button class="oe_stat_button"-->
|
||||
<!-- type="object"-->
|
||||
<!-- name="action_open_addendums"-->
|
||||
<!-- icon="fa-files-o">-->
|
||||
<!-- <field name="addendum_count" widget="statinfo" string="Addendums"/>-->
|
||||
<!-- </button>-->
|
||||
|
||||
</div>
|
||||
<div class="oe_title" name="title">
|
||||
|
|
@ -104,6 +110,8 @@
|
|||
<tree editable="bottom">
|
||||
<field name="product_id"/>
|
||||
<field name="description"/>
|
||||
<field name="price_unit" readonly="1"
|
||||
attrs="{'column_invisible': [('parent.state','not in',['ssd','ceo','procurement','purchase'])]}"/>
|
||||
<field name="uom_id"/>
|
||||
<field name="quantity"/>
|
||||
</tree>
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@
|
|||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Technical Offer Attachment">
|
||||
<field name="technical_attachment_id"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
|
|
@ -324,11 +327,6 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</xpath>
|
||||
|
|
@ -337,4 +335,40 @@
|
|||
|
||||
|
||||
|
||||
<!-- Inherit the Purchase Order form -->
|
||||
<record id="purchase_order_custom_form_view_Inherit" model="ir.ui.view">
|
||||
<field name="name">purchase.order.form.custom</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="inherit_id" ref="purchase_requisition_custom.purchase_order_custom_form_view"/>
|
||||
<field name="priority" eval="100"/>
|
||||
<field name="arch" type="xml">
|
||||
|
||||
<xpath expr="/form/header" position="inside">
|
||||
<field name="requisition_id" invisible="1"/>
|
||||
<field name="annual_request_id" invisible="1"/>
|
||||
<field name="is_signed" invisible="1"/>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="/form/header/button[@name='action_sign']" position="replace">
|
||||
<button type="object"
|
||||
name="action_sign"
|
||||
class="oe_highlight"
|
||||
string="Sign"
|
||||
groups="purchase_requisition_custom.group_sign_purchase_order"
|
||||
attrs="{
|
||||
'invisible': [
|
||||
'|','|',
|
||||
'&', ('requisition_id','=',False), ('annual_request_id','=',False),
|
||||
('state','in',['sign','purchase','to approve','done','cancel','budget_rejected','wait_for_send','waiting']),
|
||||
('is_signed','=',True)
|
||||
]
|
||||
}"/>
|
||||
</xpath>
|
||||
|
||||
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue