def unlink(self): for payment in self: if payment.state != 'draft': raise UserError("No se puede eliminar memorandums diferente a estado borrador.") return super(Memo, self).unlink()
def _get_default_from(self): if self.env.user.email: return formataddr((self.env.user.name, self.env.user.email)) raise UserError(_("Unable to send email, please configure the sender's email address."))
def _fill_missing_values(self, vals): journal_type = vals.get('type') # 'type' field is required. if not journal_type: return # === Fill missing company === company = self.env['res.company'].browse( vals['company_id']) if vals.get('company_id') else self.env.company vals['company_id'] = company.id # Don't get the digits on 'chart_template_id' since the chart template could be a custom one. random_account = self.env['account.account'].search( [('company_id', '=', company.id)], limit=1) digits = len(random_account.code) if random_account else 6 liquidity_type = self.env.ref('account.data_account_type_liquidity') current_assets_type = self.env.ref( 'account.data_account_type_current_assets') if journal_type in ('bank', 'cash'): has_liquidity_accounts = vals.get( 'default_debit_account_id') or vals.get( 'default_credit_account_id') has_payment_accounts = vals.get( 'payment_debit_account_id') or vals.get( 'payment_credit_account_id') has_profit_account = vals.get('profit_account_id') has_loss_account = vals.get('loss_account_id') if journal_type == 'bank': liquidity_account_prefix = company.bank_account_code_prefix or '' else: liquidity_account_prefix = company.cash_account_code_prefix or company.bank_account_code_prefix or '' # === Fill missing name === vals['name'] = vals.get('name') or vals.get('bank_acc_number') # === Fill missing code === if 'code' not in vals: vals['code'] = self.get_next_bank_cash_default_code( journal_type, company) if not vals['code']: raise UserError( _("Cannot generate an unused journal code. Please fill the 'Shortcode' field." )) # === Fill missing accounts === if not has_liquidity_accounts: liquidity_account = self.env['account.account'].create({ 'name': vals.get('name'), 'code': self.env['account.account']._search_new_account_code( company, digits, liquidity_account_prefix), 'user_type_id': liquidity_type.id, 'currency_id': vals.get('currency_id'), 'company_id': company.id, }) vals.update({ 'default_debit_account_id': liquidity_account.id, 'default_credit_account_id': liquidity_account.id, }) if not has_payment_accounts: vals['payment_debit_account_id'] = self.env[ 'account.account'].create({ 'name': _("Outstanding Receipts"), 'code': self.env['account.account']._search_new_account_code( company, digits, liquidity_account_prefix), 'reconcile': True, 'user_type_id': current_assets_type.id, 'company_id': company.id, }).id vals['payment_credit_account_id'] = self.env[ 'account.account'].create({ 'name': _("Outstanding Payments"), 'code': self.env['account.account']._search_new_account_code( company, digits, liquidity_account_prefix), 'reconcile': True, 'user_type_id': current_assets_type.id, 'company_id': company.id, }).id if journal_type == 'cash' and not has_profit_account: vals[ 'profit_account_id'] = company.default_cash_difference_income_account_id.id if journal_type == 'cash' and not has_loss_account: vals[ 'loss_account_id'] = company.default_cash_difference_expense_account_id.id # === Fill missing refund_sequence === if 'refund_sequence' not in vals: vals['refund_sequence'] = vals['type'] in ('sale', 'purchase')
def action_set_completed(self): if not all(slide.channel_id.is_member for slide in self): raise UserError(_('You cannot mark a slide as completed if you are not among its members.')) return self._action_set_completed(self.env.user.partner_id)
def data_save(self): obj_acc_period = self.env['account.period'] obj_acc_fiscalyear = self.env['account.fiscalyear'] obj_acc_journal = self.env['account.journal'] obj_acc_move = self.env['account.move'] obj_acc_move_line = self.env['account.move.line'] obj_acc_account = self.env['account.account'] obj_acc_journal_period = self.env['account.journal.period'] currency_obj = self.env['res.currency'] cr = self.env.cr data = self if self._context is None: self._context = {} fy_id = self.fy_id.id cr.execute("SELECT id FROM account_period WHERE date_stop < (SELECT date_start FROM account_fiscalyear WHERE id = %s)", (str(self.fy2_id.id),)) fy_period_set = ','.join(map(lambda id: str(id[0]), cr.fetchall())) cr.execute("SELECT id FROM account_period WHERE date_start > (SELECT date_stop FROM account_fiscalyear WHERE id = %s)", (str(fy_id),)) fy2_period_set = ','.join(map(lambda id: str(id[0]), cr.fetchall())) if not fy_period_set or not fy2_period_set: raise UserError(_('The periods to generate opening entries cannot be found.')) period = self.period_id new_fyear = self.fy2_id old_fyear = self.fy_id new_journal = self.journal_id company_id = new_journal.company_id.id if not new_journal.default_credit_account_id or not new_journal.default_debit_account_id: raise UserError(_('The journal must have default credit and debit account.')) if (not new_journal.centralisation) or new_journal.entry_posted: raise UserError(_('The journal must have centralized counterpart without the Skipping draft state option checked.')) #delete existing move and move lines if any move_ids = obj_acc_move.search([ ('journal_id', '=', new_journal.id), ('period_id', '=', period.id)]) if move_ids: move_line_ids = obj_acc_move_line.search([('move_id', 'in', move_ids.ids)]) move_line_ids.remove_move_reconcile() move_line_ids.unlink() move_ids.unlink() cr.execute("SELECT id FROM account_fiscalyear WHERE date_stop < %s", (str(new_fyear.date_start),)) result = cr.dictfetchall() fy_ids = [x['id'] for x in result] #create the opening move vals = { 'name': '/', 'ref': '', 'period_id': period.id, 'date': period.date_start, 'journal_id': new_journal.id, } move_id = obj_acc_move.create(vals) period_ids = self.env['account.period'].search([('fiscalyear_id', 'in', fy_ids)]) period_ids = tuple(period_ids and period_ids.ids or []) #1. report of the accounts with defferal method == 'unreconciled' cr.execute(''' SELECT a.id FROM account_account a LEFT JOIN account_account_type t ON (a.user_type_id = t.id) WHERE not a.deprecated AND a.company_id = %s AND t.close_method = %s''', (company_id, 'unreconciled', )) account_ids = map(lambda x: x[0], cr.fetchall()) account_ids = tuple(account_ids) if account_ids and period_ids: cr.execute(''' INSERT INTO account_move_line ( name, create_uid, create_date, write_uid, write_date, statement_id, journal_id, currency_id, date_maturity, partner_id, blocked, credit, state, debit, ref, account_id, period_id, date, move_id, amount_currency, quantity, product_id, company_id) (SELECT name, create_uid, create_date, write_uid, write_date, statement_id, %s,currency_id, date_maturity, partner_id, blocked, credit, 'draft', debit, ref, account_id, %s, (%s) AS date, %s, amount_currency, quantity, product_id, company_id FROM account_move_line WHERE account_id IN %s AND period_id IN %s AND not reconciled)''', (new_journal.id, period.id, period.date_start, move_id.id, account_ids, period_ids)) #We have also to consider all move_lines that were reconciled #on another fiscal year, and report them too cr.execute(''' INSERT INTO account_move_line ( name, create_uid, create_date, write_uid, write_date, statement_id, journal_id, currency_id, date_maturity, partner_id, blocked, credit, state, debit, ref, account_id, period_id, date, move_id, amount_currency, quantity, product_id, company_id) (SELECT b.name, b.create_uid, b.create_date, b.write_uid, b.write_date, b.statement_id, %s, b.currency_id, b.date_maturity, b.partner_id, b.blocked, b.credit, 'draft', b.debit, b.ref, b.account_id, %s, (%s) AS date, %s, b.amount_currency, b.quantity, b.product_id, b.company_id FROM account_move_line b WHERE b.account_id IN %s AND b.full_reconcile_id IS NOT NULL AND b.period_id IN ('''+fy_period_set+''') AND b.full_reconcile_id IN (SELECT DISTINCT(full_reconcile_id) FROM account_move_line a WHERE a.period_id IN ('''+fy2_period_set+''')))''', (new_journal.id, period.id, period.date_start, move_id.id, account_ids,)) self.invalidate_cache() #2. report of the accounts with defferal method == 'detail' cr.execute(''' SELECT a.id FROM account_account a LEFT JOIN account_account_type t ON (a.user_type_id = t.id) WHERE not a.deprecated AND a.company_id = %s AND t.close_method = %s''', (company_id, 'detail', )) account_ids = map(lambda x: x[0], cr.fetchall()) account_ids = tuple(account_ids) if account_ids and period_ids: cr.execute(''' INSERT INTO account_move_line ( name, create_uid, create_date, write_uid, write_date, statement_id, journal_id, currency_id, date_maturity, partner_id, blocked, credit, state, debit, ref, account_id, period_id, date, move_id, amount_currency, quantity, product_id, company_id) (SELECT name, create_uid, create_date, write_uid, write_date, statement_id, %s,currency_id, date_maturity, partner_id, blocked, credit, 'draft', debit, ref, account_id, %s, (%s) AS date, %s, amount_currency, quantity, product_id, company_id FROM account_move_line WHERE account_id IN %s AND period_id IN %s) ''', (new_journal.id, period.id, period.date_start, move_id.id, tuple(account_ids), period_ids)) self.invalidate_cache() #3. report of the accounts with defferal method == 'balance' cr.execute(''' SELECT a.id FROM account_account a LEFT JOIN account_account_type t ON (a.user_type_id = t.id) WHERE not a.deprecated AND a.company_id = %s AND t.close_method = %s''', (company_id, 'balance', )) account_ids = map(lambda x: x[0], cr.fetchall()) query_1st_part = """ INSERT INTO account_move_line ( debit, credit, name, date, move_id, journal_id, period_id, account_id, currency_id, amount_currency, company_id, state) VALUES """ query_2nd_part = "" query_2nd_part_args = [] for account in obj_acc_account.browse(account_ids): account.compute_values() company_currency_id = self.env.user.company_id.currency_id if not company_currency_id.is_zero(abs(account.balance)): if query_2nd_part: query_2nd_part += ',' query_2nd_part += "(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" query_2nd_part_args += (account.balance > 0 and account.balance or 0.0, account.balance < 0 and -account.balance or 0.0, self.report_name, period.date_start, move_id and move_id.id or False, new_journal.id, period.id, account.id, account.currency_id and account.currency_id.id or None, account.foreign_balance if account.currency_id else 0.0, account.company_id.id, 'draft') if query_2nd_part: cr.execute(query_1st_part + query_2nd_part, tuple(query_2nd_part_args)) self.invalidate_cache() #validate and centralize the opening move move_id.validate() #create the journal.period object and link it to the old fiscalyear new_period = self.period_id.id ids = obj_acc_journal_period.search([('journal_id', '=', new_journal.id), ('period_id', '=', new_period)]) if not ids: ids = [obj_acc_journal_period.create({ 'name': (new_journal.name or '') + ':' + (period.code or ''), 'journal_id': new_journal.id, 'period_id': period.id })] cr.execute('UPDATE account_fiscalyear ' \ 'SET end_journal_period_id = %s ' \ 'WHERE id = %s', (ids[0].id, old_fyear.id)) obj_acc_fiscalyear.invalidate_cache(['end_journal_period_id'], [old_fyear.id]) return {'type': 'ir.actions.act_window_close'}
def install_from_urls(self, urls): if not self.env.user.has_group('base.group_system'): raise AccessDenied() # One-click install is opt-in - cfr Issue #15225 ad_dir = tools.config.addons_data_dir if not os.access(ad_dir, os.W_OK): msg = (_("Automatic install of downloaded Apps is currently disabled.") + "\n\n" + _("To enable it, make sure this directory exists and is writable on the server:") + "\n%s" % ad_dir) _logger.warning(msg) raise UserError(msg) apps_server = urls.url_parse(self.get_apps_server()) OPENERP = odoo.release.product_name.lower() tmp = tempfile.mkdtemp() _logger.debug('Install from url: %r', urls) try: # 1. Download & unzip missing modules for module_name, url in urls.items(): if not url: continue # nothing to download, local version is already the last one up = urls.url_parse(url) if up.scheme != apps_server.scheme or up.netloc != apps_server.netloc: raise AccessDenied() try: _logger.info('Downloading module `%s` from OpenERP Apps', module_name) response = requests.get(url) response.raise_for_status() content = response.content except Exception: _logger.exception('Failed to fetch module %s', module_name) raise UserError(_('The `%s` module appears to be unavailable at the moment, please try again later.') % module_name) else: zipfile.ZipFile(io.BytesIO(content)).extractall(tmp) assert os.path.isdir(os.path.join(tmp, module_name)) # 2a. Copy/Replace module source in addons path for module_name, url in urls.items(): if module_name == OPENERP or not url: continue # OPENERP is special case, handled below, and no URL means local module module_path = modules.get_module_path(module_name, downloaded=True, display_warning=False) bck = backup(module_path, False) _logger.info('Copy downloaded module `%s` to `%s`', module_name, module_path) shutil.move(os.path.join(tmp, module_name), module_path) if bck: shutil.rmtree(bck) # 2b. Copy/Replace server+base module source if downloaded if urls.get(OPENERP): # special case. it contains the server and the base module. # extract path is not the same base_path = os.path.dirname(modules.get_module_path('base')) # copy all modules in the SERVER/odoo/addons directory to the new "odoo" module (except base itself) for d in os.listdir(base_path): if d != 'base' and os.path.isdir(os.path.join(base_path, d)): destdir = os.path.join(tmp, OPENERP, 'addons', d) # XXX 'odoo' subdirectory ? shutil.copytree(os.path.join(base_path, d), destdir) # then replace the server by the new "base" module server_dir = tools.config['root_path'] # XXX or dirname() bck = backup(server_dir) _logger.info('Copy downloaded module `odoo` to `%s`', server_dir) shutil.move(os.path.join(tmp, OPENERP), server_dir) #if bck: # shutil.rmtree(bck) self.update_list() with_urls = [module_name for module_name, url in urls.items() if url] downloaded = self.search([('name', 'in', with_urls)]) installed = self.search([('id', 'in', downloaded.ids), ('state', '=', 'installed')]) to_install = self.search([('name', 'in', list(urls)), ('state', '=', 'uninstalled')]) post_install_action = to_install.button_immediate_install() if installed or to_install: # in this case, force server restart to reload python code... self._cr.commit() odoo.service.server.restart() return { 'type': 'ir.actions.client', 'tag': 'home', 'params': {'wait': True}, } return post_install_action finally: shutil.rmtree(tmp)
def unlink(self): if self.question_ids and self.channel_id.channel_partner_ids: raise UserError(_("People already took this quiz. To keep course progression it should not be deleted.")) for category in self.filtered(lambda slide: slide.is_category): category.channel_id._move_category_slides(category, False) super(Slide, self).unlink()
def unlink(self): if self.env['mrp.production'].search([('bom_id', 'in', self.ids), ('state', 'not in', ['done', 'cancel'])], limit=1): raise UserError(_('You can not delete a Bill of Material with running manufacturing orders.\nPlease close or cancel it first.')) return super(MrpBom, self).unlink()
def generate_bank_statement(self): """ Use : Using this method user can able to create bank statement. Added by : Deval Jagad Added on : 05/06/2020 Task ID : 164126 :return: True """ bank_statement_obj = self.env['account.bank.statement'] partner_obj = self.env['res.partner'] bank_statement_line_obj = self.env['account.bank.statement.line'] payout_logline_obj = self.env['shopify.payout.logline.ept'] account_invoice_obj = self.env['account.move'] journal = self.instance_id.shopify_settlement_report_journal_id if not journal: message_body = "You have not configured Payout report Journal in " \ "Instance.\nPlease configured it from Setting" if self._context.get('is_cron'): self.message_post(body=_(message_body)) self.is_skip_from_cron = True return False else: raise UserError(_(message_body)) currency_id = journal.currency_id.id or self.instance_id.shopify_company_id.currency_id.id or False if currency_id != self.currency_id.id: message_body = "Report currency and Currency in Instance Journal are different.\nMake sure Report currency and Instance Journal currency must be same." self.message_post(body=_(message_body)) bank_statement_exist = bank_statement_obj.search([('shopify_payout_ref', '=', self.payout_reference_id)], limit=1) if bank_statement_exist: self.write({'statement_id': bank_statement_exist.id}) self.is_skip_from_cron = False return True name = '{0}_{1}'.format(self.instance_id.name, self.payout_reference_id) vals = { 'shopify_payout_ref': self.payout_reference_id, 'journal_id': journal.id, 'name': name, 'accounting_date': self.payout_date, 'date': self.payout_date, } bank_statement_id = bank_statement_obj.create(vals) for transaction in self.payout_transaction_ids: order_id = transaction.order_id if transaction.transaction_type in ['charge', 'refund'] and not order_id: message = "Transaction line is skip due to order {0} is not found in odoo.".format( transaction.source_order_id) payout_logline_obj.create({'message': message, 'instance_id': self.instance_id.id, 'payout_transaction_ref': transaction.transaction_id, 'payout_id': self.id}) transaction.is_remaining_statement = True continue partner = partner_obj._find_accounting_partner(order_id.partner_id) invoice_ids = account_invoice_obj account_id = False if transaction.transaction_type == 'charge': invoice_ids = order_id.invoice_ids.filtered( lambda l: l.state == 'posted' and l.type == 'out_invoice' and l.amount_total == transaction.amount) if not invoice_ids: message = "Invoice is not created for order %s in odoo" % ( order_id.name or transaction.source_order_id) payout_logline_obj.create({'message': message, 'is_skipped': True, 'instance_id': self.instance_id.id, 'payout_transaction_ref': transaction.transaction_id, 'payout_id': self.id}) transaction.is_remaining_statement = True continue if transaction.transaction_type == 'refund': invoice_ids = order_id.invoice_ids.filtered( lambda l: l.state == 'posted' and l.type == 'out_refund' and l.amount_total == -( transaction.amount)) if not invoice_ids: message = "In shopify payout there is refund, but Refund is not created for order %s in odoo" % ( order_id.name or transaction.source_order_id) payout_logline_obj.create({'message': message, 'is_skipped': True, 'instance_id': self.instance_id.id, 'payout_transaction_ref': transaction.transaction_id, 'payout_id': self.id}) transaction.is_remaining_statement = True continue payment_reference = False if transaction.transaction_type not in ['charge', 'refund']: shopify_account_config_id = self.instance_id.transaction_line_ids.filtered(lambda l: l.transaction_type == transaction.transaction_type) account_id = shopify_account_config_id and shopify_account_config_id.account_id if transaction.transaction_type == 'charge': payment_reference = self.env['account.payment'].search([('invoice_ids', 'in', invoice_ids.ids), ('amount', '=', transaction.amount), ('payment_type', '=', 'inbound')], limit=1) if transaction.transaction_type == 'refund': payment_reference = self.env['account.payment'].search([('invoice_ids', 'in', invoice_ids.ids), ('amount', '=', -transaction.amount), ('payment_type', '=', 'outbound')], limit=1) if payment_reference: reference = payment_reference.name payment_aml_rec = payment_reference.mapped('move_line_ids').filtered( lambda line: line.account_internal_type == "liquidity") if self.check_reconciled_transactions(transaction, payment_aml_rec): continue else: reference = invoice_ids.name or '' if transaction.amount: bank_line_vals = { 'name': order_id.name or transaction.transaction_type, 'ref': reference or '', 'date': self.payout_date, 'partner_id': partner and partner.id, 'amount': transaction.amount, 'statement_id': bank_statement_id.id, 'shopify_order_ids': [(6, 0, order_id.ids)], 'shopify_transaction_id': transaction.transaction_id, 'shopify_transaction_type': transaction.transaction_type, } if account_id: bank_line_vals.update({'account_ept_id': account_id.id}) bank_statement_line_obj.create(bank_line_vals) if self.check_process_statement(): state = 'generated' else: state = 'partially_generated' if bank_statement_id: self.write({'statement_id': bank_statement_id.id, 'state': state}) if self.reconciliation_log_ids: self.env['shopify.payout.logline.ept'].create_payout_schedule_activity(self.reconciliation_log_ids) self.is_skip_from_cron = False return True
def compute_depreciation_board(self): def group_lines(x, y): y.update({'amount': x['amount'] + y['amount']}) return y line_obj = self.env['account.asset.line'] digits = self.env['decimal.precision'].precision_get('Account') for asset in self: if asset.value_residual == 0.0: continue domain = [('asset_id', '=', asset.id), ('type', '=', 'depreciate'), '|', ('move_check', '=', True), ('init_entry', '=', True)] posted_lines = line_obj.search(domain, order='line_date desc') if posted_lines: last_line = posted_lines[0] else: last_line = line_obj domain = [('asset_id', '=', asset.id), ('type', '=', 'depreciate'), ('move_id', '=', False), ('init_entry', '=', False)] old_lines = line_obj.search(domain) if old_lines: old_lines.unlink() table = asset._compute_depreciation_table() if not table: continue # group lines prior to depreciation start period depreciation_start_date = asset.date_start lines = table[0]['lines'] lines1 = [] lines2 = [] flag = lines[0]['date'] < depreciation_start_date for line in lines: if flag: lines1.append(line) if line['date'] >= depreciation_start_date: flag = False else: lines2.append(line) if lines1: lines1 = [reduce(group_lines, lines1)] lines1[0]['depreciated_value'] = 0.0 table[0]['lines'] = lines1 + lines2 # check table with posted entries and # recompute in case of deviation depreciated_value_posted = depreciated_value = 0.0 if posted_lines: last_depreciation_date = last_line.line_date last_date_in_table = table[-1]['lines'][-1]['date'] if last_date_in_table <= last_depreciation_date: raise UserError( _("The duration of the asset conflicts with the " "posted depreciation table entry dates.")) for table_i, entry in enumerate(table): residual_amount_table = \ entry['lines'][-1]['remaining_value'] if entry['date_start'] <= last_depreciation_date \ <= entry['date_stop']: break if entry['date_stop'] == last_depreciation_date: table_i += 1 line_i = 0 else: entry = table[table_i] date_min = entry['date_start'] for line_i, line in enumerate(entry['lines']): residual_amount_table = line['remaining_value'] if date_min <= last_depreciation_date <= line['date']: break date_min = line['date'] if line['date'] == last_depreciation_date: line_i += 1 table_i_start = table_i line_i_start = line_i # check if residual value corresponds with table # and adjust table when needed depreciated_value_posted = depreciated_value = \ sum([l.amount for l in posted_lines]) residual_amount = asset.depreciation_base - depreciated_value amount_diff = round(residual_amount_table - residual_amount, digits) if amount_diff: # compensate in first depreciation entry # after last posting line = table[table_i_start]['lines'][line_i_start] line['amount'] -= amount_diff else: # no posted lines table_i_start = 0 line_i_start = 0 seq = len(posted_lines) depr_line = last_line last_date = table[-1]['lines'][-1]['date'] depreciated_value = depreciated_value_posted for entry in table[table_i_start:]: for line in entry['lines'][line_i_start:]: seq += 1 name = asset._get_depreciation_entry_name(seq) if line['date'] == last_date: # ensure that the last entry of the table always # depreciates the remaining value if asset.method in ['linear-limit', 'degr-limit']: depr_max = asset.depreciation_base \ - asset.salvage_value else: depr_max = asset.depreciation_base amount = depr_max - depreciated_value else: amount = line['amount'] if amount: vals = { 'previous_id': depr_line.id, 'amount': round(amount, digits), 'asset_id': asset.id, 'name': name, 'line_date': line['date'], 'line_days': line['days'], 'init_entry': entry['init'], } depreciated_value += round(amount, digits) depr_line = line_obj.create(vals) else: seq -= 1 line_i_start = 0 return True
def _check_pin(self): if self.authorize_password and not self.authorize_password.isdigit(): raise UserError(_("Authorize Password can only contain digits"))
def _check_dates(self): for asset in self: if asset.method_time == 'end': if asset.method_end <= asset.date_start: raise UserError( _("The Start Date must precede the Ending Date."))
def _check_method(self): for asset in self: if asset.method == 'degr-linear' and asset.method_time != 'year': raise UserError( _("Degressive-Linear is only supported for Time Method = " "Year."))
def do_billing(self): pre_invoice = {} # lista de facuri agreements = self.env["service.agreement"] for cons in self.consumption_ids: pre_invoice[cons.date_invoice] = {} agreements |= cons.agreement_id self.do_billing_step1(pre_invoice) for cons in self.consumption_ids.filtered(lambda r: r.state == "none"): if self.group_invoice == "agreement" or cons.agreement_id.invoice_mode == "detail": key = cons.agreement_id.id else: key = cons.partner_id.id if pre_invoice[cons.date_invoice].get(key, False): # daca a fost generata o factura atunci leg si consumul de facura pentru a aparea in centralizator pre_invoice[cons.date_invoice][key]["cons"] += cons if not pre_invoice: raise UserError(_("No condition for create a new invoice")) res = [] for date_invoice in pre_invoice: for key in pre_invoice[date_invoice]: comment = _("According to agreement ") payment_term_id = False for agreement in pre_invoice[date_invoice][key][ "agreement_ids"]: comment += _("%s from %s \n") % (agreement.name or "____", agreement.date_agreement or "____") if len(pre_invoice[date_invoice][key]["agreement_ids"]) > 1: payment_term_id = False else: for agreement in pre_invoice[date_invoice][key][ "agreement_ids"]: payment_term_id = agreement.payment_term_id.id invoice_value = { # 'name': _('Invoice'), "partner_id": pre_invoice[date_invoice][key]["partner_id"], "journal_id": self.journal_id.id, "company_id": self.company_id.id, "date_invoice": date_invoice, "payment_term_id": payment_term_id, # todo: de determinat contul # 'account_id': pre_invoice[date_invoice][key]['account_id'], "type": "out_invoice", "state": "draft", "invoice_line_ids": [(0, 0, x) for x in pre_invoice[date_invoice][key]["lines"]], "comment": comment, # 'agreement_id':pre_invoice[key]['agreement_id'], } invoice_id = self.env["account.move"].create(invoice_value) # todo: de determinat care e butonul de calcul tva # invoice_id.button_compute(True) pre_invoice[date_invoice][key]["cons"].write( {"invoice_id": invoice_id.id}) res.append(invoice_id.id) agreements.compute_totals() action = self.env.ref( "deltatech_service.action_service_invoice").read()[0] action["domain"] = "[('id','in', [" + ",".join(map(str, res)) + "])]" return action
def find_source_order(self): ''' 查看原始单据,有以下情况:销售发货单、销售退货单、采购退货单、采购入库单、 项目、委外加工单、核销单、购货订单、固定资产、固定资产变更以及期初应收应付。 ''' self.ensure_one() code = False res_models = [ 'reconcile.order', ] views = [ 'money.reconcile_order_form', ] # 判断当前数据库中否存在该 model if self.env.get('sell.delivery') != None: res_models += ['sell.delivery'] views += ['sell.sell_delivery_form'] if self.env.get('outsource') != None: res_models += ['outsource'] views += ['warehouse.outsource_form'] if self.env.get('buy.order') != None: res_models += ['buy.order'] views += ['buy.buy_order_form'] if self.env.get('buy.receipt') != None: res_models += ['buy.receipt'] views += ['buy.buy_receipt_form'] if self.env.get('project') != None: res_models += ['project'] views += ['task.project_form'] if self.env.get('asset') != None: res_models += ['asset'] views += ['asset.asset_form'] if self.env.get('cost.order') != None: res_models += ['cost.order'] views += ['account_cost.cost_order_form'] if u'固定资产变更' in self.name: code = self.name.replace(u'固定资产变更', '') elif u'固定资产' in self.name: code = self.name.replace(u'固定资产', '') domain = code and [('code', '=', code)] or [('name', '=', self.name)] for i in range(len(res_models)): # 若code存在说明 model为asset,view为固定资产form视图。 res_model = code and 'asset' or res_models[i] view = code and self.env.ref('asset.asset_form') or self.env.ref( views[i]) res = self.env[res_model].search(domain) if res: # 如果找到res_id,则退出for循环。 break if not res: raise UserError(u'没有原始单据可供查看。') if res_model == 'sell.delivery' and res.is_return: view = self.env.ref('sell.sell_return_form') elif res_model == 'buy.receipt' and res.is_return: view = self.env.ref('buy.buy_return_form') return { 'view_type': 'form', 'view_mode': 'form', 'view_id': False, 'views': [(view.id, 'form')], 'res_model': res_model, 'type': 'ir.actions.act_window', 'res_id': res.id, }
def get_payout_report(self, start_date, end_date, instance): """ Use : Using this method get Payout records as per date given. Added by : Deval Jagad (02/06/2020) Task ID : 164126 :param start_date:From Date(year-month-day) :param end_date: To Date(year-month-day) :param instance: Browsable shopify instance. :return: True """ shopify_payout_report_line_obj = self.env['shopify.payout.report.line.ept'] log_book_obj = self.env['common.log.book.ept'] log_line_obj = self.env['common.log.lines.ept'] if not instance.shopify_api_url: raise UserError(_("Shopify API URL is blank!")) shop = instance.shopify_host.split("//") headers = {"Accept": "application/json", "Content-Type": "application/json; charset=utf-8"} params = {"status": 'paid', "date_min": start_date, "date_max": end_date, "limit": 250} try: shopify_api_url = instance.shopify_api_url + 'payouts.json' payout_ids = [] if len(shop) == 2: url = "{0}//{1}:{2}@{3}/{4}".format(shop[0], instance.shopify_api_key, instance.shopify_password, shop[1], shopify_api_url) else: url = "https://{0}:{1}@{2}/{3}".format(instance.shopify_api_key, instance.shopify_password, shop[0], shopify_api_url) response = requests.get(url, params=params, headers=headers) payout_response = response.json() payout_ids = payout_ids + payout_response.get('payouts', []) except Exception as error: message = "Something is wrong while import the payout records : {0}".format(error) model = "shopify.payout.report.ept" model_id = self.env["common.log.lines.ept"].get_model_id(model) log_book_id = log_book_obj.create({'type': 'import', 'module': 'shopify_ept', 'shopify_instance_id': instance.id, 'model_id': model_id and model_id.id, 'create_date': datetime.now(), 'active': True}) log_line_obj.create({'log_book_id': log_book_id, 'message': message, 'model_id': model_id and model_id.id or False, }) return False for payout in payout_ids: _logger.info("Payout ID %s ", payout.get('id')) payout_id = self.search([('instance_id', '=', instance.id), ('payout_reference_id', '=', payout.get('id'))]) if payout_id: continue payout_vals = self.prepare_payout_vals(payout, instance) payout_id = self.create(payout_vals) if not payout_id: continue # Get Payout Transaction data and Create record. transaction_ids = self.get_payout_transactions_data(payout_id, instance) for transaction in transaction_ids: _logger.info("Transaction ID %s ", transaction.get('id')) transaction_vals = self.prepare_transaction_vals(transaction, payout_id, instance) shopify_payout_report_line_obj.create(transaction_vals) # Create fees line fees_amount = float(payout.get('summary').get('charges_fee_amount', 0.0)) + float( payout.get('summary').get('refunds_fee_amount', 0.0)) + float( payout.get('summary').get('adjustments_fee_amount', 0.0)) shopify_payout_report_line_obj.create({ 'payout_id': payout_id.id or False, 'transaction_id': '', 'source_order_id': '', 'transaction_type': 'fees', 'order_id': '', 'amount': -fees_amount, 'fee': 0.0, 'net_amount': fees_amount, }) instance.write({'payout_last_import_date': datetime.now()}) return True
def button_uninstall(self): if 'base' in self.mapped('name'): raise UserError(_("The `base` module cannot be uninstalled")) deps = self.downstream_dependencies() (self + deps).write({'state': 'to remove'}) return dict(ACTION_DICT, name=_('Uninstall'))
def _onchange_product_uom_id(self): if self.product_id and self.product_uom_id.category_id != self.product_id.uom_id.category_id: raise UserError(_('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.'))
def tax_invoice_draft(self): for rec in self: if rec.state == 'draft': raise UserError(u'请不要重复反确认') rec.state = 'draft'
def unlink(self): for expense in self: if expense.state in ['done', 'approved']: raise UserError(_('You cannot delete a posted or approved expense.')) return super(HrExpense, self).unlink()
def action_set_viewed(self, quiz_attempts_inc=False): if not all(slide.channel_id.is_member for slide in self): raise UserError(_('You cannot mark a slide as viewed if you are not among its members.')) return bool(self._action_set_viewed(self.env.user.partner_id, quiz_attempts_inc=quiz_attempts_inc))
def unlink(self): for expense in self: if expense.state in ['post', 'done']: raise UserError(_('You cannot delete a posted or paid expense.')) super(HrExpenseSheet, self).unlink()
def _get_invoice_matching_query(self, st_lines, excluded_ids=None, partner_map=None): ''' Get the query applying all rules trying to match existing entries with the given statement lines. :param st_lines: Account.bank.statement.lines recordset. :param excluded_ids: Account.move.lines to exclude. :param partner_map: Dict mapping each line with new partner eventually. :return: (query, params) ''' if any(m.rule_type != 'invoice_matching' for m in self): raise UserError(_('Programmation Error: Can\'t call _get_invoice_matching_query() for different rules than \'invoice_matching\'')) queries = [] all_params = [] for rule in self: # N.B: 'communication_flag' is there to distinguish invoice matching through the number/reference # (higher priority) from invoice matching using the partner (lower priority). query = r''' SELECT %s AS sequence, %s AS model_id, st_line.id AS id, aml.id AS aml_id, aml.currency_id AS aml_currency_id, aml.date_maturity AS aml_date_maturity, aml.amount_residual AS aml_amount_residual, aml.amount_residual_currency AS aml_amount_residual_currency, aml.balance AS aml_balance, aml.amount_currency AS aml_amount_currency, account.internal_type AS account_internal_type, ''' + rule._get_select_communication_flag() + r''', ''' + rule._get_select_payment_reference_flag() + r''' FROM account_bank_statement_line st_line LEFT JOIN account_journal journal ON journal.id = st_line.journal_id LEFT JOIN jnl_precision ON jnl_precision.journal_id = journal.id LEFT JOIN res_company company ON company.id = st_line.company_id LEFT JOIN partners_table line_partner ON line_partner.line_id = st_line.id , account_move_line aml LEFT JOIN account_move move ON move.id = aml.move_id AND move.state = 'posted' LEFT JOIN account_account account ON account.id = aml.account_id WHERE st_line.id IN %s AND aml.company_id = st_line.company_id AND move.state = 'posted' AND ( -- the field match_partner of the rule might enforce the second part of -- the OR condition, later in _apply_conditions() line_partner.partner_id = 0 OR aml.partner_id = line_partner.partner_id ) AND CASE WHEN st_line.amount > 0.0 THEN aml.balance > 0 ELSE aml.balance < 0 END -- if there is a partner, propose all aml of the partner, otherwise propose only the ones -- matching the statement line communication AND ( ( line_partner.partner_id != 0 AND aml.partner_id = line_partner.partner_id ) OR ( line_partner.partner_id = 0 AND substring(REGEXP_REPLACE(st_line.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*') != '' AND ( ( aml.name IS NOT NULL AND substring(REGEXP_REPLACE(aml.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*') != '' AND regexp_split_to_array(substring(REGEXP_REPLACE(aml.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'),'\s+') && regexp_split_to_array(substring(REGEXP_REPLACE(st_line.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'), '\s+') ) OR regexp_split_to_array(substring(REGEXP_REPLACE(move.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'),'\s+') && regexp_split_to_array(substring(REGEXP_REPLACE(st_line.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'), '\s+') OR ( move.ref IS NOT NULL AND substring(REGEXP_REPLACE(move.ref, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*') != '' AND regexp_split_to_array(substring(REGEXP_REPLACE(move.ref, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'),'\s+') && regexp_split_to_array(substring(REGEXP_REPLACE(st_line.name, '[^0-9|^\s]', '', 'g'), '\S(?:.*\S)*'), '\s+') ) OR ( move.invoice_payment_ref IS NOT NULL AND regexp_replace(move.invoice_payment_ref, '\s+', '', 'g') = regexp_replace(st_line.name, '\s+', '', 'g') ) ) ) ) AND ( ( -- blue lines appearance conditions aml.account_id IN (journal.default_credit_account_id, journal.default_debit_account_id) AND aml.statement_id IS NULL AND ( company.account_bank_reconciliation_start IS NULL OR aml.date > company.account_bank_reconciliation_start ) ) OR ( -- black lines appearance conditions account.reconcile IS TRUE AND aml.reconciled IS FALSE ) ) ''' # Filter on the same currency. if rule.match_same_currency: query += ''' AND COALESCE(st_line.currency_id, journal.currency_id, company.currency_id) = COALESCE(aml.currency_id, company.currency_id) ''' params = [rule.sequence, rule.id, tuple(st_lines.ids)] # Filter out excluded account.move.line. if excluded_ids: query += 'AND aml.id NOT IN %s' params += [tuple(excluded_ids)] query, params = rule._apply_conditions(query, params) queries.append(query) all_params += params full_query = self._get_with_tables(st_lines, partner_map=partner_map) full_query += ' UNION ALL '.join(queries) # Oldest due dates come first. full_query += ' ORDER BY aml_date_maturity, aml_id' return full_query, all_params
def unlink(self): for ob in self: if ob.state != 'draft': raise UserError('No puede eliminar un documento validado.') super(AccountBankReconcile, self).unlink() return True
def execute(self): self.ensure_one() if not self.env.user.has_group( 'b2b_platform.group_qdoo_distributor_manager'): raise UserError("只有管理员才允许修改配置参数") self = self.with_context(active_test=False) classified = self._get_classified_fields() # default values fields IrValues = self.env['ir.values'].sudo() for name, model, field in classified['default']: if isinstance(self[name], models.BaseModel): if self._fields[name].type == 'many2one': value = self[name].id else: value = self[name].ids else: value = self[name] IrValues.set_default(model, field, value) # group fields: modify group / implied groups for name, groups, implied_group in classified['group']: if self[name]: groups.write({'implied_ids': [(4, implied_group.id)]}) else: groups.write({'implied_ids': [(3, implied_group.id)]}) implied_group.write({ 'users': [(3, user.id) for user in groups.mapped('users')] }) # other fields: execute all methods that start with 'set_' for method in dir(self): if method.startswith('set_'): getattr(self, method)() # module fields: install/uninstall the selected modules to_install = [] to_uninstall_modules = self.env['ir.module.module'] lm = len('module_') for name, module in classified['module']: if self[name]: to_install.append((name[lm:], module)) else: if module and module.state in ('installed', 'to upgrade'): to_uninstall_modules += module if to_uninstall_modules: to_uninstall_modules.button_immediate_uninstall() action = self._install_modules(to_install) if action: return action if to_install or to_uninstall_modules: # After the uninstall/install calls, the registry and environments # are no longer valid. So we reset the environment. self.env.reset() self = self.env()[self._name] config = self.env['res.config'].next() or {} if config.get('type') not in ('ir.actions.act_window_close', ): return config # force client-side reload (update user menu and current view) return { 'type': 'ir.actions.client', 'tag': 'reload', }
def unlink(self): for record in self: if record.number and record.state not in ('draft','cancel'): raise UserError(_('You can not delete invoice')) return super(CustomerInvoiceExtends, self).unlink()
def write(self, vals): for journal in self: company = journal.company_id if ('company_id' in vals and journal.company_id.id != vals['company_id']): if self.env['account.move'].search( [('journal_id', '=', journal.id)], limit=1): raise UserError( _('This journal already contains items, therefore you cannot modify its company.' )) company = self.env['res.company'].browse(vals['company_id']) if journal.bank_account_id.company_id and journal.bank_account_id.company_id != company: journal.bank_account_id.write({ 'company_id': company.id, 'partner_id': company.partner_id.id, }) if 'currency_id' in vals: if journal.bank_account_id: journal.bank_account_id.currency_id = vals['currency_id'] if 'bank_account_id' in vals: if not vals.get('bank_account_id'): raise UserError( _('You cannot remove the bank account from the journal once set.' )) else: bank_account = self.env['res.partner.bank'].browse( vals['bank_account_id']) if bank_account.partner_id != company.partner_id: raise UserError( _("The partners of the journal's company and the related bank account mismatch." )) if 'alias_name' in vals: journal._update_mail_alias(vals) if 'restrict_mode_hash_table' in vals and not vals.get( 'restrict_mode_hash_table'): journal_entry = self.env['account.move'].search( [('journal_id', '=', self.id), ('state', '=', 'posted'), ('secure_sequence_number', '!=', 0)], limit=1) if len(journal_entry) > 0: field_string = self._fields[ 'restrict_mode_hash_table'].get_description( self.env)['string'] raise UserError( _( "You cannot modify the field %s of a journal that already has accounting entries.", field_string)) result = super(AccountJournal, self).write(vals) for journal in self: # Ensure the liquidity accounts are sharing the same foreign currency. accounts = journal.default_debit_account_id + journal.default_credit_account_id accounts.write({'currency_id': journal.currency_id.id}) # Create the bank_account_id if necessary if 'bank_acc_number' in vals: for journal in self.filtered( lambda r: r.type == 'bank' and not r.bank_account_id): journal.set_bank_account(vals.get('bank_acc_number'), vals.get('bank_id')) for record in self: if record.restrict_mode_hash_table and not record.secure_sequence_id: record._create_secure_sequence(['secure_sequence_id']) return result
def money_order_done(self): '''对收付款单的审核按钮''' for order in self: if order.type == 'pay' and not order.partner_id.s_category_id.account_id: raise UserError(u'请输入供应商类别(%s)上的科目' % order.partner_id.s_category_id.name) if order.type == 'get' and not order.partner_id.c_category_id.account_id: raise UserError(u'请输入客户类别(%s)上的科目' % order.partner_id.c_category_id.name) if order.advance_payment < 0: raise UserError(u'本次核销金额不能大于付款金额。\n差额: %s' % (order.advance_payment)) total = 0 for line in order.line_ids: rate_silent = self.env['res.currency'].get_rate_silent( order.date, line.currency_id.id) if order.type == 'pay': # 付款账号余额减少, 退款账号余额增加 decimal_amount = self.env.ref('core.decimal_amount') balance = line.currency_id != self.env.user.company_id.currency_id \ and line.bank_id.currency_amount or line.bank_id.balance if float_compare( balance, line.amount, precision_digits=decimal_amount.digits) == -1: raise UserError(u'账户余额不足。\n账户余额:%s 付款行金额:%s' % (balance, line.amount)) if line.currency_id != self.env.user.company_id.currency_id: # 外币 line.bank_id.currency_amount -= line.amount line.bank_id.balance -= line.amount * rate_silent else: line.bank_id.balance -= line.amount else: # 收款账号余额增加, 退款账号余额减少 if line.currency_id != self.env.user.company_id.currency_id: # 外币 line.bank_id.currency_amount += line.amount line.bank_id.balance += line.amount * rate_silent else: line.bank_id.balance += line.amount total += line.amount if order.type == 'pay': order.partner_id.payable -= total - order.discount_amount else: order.partner_id.receivable -= total + order.discount_amount # 更新结算单的未核销金额、已核销金额 for source in order.source_ids: '''float_compare(value1,value2): return -1, 0 or 1, if 'value1' is lower than, equal to, or greater than 'value2' at the given precision''' decimal_amount = self.env.ref('core.decimal_amount') if float_compare(source.this_reconcile, abs(source.to_reconcile), precision_digits=decimal_amount.digits) == 1: raise UserError( u'本次核销金额不能大于未核销金额。\n 核销金额:%s 未核销金额:%s' % (abs(source.to_reconcile), source.this_reconcile)) source.name.to_reconcile -= source.this_reconcile source.name.reconciled += source.this_reconcile # 生成凭证并审核 if order.type == 'get': voucher = order.create_money_order_get_voucher( order.line_ids, order.source_ids, order.partner_id, order.name, order.note or '') else: voucher = order.create_money_order_pay_voucher( order.line_ids, order.source_ids, order.partner_id, order.name, order.note or '') voucher.voucher_done() return order.write({ 'to_reconcile': order.advance_payment, 'reconciled': order.amount - order.advance_payment, 'voucher_id': voucher.id, 'state': 'done', })
def _unlink_except_done(self): if 'done' in self.mapped('state'): raise UserError(_("You cannot delete an unbuild order if the state is 'Done'."))
def unlink(self): raise UserError("No se puede eliminar un tipo memorandums.") return super(TypeMemo, self).unlink()