# Part of Flectra See LICENSE file for full copyright and licensing details. from datetime import datetime from flectra.exceptions import Warning, AccessError from flectra.tools.misc import formatLang import flectra.addons.decimal_precision as dp from flectra import api, fields, models, _ class PurchaseOrder(models.Model): _inherit = 'purchase.order' purchase_indent_ids = fields.Many2many( 'purchase.indent', string='Purchase Indent') @api.onchange('requisition_id') def _onchange_requisition_id(self): if not self.requisition_id: return requisition = self.requisition_id if self.partner_id: partner = self.partner_id else: partner = requisition.vendor_id payment_term = partner.property_supplier_payment_term_id company = requisition.company_id currency = \ partner.property_purchase_currency_id or \ company.currency_id FiscalPosition = self.env['account.fiscal.position'] fpos = FiscalPosition.get_fiscal_position(partner.id) fpos = FiscalPosition.browse(fpos) self.partner_id = partner.id self.fiscal_position_id = fpos.id self.payment_term_id = payment_term.id, self.company_id = company.id self.currency_id = currency.id self.origin = requisition.name self.partner_ref = requisition.name self.notes = requisition.description self.date_order = requisition.date_end or fields.Datetime.now() self.picking_type_id = requisition.picking_type_id.id if requisition.type_id.line_copy != 'copy': return order_lines = [] for line in requisition.line_ids: product_lang = line.product_id.with_context({ 'lang': partner.lang, 'partner_id': partner.id, }) name = product_lang.display_name if product_lang.description_purchase: name += '\n' + product_lang.description_purchase if fpos: taxes_ids = fpos.map_tax( line.product_id.supplier_taxes_id.filtered( lambda tax: tax.company_id == company)) else: taxes_ids = line.product_id.supplier_taxes_id.filtered( lambda tax: tax.company_id == company).ids if line.product_uom_id != line.product_id.uom_po_id: product_qty = line.product_uom_id._compute_quantity( line.product_qty, line.product_id.uom_po_id) price_unit = line.product_uom_id._compute_price( line.price_unit, line.product_id.uom_po_id) else: product_qty = line.product_qty price_unit = line.price_unit if requisition.type_id.quantity_copy != 'copy': product_qty = 0 if company.currency_id != currency: price_unit = requisition.company_id.currency_id.compute( price_unit, currency) order_lines.append((0, 0, { 'name': name, 'product_id': line.product_id.id, 'product_uom': line.product_id.uom_po_id.id, 'product_qty': product_qty, 'price_unit': price_unit, 'taxes_id': [(6, 0, taxes_ids)], 'date_planned': requisition.schedule_date or fields.Date.today(), 'account_analytic_id': line.account_analytic_id.id, 'purchase_indent_ids': [(6, 0, line.purchase_indent_ids.ids)], 'purchase_indent_line_id': line.purchase_indent_line_id.id, })) self.order_line = order_lines @api.multi def button_draft(self): self.env['purchase.indent'].set_qty_state_confirm(self, False) return super(PurchaseOrder, self).button_draft() @api.multi def button_cancel(self): res = super(PurchaseOrder, self).button_cancel() for purchase_order_id in self: self.env['purchase.indent'].set_qty_state_cancel( purchase_order_id, False) return res @api.model def create(self, vals): if vals.get('requisition_id', False): requisition_id = self.requisition_id.browse( vals.get('requisition_id', False)) if requisition_id.purchase_indent_ids: vals['purchase_indent_ids'] = \ [(6, 0, requisition_id.purchase_indent_ids.ids)] return super(PurchaseOrder, self).create(vals) @api.multi def write(self, vals): res = super(PurchaseOrder, self).write(vals) if vals.get('requisition_id', False): self.write({ 'purchase_indent_ids': [(6, 0, self.requisition_id.purchase_indent_ids.ids)]}) return res @api.multi def unlink(self): for record in self: if record.purchase_indent_ids: raise Warning(_("You can not delete Purchase order which \ have reference of Purchase Indent!")) return super(PurchaseOrder, self).unlink() @api.multi def copy(self): self.ensure_one() if self.purchase_indent_ids: raise Warning(_("You can not copy Purchase order which have \ reference of Purchase Indent!")) return super(PurchaseOrder, self).copy() class PurchaseOrderLine(models.Model): _inherit = 'purchase.order.line' purchase_indent_line_id = fields.Many2one( 'purchase.indent.line', 'Purchase Indent Line Ref') purchase_indent_ids = fields.Many2many( 'purchase.indent', string='Purchase Indent') @api.multi def unlink(self): if self.purchase_indent_line_id: raise Warning(_("You can not delete line which have \ reference of Purchase Indent")) return super(PurchaseOrderLine, self).unlink() class PurchaseRequisition(models.Model): _name = 'purchase.requisition' _inherit = ['purchase.requisition'] purchase_indent_ids = fields.Many2many( 'purchase.indent', string='Purchase Indent') @api.multi def action_draft(self): self.env['purchase.indent'].set_qty_state_confirm(False, self) return super(PurchaseRequisition, self).action_draft() @api.multi def action_cancel(self): self.env['purchase.indent'].set_qty_state_cancel(False, self) return super(PurchaseRequisition, self).action_cancel() @api.multi def unlink(self): for record in self: if record.purchase_indent_ids: raise Warning(_("You can not delete agreement which have \ reference of Purchase Indent!")) return super(PurchaseRequisition, self).unlink() @api.multi def copy(self, default=None): self.ensure_one() default = dict(default or {}) if self.purchase_indent_ids: raise Warning(_("You can not copy Purchase Agreement which \ have reference of Purchase Indent!")) default.update( name=_("%s (copy)") % (self.name or '')) return super(PurchaseRequisition, self).copy(default) class PurchaseRequisitionLine(models.Model): _inherit = 'purchase.requisition.line' purchase_indent_line_id = fields.Many2one( 'purchase.indent.line', 'Purchase Indent Line Ref') purchase_indent_ids = fields.Many2many( 'purchase.indent', string='Purchase Indent') class PurchaseIndent(models.Model): _name = 'purchase.indent' _inherit = ['mail.thread', 'mail.activity.mixin'] _description = "Purchase Indent" @api.multi def _compute_order_count(self): po_list = [] pa_list = [] for history_id in self.intend_history_ids: if history_id.order_id: po_list.append(history_id.order_id.id) elif history_id.purchase_requisition_id: pa_list.append(history_id.purchase_requisition_id.id) self.purchase_order_count = len(list(set(po_list))) self.agreement_count = len(list(set(pa_list))) @api.model def _default_picking_type(self): type_obj = self.env['stock.picking.type'] company_id = \ self.env.context.get('company_id') or self.env.user.company_id.id types = type_obj.search([('code', '=', 'incoming'), ('warehouse_id.company_id', '=', company_id)]) if not types: types = type_obj.search([('code', '=', 'incoming'), ('warehouse_id', '=', False)]) return types[:1] name = fields.Char( 'Reference', index=True, copy=False, readonly=True, track_visibility='onchange') request_date = fields.Date( 'Request Date', default=fields.Date.today(), track_visibility='onchange') category_id = fields.Many2one( 'product.category', 'Category', track_visibility='onchange') state = fields.Selection([ ('draft', 'Draft'), ('confirm', 'Confirm'), ('requisition', 'Requisition'), ('done', 'Done'), ('cancel', 'Cancel')], 'State', default='draft', track_visibility='onchange') indent_line = fields.One2many( 'purchase.indent.line', 'purchase_indent_id', 'Indent Lines') company_id = fields.Many2one( 'res.company', string='Company', track_visibility='onchange') user_id = fields.Many2one( 'res.users', string='Requested By', default=lambda self: self.env.uid, readonly=True, track_visibility='onchange') partner_id = fields.Many2one( 'res.partner', related='user_id.partner_id', string="Partner", track_visibility='onchange') intend_history_ids = fields.One2many( 'purchase.indent.history', 'purchase_indent_id', 'History') purchase_order_count = fields.Integer( compute='_compute_order_count', string='# of Purchase Order') agreement_count = fields.Integer( compute='_compute_order_count', string='# of Purchase Agreement') dest_address_id = fields.Many2one( 'res.partner', string='Drop Ship Address', help="Put an address if you want to deliver directly from the vendor \ to the customer.Otherwise, keep empty to deliver to your own company.") picking_type_id = fields.Many2one( 'stock.picking.type', 'Deliver To', required=True, default=_default_picking_type, help="This will determine operation type of incoming shipment") default_location_dest_id_usage = fields.Selection( related='picking_type_id.default_location_dest_id.usage', string='Destination Location Type', help="Technical field used to display the Drop Ship Address", readonly=True) @api.multi def set_qty_state_cancel(self, purchase_order_id=False, purchase_agreement_id=False): intend_history_ids = [] indent_line_obj = self.env['purchase.indent.line'] if purchase_order_id: intend_history_ids = self.env['purchase.indent.history'].search([ ('order_id', '=', purchase_order_id.id), ('purchase_requisition_id', '=', False)]) elif purchase_agreement_id: intend_history_ids = self.env['purchase.indent.history'].search([ ('order_id', '=', False), ('purchase_requisition_id', '=', purchase_agreement_id.id)]) for history_id in intend_history_ids: indent_line_id = indent_line_obj.sudo().search([ ('product_id', '=', history_id.product_id.id), ('purchase_indent_id', '=', history_id.purchase_indent_id.id)]) requisition_qty = \ indent_line_id.requisition_qty - history_id.requisition_qty indent_line_id.write({'requisition_qty': requisition_qty}) history_id.purchase_indent_id.check_state() history_id.date = datetime.now() @api.multi def set_qty_state_confirm(self, purchase_order_id=False, purchase_agreement_id=False): indent_line_obj = self.env['purchase.indent.line'] intend_history_ids = [] if purchase_order_id: intend_history_ids = self.env['purchase.indent.history'].search([ ('order_id', '=', purchase_order_id.id), ('state', '=', 'Cancelled')]) elif purchase_agreement_id: intend_history_ids = self.env['purchase.indent.history'].search([ ('purchase_requisition_id', '=', purchase_agreement_id.id), ('state', '=', 'Cancelled')]) for history_id in intend_history_ids: indent_line_id = indent_line_obj.sudo().search([ ('product_id', '=', history_id.product_id.id), ('purchase_indent_id', '=', history_id.purchase_indent_id.id)]) if indent_line_id.requisition_qty + history_id.requisition_qty > \ indent_line_id.product_qty: remaining_qty = \ indent_line_id.product_qty - indent_line_id.requisition_qty raise Warning(_("Requisition Quantity of ' %s ' is more than \ Remaining Quantity (%s)!") % ( history_id.product_id.name, formatLang( self.env, remaining_qty, digits=2))) requisition_qty = \ indent_line_id.requisition_qty + history_id.requisition_qty indent_line_id.write({'requisition_qty': requisition_qty}) history_id.purchase_indent_id.check_state() history_id.date = datetime.now() @api.onchange('company_id') def onchange_company_id(self): res = {} user_company_id = self.user_id.company_ids res['domain'] = {'company_id': [ ('id', 'in', user_company_id.ids)]} if len(user_company_id) == 1: res['domain'] = { 'company_id': [('id', '=', user_company_id.id)]} self.company_id = user_company_id.id return res @api.multi def check_duplicate_product(self): product_dup_list = [] for line in self.indent_line: if line.product_id.id not in product_dup_list: product_dup_list.append(line.product_id.id) else: dup_line_id = self.env['purchase.indent.line'].search([ ('purchase_indent_id', '=', line.purchase_indent_id.id), ('product_id', '=', line.product_id.id)], limit=1) dup_line_id.product_qty += line.product_qty line.unlink() @api.multi def action_confirm(self): if self._uid != self.create_uid.id: raise Warning(_("You can't confirm purchase indent which is \ requested by %s!") % (self.create_uid.name)) if not self.indent_line: raise Warning(_('No Product Line(s) were found!')) check_pro_qty = [ line.id for line in self.indent_line if line.product_qty] if not check_pro_qty: raise Warning(_("No Quantity were found for any line!")) self.check_duplicate_product() group_id = self.sudo().env.ref('purchase.group_purchase_manager') if not group_id.users: raise AccessError( _("Please contact your Administrator \n \ No user found under 'Purchase Manager'")) server_id = self.env['ir.mail_server'].search([]) if not server_id: raise AccessError( _("Please configure outgoing mail server")) email_to = ",".join([user.email for user in group_id.users if user.email]) recipient_ids = [user.partner_id.id for user in group_id.users] if self.env.user.email: product_qty = '''
''' + _("Product Name") + ''' | ''' + _("Quantity") + ''' | ''' + _("Expected Date") + ''' |
' + str(line.product_id.name) + ' | \' + qty + ' | \' + str(line.expected_date) + ' | \