def _get_by_doc(self, store, data, doc): # Extra precaution in case we ever send the cpf already formatted document = format_cpf(raw_document(doc)) person = Person.get_by_document(store, document) if not person or not person.client: return data return self._dump_client(person.client)
def _get_by_doc(self, store, data, doc): # Extra precaution in case we ever send the cpf already formatted document = format_cpf(raw_document(doc)) person = Person.get_by_document(store, document) if person and person.client: data = self._dump_client(person.client) # Plugins that listen to this signal will return extra fields # to be added to the response responses = signal('CheckRewardsPermissionsEvent').send(doc) for response in responses: data.update(response[1]) return data
def get(self, store): from stoqnfe.domain.distribution import ImportedNfe cnpj = self.get_arg('cnpj') limit = self.get_arg('limit') offset = self.get_arg('offset') if not cnpj: message = "'cnpj' not provided" log.error(message) abort(400, message) if not validate_cnpj(cnpj): message = "Invalid 'cnpj' provided" log.error(message) abort(400, message) if limit is not None: try: limit = int(limit) except (TypeError, ValueError): message = "'limit' must be a number" log.error(message) abort(400, message) if limit > MAX_PAGE_SIZE: message = "'limit' must be lower than %s" % MAX_PAGE_SIZE log.error(message) abort(400, message) if offset is not None: try: offset = int(offset) except (TypeError, ValueError): message = "'offset' must be a number" log.error(message) abort(400, message) cnpj = format_cnpj(raw_document(cnpj)) limit = limit or 20 offset = offset or 0 login_user = self.get_current_user(store) tables = [ Branch, Join(Person, Branch.person_id == Person.id), Join(Company, Company.person_id == Person.id) ] query = Eq(Company.cnpj, cnpj) branches = store.using(*tables).find(Branch, query) # XXX There should exist at least one branch in database with # the cnpj from ImportedNfes. Otherwise, there is something wrong that # could lead to unwanted access to these ImportedNfes. assert branches for branch in branches: has_access = UserBranchAccess.has_access(store, login_user, branch) if has_access: continue message = 'login_user %s does not have access to branch %s' % \ (login_user.id, branch.id) log.error(message) abort(403, message) result = store.find(ImportedNfe, cnpj=cnpj).order_by(Desc(ImportedNfe.te_id)) result_count = result.count() imported_nfes = result.config(offset=offset, limit=limit) records = [] for imported_nfe in imported_nfes: # FIXME: Change it to a store.find() when NFePurchase.key had been implemented query = "SELECT id FROM nfe_purchase WHERE cnpj='{}' AND xml::text ilike '%{}%'" nfe_purchase = store.execute( query.format(imported_nfe.cnpj, imported_nfe.key)).get_one() process_date = imported_nfe.process_date record = { 'id': imported_nfe.id, 'key': imported_nfe.key, # Since process_date is a new column, we can't assure that # all entries have it fulfilled 'process_date': process_date and process_date.isoformat(), 'purchase_invoice_id': nfe_purchase and nfe_purchase[0] } records.append(record) next_offset = offset + limit has_next = result_count > next_offset next_ = None if has_next: next_ = self.routes[0] + '?limit={}&offset={}&cnpj={}'.format( limit, offset + limit, cnpj) has_previous = offset > 0 previous = None if has_previous: previous = self.routes[0] + '?limit={}&offset={}&cnpj={}'.format( limit, max(offset - limit, 0), cnpj) response = { 'previous': previous, 'next': next_, 'count': len(records), 'total_records': result_count, 'records': records } return make_response(jsonify(response), 200)
def post(self, store): # FIXME: Check branch state and force fail if no override for that product is present. self.ensure_printer() data = request.get_json() client_id = data.get('client_id') products = data['products'] payments = data['payments'] client_category_id = data.get('price_table') document = raw_document(data.get('client_document', '') or '') if document: document = format_document(document) if client_id: client = store.get(Client, client_id) elif document: person = Person.get_by_document(store, document) client = person and person.client else: client = None # Create the sale branch = api.get_current_branch(store) group = PaymentGroup(store=store) user = api.get_current_user(store) sale = Sale( store=store, branch=branch, salesperson=user.person.sales_person, client=client, client_category_id=client_category_id, group=group, open_date=localnow(), coupon_id=None, ) # Add products for p in products: sellable = store.get(Sellable, p['id']) item = sale.add_sellable(sellable, price=currency(p['price']), quantity=decimal.Decimal(p['quantity'])) # XXX: bdil has requested that when there is a special discount, the discount does # not appear on the coupon. Instead, the item wil be sold using the discount price # as the base price. Maybe this should be a parameter somewhere item.base_price = item.price # Add payments sale_total = sale.get_total_sale_amount() money_payment = None payments_total = 0 for p in payments: method_name = p['method'] tef_data = p.get('tef_data', {}) if method_name == 'tef': p['provider'] = tef_data['card_name'] method_name = 'card' method = PaymentMethod.get_by_name(store, method_name) installments = p.get('installments', 1) or 1 due_dates = list(create_date_interval( INTERVALTYPE_MONTH, interval=1, start_date=localnow(), count=installments)) payment_value = currency(p['value']) payments_total += payment_value p_list = method.create_payments( Payment.TYPE_IN, group, branch, payment_value, due_dates) if method.method_name == 'money': # FIXME Frontend should not allow more than one money payment. this can be changed # once https://gitlab.com/stoqtech/private/bdil/issues/75 is fixed? if not money_payment or payment_value > money_payment.value: money_payment = p_list[0] elif method.method_name == 'card': for payment in p_list: card_data = method.operation.get_card_data_by_payment(payment) card_type = p['mode'] # Stoq does not have the voucher comcept, so register it as a debit card. if card_type == 'voucher': card_type = 'debit' device = self._get_card_device(store, 'TEF') provider = self._get_provider(store, p['provider']) if tef_data: card_data.nsu = tef_data['aut_loc_ref'] card_data.auth = tef_data['aut_ext_ref'] card_data.update_card_data(device, provider, card_type, installments) card_data.te.metadata = tef_data # If payments total exceed sale total, we must adjust money payment so that the change is # correctly calculated.. if payments_total > sale_total and money_payment: money_payment.value -= (payments_total - sale_total) assert money_payment.value >= 0 # Confirm the sale group.confirm() sale.order() till = Till.get_last(store) sale.confirm(till) # Fiscal plugins will connect to this event and "do their job" # It's their responsibility to raise an exception in case of # any error, which will then trigger the abort bellow # FIXME: Catch printing errors here and send message to the user. SaleConfirmedRemoteEvent.emit(sale, document) # This will make sure we update any stock or price changes products may # have between sales return True
def get(self, store): data = request.args required_params = ['dtinicio', 'dtfim'] _check_required_params(data, required_params) initial_date = datetime.datetime.strptime(data['dtinicio'], '%Y-%m-%d') end_date = datetime.datetime.combine( datetime.datetime.strptime(data['dtfim'], '%Y-%m-%d').date(), datetime.time.max) request_branches = data.get('lojas') request_documents = data.get('consumidores') request_invoice_keys = data.get('operacaocupom') branch_ids = _parse_request_list(request_branches) _check_if_uuid(branch_ids) documents = _parse_request_list(request_documents) invoice_keys = _parse_request_list(request_invoice_keys) clauses = [ Sale.confirm_date >= initial_date, Sale.confirm_date <= end_date ] ClientPerson = ClassAlias(Person, 'person_client') ClientIndividual = ClassAlias(Individual, 'individual_client') ClientCompany = ClassAlias(Company, 'company_client') SalesPersonPerson = ClassAlias(Person, 'person_sales_person') SalesPersonIndividual = ClassAlias(Individual, 'individual_sales_person') tables = [ Sale, Join(Branch, Sale.branch_id == Branch.id), LeftJoin(Client, Client.id == Sale.client_id), LeftJoin(Person, Person.id == Client.person_id), Join(BranchStation, Sale.station_id == BranchStation.id), LeftJoin(ClientPerson, Client.person_id == ClientPerson.id), LeftJoin(ClientIndividual, Client.person_id == ClientIndividual.person_id), LeftJoin(Individual, Client.person_id == Individual.person_id), LeftJoin(ClientCompany, Client.person_id == ClientCompany.person_id), LeftJoin(Company, Client.person_id == Company.person_id), LeftJoin(SalesPerson, SalesPerson.id == Sale.salesperson_id), LeftJoin(SalesPersonPerson, SalesPerson.person_id == SalesPersonPerson.id), LeftJoin(SalesPersonIndividual, SalesPerson.person_id == SalesPersonIndividual.person_id), Join(LoginUser, LoginUser.person_id == SalesPerson.person_id), Join(PaymentGroup, PaymentGroup.id == Sale.group_id), Join(Invoice, Sale.invoice_id == Invoice.id), ] payment_tables = [ Payment, Join(PaymentMethod, Payment.method_id == PaymentMethod.id), Join(PaymentGroup, Payment.group_id == PaymentGroup.id), ] sale_objs = (Sale, ClientCompany, ClientIndividual, LoginUser, Branch, PaymentGroup, BranchStation, Client, ClientPerson, SalesPerson, SalesPersonPerson) payment_objs = (Payment, PaymentMethod, PaymentGroup) if len(branch_ids) > 0: clauses.append(Branch.id.is_in(branch_ids)) if len(documents) > 0: clauses.append( Or(Individual.cpf.is_in(documents), Company.cnpj.is_in(documents))) if len(invoice_keys) > 0: clauses.append(Invoice.key.is_in(invoice_keys)) if data.get('cancelados') and data.get('cancelados') == '0': clauses.append(Sale.status != Sale.STATUS_CANCELLED) if data.get('cancelados') and data.get('cancelados') == '1': clauses.append(Sale.status == Sale.STATUS_CANCELLED) data = list(store.using(*tables).find(sale_objs, And(*clauses))) group_ids = [i[0].group_id for i in data] payments_list = list( store.using(*payment_tables).find( payment_objs, Payment.group_id.is_in(group_ids))) sale_payments = {} for payment in payments_list: sale_payments.setdefault(payment[0].group_id, []) sale_payments[payment[0].group_id].append(payment[0]) response = [] for row in data: sale, company, individual, login_user, branch, group = row[:6] cpf = individual and individual.cpf cnpj = company and company.cnpj document = cpf or cnpj or '' if cpf: document_type = 'CPF' elif cnpj: document_type = 'CNPJ' else: document_type = '' network = _get_network_info() payment_methods = _get_payments_info(sale_payments[sale.group_id], login_user, sale) change = sum(payment['troco'] for payment in payment_methods) res_item = { 'idMovimentoCaixa': sale.id, 'redeId': network['id'], 'rede': network['name'], 'lojaId': branch.id, 'loja': branch.name, 'hora': sale.confirm_date.strftime('%H'), 'cancelado': sale.status == Sale.STATUS_CANCELLED, 'idAtendente': login_user.id, 'codAtendente': login_user.username, 'nomeAtendente': sale.salesperson.person.name, 'vlDesconto': float(sale.discount_value), 'vlAcrescimo': float(sale.surcharge_value), 'vlTotalReceber': float(sale.total_amount), 'vlTotalRecebido': float(self._get_payments_sum(sale_payments[sale.group_id])), 'vlTrocoFormasPagto': change, 'vlServicoRecebido': 0, 'vlRepique': 0, 'vlTaxaEntrega': 0, 'numPessoas': 1, 'operacaoId': sale.id, 'maquinaId': sale.station.id, 'nomeMaquina': sale.station.name, 'maquinaCod': _get_station_code(sale.station), 'maquinaPortaFiscal': None, 'meiosPagamento': payment_methods, 'consumidores': [{ 'documento': raw_document(document), 'tipo': document_type, }], # FIXME B1Food expect this date to be the same as the emission date # we want the emission date of nfe_data for this field # https://gitlab.com/stoqtech/private/stoq-plugin-nfe/-/issues/111 'dataContabil': sale.confirm_date.strftime('%Y-%m-%d %H:%M:%S -0300'), 'periodoId': None, 'periodoCod': None, 'periodoNome': None, 'centroRendaId': None, 'centroRendaCod': None, 'centroRendaNome': None, } response.append(res_item) return response
def get(self, store): data = request.args required_params = ['dtinicio', 'dtfim'] _check_required_params(data, required_params) initial_date = datetime.datetime.strptime(data['dtinicio'], '%Y-%m-%d') end_date = datetime.datetime.combine( datetime.datetime.strptime(data['dtfim'], '%Y-%m-%d').date(), datetime.time.max) request_branches = data.get('lojas') request_documents = data.get('consumidores') request_invoice_keys = data.get('operacaocupom') branch_ids = _parse_request_list(request_branches) _check_if_uuid(branch_ids) documents = _parse_request_list(request_documents) invoice_keys = _parse_request_list(request_invoice_keys) if data.get('usarDtMov') and data.get('usarDtMov') == '1': clauses = [ Sale.confirm_date >= initial_date, Sale.confirm_date <= end_date ] else: clauses = [ Sale.open_date >= initial_date, Sale.open_date <= end_date ] ClientPerson = ClassAlias(Person, 'person_client') ClientIndividual = ClassAlias(Individual, 'individual_client') ClientCompany = ClassAlias(Company, 'company_client') SalesPersonPerson = ClassAlias(Person, 'person_sales_person') SalesPersonIndividual = ClassAlias(Individual, 'individual_sales_person') tables = [ Sale, Join(Branch, Sale.branch_id == Branch.id), LeftJoin(Client, Client.id == Sale.client_id), LeftJoin(Person, Person.id == Client.person_id), Join(BranchStation, Sale.station_id == BranchStation.id), LeftJoin(ClientPerson, Client.person_id == ClientPerson.id), LeftJoin(ClientIndividual, Client.person_id == ClientIndividual.person_id), LeftJoin(Individual, Client.person_id == Individual.person_id), LeftJoin(ClientCompany, Client.person_id == ClientCompany.person_id), LeftJoin(Company, Client.person_id == Company.person_id), LeftJoin(SalesPerson, SalesPerson.id == Sale.salesperson_id), LeftJoin(SalesPersonPerson, SalesPerson.person_id == SalesPersonPerson.id), LeftJoin(SalesPersonIndividual, SalesPerson.person_id == SalesPersonIndividual.person_id), Join(LoginUser, LoginUser.person_id == SalesPerson.person_id), Join(Invoice, Sale.invoice_id == Invoice.id), ] sale_item_tables = [ SaleItem, Join(Sellable, SaleItem.sellable_id == Sellable.id), Join(Product, SaleItem.sellable_id == Product.id), LeftJoin(SellableCategory, Sellable.category_id == SellableCategory.id), LeftJoin(TransactionEntry, SellableCategory.te_id == TransactionEntry.id) ] sale_objs = (Sale, ClientCompany, ClientIndividual, LoginUser, Branch, BranchStation, Client, ClientPerson, SalesPerson, SalesPersonPerson) sale_items_objs = (SaleItem, Sellable, SellableCategory, Product, TransactionEntry) if len(branch_ids) > 0: clauses.append(Branch.id.is_in(branch_ids)) if len(documents) > 0: clauses.append( Or(Individual.cpf.is_in(documents), Company.cnpj.is_in(documents))) if len(invoice_keys) > 0: clauses.append(Invoice.key.is_in(invoice_keys)) if data.get('cancelados') and data.get('cancelados') == '0': clauses.append(Sale.status != Sale.STATUS_CANCELLED) if data.get('cancelados') and data.get('cancelados') == '1': clauses.append(Sale.status == Sale.STATUS_CANCELLED) data = list(store.using(*tables).find(sale_objs, And(*clauses))) sale_ids = [i[0].id for i in data] sale_items = list( store.using(*sale_item_tables).find( sale_items_objs, SaleItem.sale_id.is_in(sale_ids))) sales = {} for item in sale_items: sales.setdefault(item[0].sale_id, []) sales[item[0].sale_id].append(item[0]) response = [] for row in data: sale, company, individual, login_user = row[:4] for item in sales[sale.id]: discount = item.item_discount sellable = item.sellable station = sale.station salesperson = sale.salesperson cpf = individual and individual.cpf cnpj = company and company.cnpj document = cpf or cnpj or '' if cpf: document_type = 'CPF' elif cnpj: document_type = 'CNPJ' else: document_type = '' network = _get_network_info() res_item = { 'idItemVenda': item.id, 'valorUnitario': float(item.base_price), 'valorBruto': float(item.base_price * item.quantity), 'valorUnitarioLiquido': float(item.price), 'valorLiquido': float(item.price * item.quantity), 'idOrigem': None, 'codOrigem': None, 'desconto': float(discount), 'acrescimo': 0, 'maquinaId': station.id, 'nomeMaquina': station.name, 'maquinaCod': _get_station_code(station), 'quantidade': float(item.quantity), 'redeId': network['id'], 'lojaId': sale.branch.id, 'idMaterial': sellable.id, 'codMaterial': _get_sellable_code(sellable), 'descricao': sellable.description, 'grupo': _get_category_info(sellable), 'operacaoId': sale.id, 'atendenteId': login_user.id, 'atendenteCod': login_user.username, 'atendenteNome': salesperson.person.name, 'isTaxa': False, 'isRepique': False, 'isGorjeta': False, 'isEntrega': False, # FIXME maybe should be true if external order 'consumidores': [{ 'documento': raw_document(document), 'tipo': document_type }], 'cancelado': sale.status == Sale.STATUS_CANCELLED, 'dtLancamento': sale.confirm_date.strftime('%Y-%m-%d'), 'horaLancamento': sale.confirm_date.strftime('%H:%M'), 'tipoDescontoId': sale.client_category and sale.client_category.id, 'tipoDescontoCod': _get_client_category_code(sale.client_category), 'tipoDescontoNome': sale.client_category and sale.client_category.name, } response.append(res_item) return response