def automatic_payment(self, amount=None): """ Create the payment entries to pay a sale order, respecting the payment terms. If no amount is defined, it will pay the residual amount of the sale order. """ self.ensure_one() method = self.payment_method_id if not method: raise exceptions.Warning( _("An automatic payment can not be created for the sale " "order %s because it has no payment method.") % self.name) if not method.journal_id: raise exceptions.Warning( _("An automatic payment should be created for the sale order" " %s but the payment method '%s' has no journal defined.") % (self.name, method.name)) journal = method.journal_id date = self.date_order[:10] if amount is None: amount = self.residual if self.payment_term: amounts = self.payment_term.compute(amount, date_ref=date)[0] else: amounts = [(date, amount)] # reversed is cosmetic, compute returns terms in the 'wrong' order for date, amount in reversed(amounts): self._add_payment(journal, amount, date) return True
def generate_dbname(self, raise_error=True): if not self.dbname_template: if raise_error: raise exceptions.Warning(_('Template for db name is not configured')) return '' sequence = self.env['ir.sequence'].get('saas_portal.plan') return self.dbname_template.replace('%i', sequence).replace('%t', datetime.now().strftime('%m%d%I%M%S'))
def action_cancel(self): for sale in self: if sale.payment_ids: raise exceptions.Warning( _('Cannot cancel this sales order ' 'because automatic payment entries ' 'are linked with it.')) return super(SaleOrder, self).action_cancel()
def _get_s3_conn(env): ir_params = env['ir.config_parameter'] aws_access_key_id = ir_params.get_param('saas_s3.saas_s3_aws_accessid') aws_secret_access_key = ir_params.get_param('saas_s3.saas_s3_aws_accesskey') aws_s3_bucket = ir_params.get_param('saas_s3.saas_s3_aws_bucket') if not aws_access_key_id or not aws_secret_access_key or not aws_s3_bucket: raise exceptions.Warning( _(u'Please provide your AWS Access Key and ID \ and also the S3 bucket to be used')) return boto.connect_s3(aws_access_key_id, aws_secret_access_key), aws_s3_bucket
def _get_payment_move_name(self, journal, period): sequence = journal.sequence_id if not sequence: raise exceptions.Warning( _('Please define a sequence on the ' 'journal %s.') % journal.name) if not sequence.active: raise exceptions.Warning( _('Please activate the sequence of the ' 'journal %s.') % journal.name) sequence = sequence.with_context(fiscalyear_id=period.fiscalyear_id.id) # next_by_id not compatible with new api sequence_model = self.pool['ir.sequence'] name = sequence_model.next_by_id(self.env.cr, self.env.uid, sequence.id, context=self.env.context) return name
def get_plan(self, plan_id=None): plan = request.registry['saas_portal.plan'] if not plan_id: domain = [('state', '=', 'confirmed')] plan_ids = request.registry['saas_portal.plan'].search( request.cr, SUPERUSER_ID, domain) if plan_ids: plan_id = plan_ids[0] else: raise exceptions.Warning(_('There is no plan configured')) return plan.browse(request.cr, SUPERUSER_ID, plan_id)
def create(self, vals): max_users = self.env["ir.config_parameter"].sudo().get_param( "saas_client.max_users") if max_users: max_users = int(max_users) cur_users = self.env['res.users'].search_count([('share', '=', False)]) if cur_users >= max_users: raise exceptions.Warning( _('Maximimum allowed users is %(max_users)s, while you already have %(cur_users)s' ) % { 'max_users': max_users, 'cur_users': cur_users }) return super(ResUsers, self).create(vals)
def get_diff(self): """Return the Difference between two document.""" history = self.env["document.page.history"] ids = self.env.context.get('active_ids', []) diff = "" if len(ids) == 2: if ids[0] > ids[1]: diff = history.getDiff(ids[1], ids[0]) else: diff = history.getDiff(ids[0], ids[1]) elif len(ids) == 1: old = history.browse(ids[0]) nids = history.search([('page_id', '=', old.page_id.id)], order='id DESC', limit=1) diff = history.getDiff(ids[0], nids.id) else: raise exceptions.Warning( _("Select one or maximum two history revisions!")) return diff
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer(help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer(help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' dbname_template = fields.Char('DB Names', help='Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.yuancloud.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.one def _new_database_vals(self, vals): vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None): self.ensure_one() server = self.server_id if not server: server = self.env['saas_portal.server'].get_saas_server() server.action_sync_server() if not partner_id and user_id: user = self.env['res.users'].browse(user_id) partner_id = user.partner_id.id if not trial and self.maximum_allowed_dbs_per_partner != 0: db_count = self.env['saas_portal.client'].search_count([('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', False)]) if db_count >= self.maximum_allowed_dbs_per_partner: raise MaximumDBException("Limit of databases for this plan is %(maximum)s reached" % { 'maximum': self.maximum_allowed_dbs_per_partner}) if trial and self.maximum_allowed_trial_dbs_per_partner != 0: trial_db_count = self.env['saas_portal.client'].search_count([('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', True)]) if trial_db_count >= self.maximum_allowed_trial_dbs_per_partner: raise MaximumTrialDBException("Limit of trial databases for this plan is %(maximum)s reached" % { 'maximum': self.maximum_allowed_trial_dbs_per_partner}) vals = {'name': dbname or self.generate_dbname()[0], 'server_id': server.id, 'plan_id': self.id, 'partner_id': partner_id, 'trial': trial, 'support_team_id': support_team_id, } client = None if client_id: vals['client_id'] = client_id client = self.env['saas_portal.client'].search([('client_id', '=', client_id)]) vals = self._new_database_vals(vals)[0] if client: client.write(vals) else: client = self.env['saas_portal.client'].create(vals) client_id = client.client_id scheme = server.request_scheme port = server.request_port if user_id: owner_user = self.env['res.users'].browse(user_id) else: owner_user = self.env.user owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'name': owner_user.name, 'email': owner_user.email, } trial_expiration_datetime = (datetime.strptime(client.create_date, DEFAULT_SERVER_DATETIME_FORMAT) + timedelta( hours=self.expiration)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) # for trial state = { 'd': client.name, 'e': trial and trial_expiration_datetime or client.create_date, 'r': '%s://%s:%s/web' % (scheme, client.name, port), 'owner_user': owner_user_data, 't': client.trial, 'addons': [addon.technical_name for addon in client.plan_id.app_store_module_ids] } if self.template_id: state.update({'db_template': self.template_id.name}) scope = ['userinfo', 'force_login', 'trial', 'skiptheuse'] url = server._request_server(path='/saas_server/new_database', scheme=scheme, port=port, state=state, client_id=client_id, scope=scope, )[0] res = requests.get(url, verify=(self.server_id.request_scheme == 'https' and self.server_id.verify_ssl)) if res.status_code != 200: # TODO /saas_server/new_database show more details here raise exceptions.Warning('Error %s' % res.status_code) data = simplejson.loads(res.text) params = { 'state': data.get('state'), 'access_token': client.oauth_application_id._get_access_token(user_id, create=True), } url = '{url}?{params}'.format(url=data.get('url'), params=werkzeug.url_encode(params)) # send email if notify_user: template = self.env.ref('saas_portal.email_template_create_saas') client.message_post_with_template(template.id, composition_mode='comment') if trial: client.expiration_datetime = trial_expiration_datetime client.send_params_to_client_db() client.server_id.action_sync_server() return {'url': url, 'id': client.id, 'client_id': client_id}
def _transport_backup(self, dump_db, filename=None): ''' backup transport agents should override this ''' raise exceptions.Warning('Transport agent has not been configured')
def create_xml(self, cr, uid, ids, context=None): """Creates xml that is to be exported and sent to estate for partner vat intra. :return: Value for next action. :rtype: dict """ decl_datas = self.browse(cr, uid, ids[0]) company = decl_datas.company_id if not (company.partner_id and company.partner_id.country_id and company.partner_id.country_id.id): self._company_warning(cr, uid, _('The country of your company is not set, ' 'please make sure to configure it first.'), context=context) kbo = company.company_registry if not kbo: self._company_warning( cr, uid, _('The registry number of your company is not set, ' 'please make sure to configure it first.'), context=context) if len(decl_datas.year) != 4: raise exceptions.Warning(_('Year must be 4 digits number (YYYY)')) #Create root declaration decl = ET.Element('DeclarationReport') decl.set('xmlns', INTRASTAT_XMLNS) #Add Administration elements admin = ET.SubElement(decl, 'Administration') fromtag = ET.SubElement(admin, 'From') fromtag.text = kbo fromtag.set('declarerType', 'KBO') ET.SubElement(admin, 'To').text = "NBB" ET.SubElement(admin, 'Domain').text = "SXX" if decl_datas.arrivals == 'be-standard': decl.append( self._get_lines(cr, SUPERUSER_ID, ids, decl_datas, company, dispatchmode=False, extendedmode=False, context=context)) elif decl_datas.arrivals == 'be-extended': decl.append( self._get_lines(cr, SUPERUSER_ID, ids, decl_datas, company, dispatchmode=False, extendedmode=True, context=context)) if decl_datas.dispatches == 'be-standard': decl.append( self._get_lines(cr, SUPERUSER_ID, ids, decl_datas, company, dispatchmode=True, extendedmode=False, context=context)) elif decl_datas.dispatches == 'be-extended': decl.append( self._get_lines(cr, SUPERUSER_ID, ids, decl_datas, company, dispatchmode=True, extendedmode=True, context=context)) #Get xml string with declaration data_file = ET.tostring(decl, encoding='UTF-8', method='xml') #change state of the wizard self.write( cr, uid, ids, { 'name': 'intrastat_%s%s.xml' % (decl_datas.year, decl_datas.month), 'file_save': base64.encodestring(data_file), 'state': 'download' }, context=context) return { 'name': _('Save'), 'context': context, 'view_type': 'form', 'view_mode': 'form', 'res_model': 'l10n_be_intrastat_xml.xml_decl', 'type': 'ir.actions.act_window', 'target': 'new', 'res_id': ids[0], }
def _get_lines(self, cr, uid, ids, decl_datas, company, dispatchmode=False, extendedmode=False, context=None): intrastatcode_mod = self.pool['report.intrastat.code'] invoiceline_mod = self.pool['account.invoice.line'] product_mod = self.pool['product.product'] region_mod = self.pool['l10n_be_intrastat.region'] warehouse_mod = self.pool['stock.warehouse'] if dispatchmode: mode1 = 'out_invoice' mode2 = 'in_refund' declcode = "29" else: mode1 = 'in_invoice' mode2 = 'out_refund' declcode = "19" decl = ET.Element('Report') if not extendedmode: decl.set('code', 'EX%sS' % declcode) else: decl.set('code', 'EX%sE' % declcode) decl.set('date', '%s-%s' % (decl_datas.year, decl_datas.month)) datas = ET.SubElement(decl, 'Data') if not extendedmode: datas.set('form', 'EXF%sS' % declcode) else: datas.set('form', 'EXF%sE' % declcode) datas.set('close', 'true') intrastatkey = namedtuple( "intrastatkey", ['EXTRF', 'EXCNT', 'EXTTA', 'EXREG', 'EXGO', 'EXTPC', 'EXDELTRM']) entries = {} sqlreq = """ select inv_line.id from account_invoice_line inv_line join account_invoice inv on inv_line.invoice_id=inv.id left join res_country on res_country.id = inv.intrastat_country_id left join res_partner on res_partner.id = inv.partner_id left join res_country countrypartner on countrypartner.id = res_partner.country_id join product_product on inv_line.product_id=product_product.id join product_template on product_product.product_tmpl_id=product_template.id where inv.state in ('open','paid') and inv.company_id=%s and not product_template.type='service' and (res_country.intrastat=true or (inv.intrastat_country_id is null and countrypartner.intrastat=true)) and ((res_country.code is not null and not res_country.code=%s) or (res_country.code is null and countrypartner.code is not null and not countrypartner.code=%s)) and inv.type in (%s, %s) and to_char(inv.date_invoice, 'YYYY')=%s and to_char(inv.date_invoice, 'MM')=%s """ cr.execute(sqlreq, (company.id, company.partner_id.country_id.code, company.partner_id.country_id.code, mode1, mode2, decl_datas.year, decl_datas.month)) lines = cr.fetchall() invoicelines_ids = [rec[0] for rec in lines] invoicelines = invoiceline_mod.browse(cr, uid, invoicelines_ids, context=context) for inv_line in invoicelines: #Check type of transaction if inv_line.intrastat_transaction_id: extta = inv_line.intrastat_transaction_id.code else: extta = "1" #Check country if inv_line.invoice_id.intrastat_country_id: excnt = inv_line.invoice_id.intrastat_country_id.code else: excnt = inv_line.invoice_id.partner_id.country_id.code #Check region #If purchase, comes from purchase order, linked to a location, #which is linked to the warehouse #if sales, the sale order is linked to the warehouse #if sales, from a delivery order, linked to a location, #which is linked to the warehouse #If none found, get the company one. exreg = None if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): #comes from purchase POL = self.pool['purchase.order.line'] poline_ids = POL.search(cr, uid, [('invoice_lines', 'in', inv_line.id)], context=context) if poline_ids: purchaseorder = POL.browse(cr, uid, poline_ids[0], context=context).order_id region_id = warehouse_mod.get_regionid_from_locationid( cr, uid, purchaseorder.location_id.id, context=context) if region_id: exreg = region_mod.browse(cr, uid, region_id).code elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): #comes from sales soline_ids = self.pool['sale.order.line'].search( cr, uid, [('invoice_lines', 'in', inv_line.id)], context=context) if soline_ids: saleorder = self.pool['sale.order.line'].browse( cr, uid, soline_ids[0], context=context).order_id if saleorder and saleorder.warehouse_id and saleorder.warehouse_id.region_id: exreg = region_mod.browse( cr, uid, saleorder.warehouse_id.region_id.id, context=context).code if not exreg: if company.region_id: exreg = company.region_id.code else: self._company_warning( cr, uid, _('The Intrastat Region of the selected company is not set, ' 'please make sure to configure it first.'), context=context) #Check commodity codes intrastat_id = product_mod.get_intrastat_recursively( cr, uid, inv_line.product_id.id, context=context) if intrastat_id: exgo = intrastatcode_mod.browse(cr, uid, intrastat_id, context=context).name else: raise exceptions.Warning( _('Product "%s" has no intrastat code, please configure it' ) % inv_line.product_id.display_name) #In extended mode, 2 more fields required if extendedmode: #Check means of transport if inv_line.invoice_id.transport_mode_id: extpc = inv_line.invoice_id.transport_mode_id.code elif company.transport_mode_id: extpc = company.transport_mode_id.code else: self._company_warning( cr, uid, _('The default Intrastat transport mode of your company ' 'is not set, please make sure to configure it first.' ), context=context) #Check incoterm if inv_line.invoice_id.incoterm_id: exdeltrm = inv_line.invoice_id.incoterm_id.code elif company.incoterm_id: exdeltrm = company.incoterm_id.code else: self._company_warning( cr, uid, _('The default Incoterm of your company is not set, ' 'please make sure to configure it first.'), context=context) else: extpc = "" exdeltrm = "" linekey = intrastatkey(EXTRF=declcode, EXCNT=excnt, EXTTA=extta, EXREG=exreg, EXGO=exgo, EXTPC=extpc, EXDELTRM=exdeltrm) #We have the key #calculate amounts if inv_line.price_unit and inv_line.quantity: amount = inv_line.price_unit * inv_line.quantity else: amount = 0 if (not inv_line.uom_id.category_id or not inv_line.product_id.uom_id.category_id or inv_line.uos_id.category_id.id != inv_line.product_id.uom_id.category_id.id): weight = inv_line.product_id.weight * inv_line.quantity else: weight = (inv_line.product_id.weight * inv_line.quantity * inv_line.uos_id.factor) if (not inv_line.uos_id.category_id or not inv_line.product_id.uom_id.category_id or inv_line.uos_id.category_id.id != inv_line.product_id.uom_id.category_id.id): supply_units = inv_line.quantity else: supply_units = inv_line.quantity * inv_line.uom_id.factor amounts = entries.setdefault(linekey, (0, 0, 0)) amounts = (amounts[0] + amount, amounts[1] + weight, amounts[2] + supply_units) entries[linekey] = amounts numlgn = 0 for linekey in entries: numlgn += 1 amounts = entries[linekey] item = ET.SubElement(datas, 'Item') self._set_Dim(item, 'EXSEQCODE', unicode(numlgn)) self._set_Dim(item, 'EXTRF', unicode(linekey.EXTRF)) self._set_Dim(item, 'EXCNT', unicode(linekey.EXCNT)) self._set_Dim(item, 'EXTTA', unicode(linekey.EXTTA)) self._set_Dim(item, 'EXREG', unicode(linekey.EXREG)) self._set_Dim(item, 'EXTGO', unicode(linekey.EXGO)) if extendedmode: self._set_Dim(item, 'EXTPC', unicode(linekey.EXTPC)) self._set_Dim(item, 'EXDELTRM', unicode(linekey.EXDELTRM)) self._set_Dim(item, 'EXTXVAL', unicode(round(amounts[0], 0)).replace(".", ",")) self._set_Dim(item, 'EXWEIGHT', unicode(round(amounts[1], 0)).replace(".", ",")) self._set_Dim(item, 'EXUNITS', unicode(round(amounts[2], 0)).replace(".", ",")) if numlgn == 0: #no datas datas.set('action', 'nihil') return decl
def check_dates(self): if self.date_from >= self.date_to: raise exceptions.Warning( _('Error! Date to must be lower ' 'than date from.'))