コード例 #1
0
ファイル: sequence.py プロジェクト: Sorawit123/netforce
 def get_number(self, type=None, name=None, seq_id=None, context={}):
     print_color("WARNING: deprecated method called: sequence.get_number", "red")
     if type:
         res = self.search([["type", "=", type]])
         if not res:
             return None
         seq_id = res[0]
     elif name:
         res = self.search([["name", "=", name]])
         if not res:
             return None
         seq_id = res[0]
     if not seq_id:
         return None
     seq = self.browse([seq_id])[0]
     prefix = self.get_prefix(seq.prefix, context) if seq.prefix else ""
     res = get_model("sequence.running").search([["sequence_id", "=", seq_id], ["prefix", "=", prefix]])
     if res:
         run_id = res[0]
     else:
         vals = {
             "sequence_id": seq_id,
             "prefix": prefix,
         }
         run_id = get_model("sequence.running").create(vals)
     run = get_model("sequence.running").browse([run_id])[0]
     num = run.next
     if seq.padding is None:
         res = "%s%d" % (prefix, num)
     elif seq.padding == 0:
         res = prefix
     else:
         res = "%s%.*d" % (prefix, seq.padding, num)
     return res
コード例 #2
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def get_contacts(self, params={}, context={}):
        contacts=[]
        print_color("Interface Get Contacts %s"%(params), "blue")
        if not params.get("input") : return True
        #search phone
        dom1=[
            ['phone','like',params.get("input")+"%"]
        ]
        res1 = get_model("contact").search(dom1)
        #search name
        dom2=[
            ['name','like',params.get("input")+"%"]
        ]
        res2 = get_model("contact").search(dom2)

        #all search
        all_res = set(res1+res2)
        for contact in get_model("contact").browse(all_res):
            contacts.append({
                'id' : contact.id,
                'name' : contact.name,
                'phone' : contact.phone,
            })
        return  {
            'contacts' : contacts
        }
コード例 #3
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def generals(self, params,context={}):
     print_color("interface.generals.params%s" % params, "yellow")
     company_id = params.get("company_id")
     cashier_id = params.get("cashier_id")
     url = params.get("url")
     cashier_name = None
     if cashier_id:
         cs = get_model("pos.register").browse(int(cashier_id))
         cashier_name = cs.name
     theme = 'blue'
     if company_id:
         for c in get_model("pos.shop").search_browse([['company_id','=',company_id]]):
             theme = c.theme
     st = get_model("settings").browse(1)
     pos_st = get_model("pos.settings").browse(1)
     version=st.version
     menu=[
         {'key': 'current_sale', 'value' : 'Current Sale', 'active' : False},
         {'key': 'retreive_sale', 'value' : 'Retreive Sale', 'active' : False},
         {'key': 'complete_sale', 'value' : 'Complete Sale', 'active' : False},
     ]
     for m in menu:
         if m['key'] == url:
             m['active']=True
     return {
         'version' : version,
         'pos_theme' : pos_st.pos_theme,
         'theme' : theme,
         'dbname': get_active_db(),
         'cashier_name':cashier_name,
         'menu':menu
         }
コード例 #4
0
 def get_number(self, type=None, name=None, seq_id=None, context={}):
     print_color("WARNING: deprecated method called: sequence.get_number", "red")
     if type:
         res = self.search([["type", "=", type]])
         if not res:
             return None
         seq_id = res[0]
     elif name:
         res = self.search([["name", "=", name]])
         if not res:
             return None
         seq_id = res[0]
     if not seq_id:
         return None
     seq = self.browse([seq_id])[0]
     prefix = self.get_prefix(seq.prefix, context) if seq.prefix else ""
     res = get_model("sequence.running").search([["sequence_id", "=", seq_id], ["prefix", "=", prefix]])
     if res:
         run_id = res[0]
     else:
         vals = {
             "sequence_id": seq_id,
             "prefix": prefix,
         }
         run_id = get_model("sequence.running").create(vals)
     run = get_model("sequence.running").browse([run_id])[0]
     num = run.next
     if seq.padding is None:
         res = "%s%d" % (prefix, num)
     elif seq.padding == 0:
         res = prefix
     else:
         res = "%s%.*d" % (prefix, seq.padding, num)
     return res
コード例 #5
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def get_local_sign(self, context={}):
     print_color("get_local_sign", "yellow")
     settings = get_model("settings").browse(1)
     sign = settings.currency_id.sign
     data = {
         'sign': sign or '',
     }
     return data
コード例 #6
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def change_theme(self, params, context={}):
     print_color("interface.change_theme.params%s" % params, "blue")
     color = params.get("color")
     pos_st = get_model("pos.settings").browse(1)
     pos_st.write({
         'pos_theme' : color,
     })
     return True
コード例 #7
0
 def compute_cost(self, ids, context={}):
     print_color("COMPUTING COST...", "green")
     self.compute_cost_standard(context=context)
     self.compute_cost_fifo(context=context)
     self.compute_cost_avg(context=context)
     self.compute_cost_lifo(context=context)
     get_model("field.cache").clear_cache(model="stock.location")
     return {"next": {"name": "stock_board"}, "flash": "Inventory cost updated successfully."}
コード例 #8
0
 def get_product(self, params,context={}):
     print_color("get_product.params%s" % params, "yellow")
     product_id=params.get("product_id")
     prod=get_model('product').browse(product_id)
     item={
         'id': prod.id,
         'name': prod.name,
         'qty': 1,
         'price': prod.sale_price,
     }
     return item
コード例 #9
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def search_customer(self, name, context={}):
     print_color("search_customer", "yellow")
     field_names = []
     res = get_model("contact").search_read([['name', 'ilike', name]], field_names)
     if res:
         contact_id = res[0]['id']
         field_names = ['street', 'sub_district', 'district', 'postal_code', 'city', 'country_id']
         address = get_model("address").search_read([['contact_id', '=', contact_id]], field_names)
         res[0]['address'] = None
         if address:
             res[0]['address'] = address[-1]
     return res
コード例 #10
0
    def get_complete_sale(self, params={}, context={}):
        print_color("Complete Sale params %s"%(params),'blue')
        sale_id = params.get("sale_id")
        check_sale_ids=params.get("check_sale_ids")
        sale_orders=[]
        sale_order=[]
        lines=[]
        customer_name = None
        customer_phone = None
        amount_total = None
        date = time.strftime("%Y-%m-%d")
        dom =[
            ['date','<=',date+' 23:59:59'],
            ['date','>=',date+' 00:00:00'],
            ['state','=','confirmed']
        ]
        for sale in get_model("sale.order").search_browse(dom):
            if check_sale_ids and str(sale.id) in check_sale_ids:
                sale.done()
                continue
            sale_orders.append({
                'sale_id' : sale.id,
                'number' : sale.number,
                'customer_name' : sale.contact_id.name,
                'total' : sale.amount_total
            })
        if sale_id:
            obj = get_model("sale.order").browse(int(sale_id))
            customer_name=obj.contact_id.name
            customer_phone=obj.contact_id.phone
            amount_total=obj.amount_total
            #line in sale
            for line in obj.lines:
                lines.append({
                    'product_name' : line.product_id.name,
                    'qty' : line.qty,
                    'uom' : line.uom_id.name,
                    'unit_price' : line.unit_price,
                    'amount' : line.amount
                })
            sale_order.append({
                'customer' : obj.contact_id.name,
                'lines' : lines,
            })
                

        return  {
            'sale_orders' : sale_orders,
            'sale_order' : lines,
            'customer_name' : customer_name,
            'customer_phone' : customer_phone,
            'amount_total' : amount_total,
        }
コード例 #11
0
 def compute_cost(self, ids, context={}):
     print_color("COMPUTING COST...", "green")
     self.compute_cost_standard(context=context)
     self.compute_cost_fifo(context=context)
     self.compute_cost_avg(context=context)
     self.compute_cost_lifo(context=context)
     get_model("field.cache").clear_cache(model="stock.location")
     return {
         "next": {
             "name": "stock_board",
         },
         "flash": "Inventory cost updated successfully.",
     }
コード例 #12
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def download_products(self, shop_id, context={}):
        print_color("download_products shop_id=%s" % shop_id, "yellow")
        shop_id = shop_id or None
        if not shop_id:
            raise Exception('Missing shop')
        shop_id = int(shop_id)
        shop = get_model("pos.shop").browse([shop_id])[0]
        categ_id = shop.categ_id.id

        if not categ_id:
            raise Exception("Missing product category")
        field_names = ["name", "code", "sale_price"]
        products = get_model("product").search_read([["categs.id", "child_of", categ_id]], field_names)
        return products
コード例 #13
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def download_product_by_register(self, register_id=None, context={}):
        print_color("download_products shop_id=%s" % register_id, "yellow")
        if not register_id:
            raise Exception('Missing Register')
        register_id = int(register_id)
        register = get_model("pos.register").browse([register_id])[0]
        shop_id = register.shop_id.id

        if not shop_id:
            raise Exception('Missing Shop')
        shop = get_model("pos.shop").browse([shop_id])[0]
        categ_id = shop.categ_id.id
        if not categ_id:
            raise Exception("Missing product category")

        field_names = ["name", "code", "sale_price"]
        products = get_model("product").search_read([["categ_id", "child_of", categ_id]], field_names)
        return products
コード例 #14
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def download_shop(self, context={}):
     print_color("download_shop", "yellow")
     field_names = ["name", "registers"]
     shops = get_model("pos.shop").search_read([], field_names)
     reg_obj = get_model('pos.register')
     for shop in shops:
         line = []
         for reg in reg_obj.browse(shop['registers']):
             vals = {
                 'id': reg.id,
                 'name': reg.name,
                 "ask_note": reg.ask_note or False,
                 "print_receipt": reg.print_receipt or False,
                 "print_note_receipt": reg.print_note_receipt or False,
                 "show_discount": reg.show_discount or False,
                 "state": reg.state or '',
             }
             line.append(vals)
         shop['registers'] = line
     return shops
コード例 #15
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def get_settings(self,params={},context={}):
     print_color("Interface Get Settings %s"%(params), "blue")
     db = database.get_connection()
     user_id = get_active_user()
     cashiers = []
     for obj in get_model("pos.register").search_browse([['user_id','=',user_id]]):
         cashiers.append({
             'id' : obj.id,
             'name' : obj.name,
         })
     res = db.query("select * from company")
     comps = []
     for r in res:
         comps.append({
             'id' : r['id'],
             'name' : r['name']
         })
     return {
         'comps' : comps,
         'cashier' : cashiers
     }
コード例 #16
0
    def import_email(self, vals):
        print("import_email from=%s to=%s cc=%s subject=%s" %
              (vals["from_addr"], vals.get("to_addrs"), vals.get("cc_addrs"), vals["subject"]))

        def _check_addr(addrs):
            if not addrs:
                return False
            addr_list = addrs.split(",")
            for addr in addr_list:
                addr = addr.strip()
                res = get_model("base.user").search([["email", "=ilike", addr]])
                if res:
                    return True
                res = get_model("contact").search([["email", "=ilike", addr]])
                if res:
                    return True
                res = get_model("sale.lead").search([["email", "=ilike", addr]])
                if res:
                    return True
            return False
        if not _check_addr(vals["from_addr"]):
            print_color("email ignored: unknown 'from' address: %s" % vals["from_addr"], "red")
            return None
        if not _check_addr(vals.get("to_addrs")) and not _check_addr(vals.get("cc_addrs")):
            print_color("email ignored: unknown 'to' and 'cc' address: to=%s cc=%s" %
                        (vals.get("to_addrs"), vals.get("cc_addrs")), "red")
            return None
        new_id = self.create(vals)
        print_color("email imported: id=%d" % new_id, "green")
        self.link_emails([new_id])
        self.trigger([new_id], "received")
        return new_id
コード例 #17
0
    def get_current_sale(self, params, context={}):
        print('get_current_sale.params ',params)
        print_color("get_current_sale.params%s" % params, "yellow")
        st = get_model("settings").browse(1)
        if params.get("contact_id"):
            contact=get_model("contact").browse(int(params.get("contact_id")))
            contact_name = contact.name
            contact_phone = contact.phone
        else:
            contact_name = st.default_contact_id.name if st.default_contact_id else '' 
            contact_phone = '-'
        ################# < variable > 
        categ_id=params.get("categ_id")
        prod_in_categ=[]
        total_amount=0
        tax_amount=0
        paid_amount=0
        ################# </ variable > 
        sub_total=total_amount
        total_amount=sub_total-tax_amount
        to_pay=total_amount-paid_amount
        ################# < result > 
        if categ_id:
            prod_in_categ=self.get_product_categ(params)
        categs=self.get_categ(params,context)
        ################# </ result > 

        return {
            'product_in_categ':prod_in_categ,
            'total_amount': total_amount,
            'sub_total': sub_total,
            'tax_amount': tax_amount,
            'to_pay': to_pay,
            'categs' : categs,
            'dbname': get_active_db(),
            'all_products': self.get_all_product()['products'],
            'contact_name' : contact_name,
            'contact_phone' : contact_phone,
        }
コード例 #18
0
ファイル: sequence.py プロジェクト: Sorawit123/netforce
 def increment(self, type=None, name=None, seq_id=None, context={}):
     print_color("WARNING: deprecated method called: sequence.increment", "red")
     if type:
         res = self.search([["type", "=", type]])
         if not res:
             return None
         seq_id = res[0]
     elif name:
         res = self.search([["name", "=", name]])
         if not res:
             return None
         seq_id = res[0]
     if not seq_id:
         return None
     seq = self.browse([seq_id])[0]
     prefix = self.get_prefix(seq.prefix, context) if seq.prefix else ""
     res = get_model("sequence.running").search([["sequence_id", "=", seq_id], ["prefix", "=", prefix]])
     if not res:
         raise Exception("Sequence prefix not found")
     run_id = res[0]
     run = get_model("sequence.running").browse([run_id])[0]
     run.write({"next": run.next + 1})
コード例 #19
0
 def increment(self, type=None, name=None, seq_id=None, context={}):
     print_color("WARNING: deprecated method called: sequence.increment", "red")
     if type:
         res = self.search([["type", "=", type]])
         if not res:
             return None
         seq_id = res[0]
     elif name:
         res = self.search([["name", "=", name]])
         if not res:
             return None
         seq_id = res[0]
     if not seq_id:
         return None
     seq = self.browse([seq_id])[0]
     prefix = self.get_prefix(seq.prefix, context) if seq.prefix else ""
     res = get_model("sequence.running").search([["sequence_id", "=", seq_id], ["prefix", "=", prefix]])
     if not res:
         raise Exception("Sequence prefix not found")
     run_id = res[0]
     run = get_model("sequence.running").browse([run_id])[0]
     run.write({"next": run.next + 1})
コード例 #20
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def create_customer(self, mode, vals, context={}):
        print_color("create_customer", "yellow")
        if mode == 'create':
            new_contact_id = get_model('contact').create(vals)
            return new_contact_id
        elif mode == 'write':
            name = vals['name']
            contact_id = get_model("contact").search_read([['name', '=', name]], [])[0]['id']
            contact = get_model("contact").browse(contact_id)

            add_vals = vals['addresses'][0][1]
            del vals['addresses']

            contact.write(vals)
            address_obj = get_model("address").search_read([['contact_id', '=', contact_id]], [])
            # write exist address
            if address_obj:
                address_id = address_obj[0]['id']
                address = get_model("address").browse(address_id)
                address.write(add_vals)
            else:
                add_vals['contact_id'] = contact_id
                address = get_model("address").create(add_vals)
コード例 #21
0
 def pay(self, params, context={}):
     print_color("pay.params%s" % params, "yellow")
     contact_id = params.get("contact_id")
     so ={
         'state' : 'confirmed',
         'contact_id':contact_id,
         'due_date' : time.strftime("%Y-%m-%d"),
         'lines' : []
         }
     items = params.get("items")
     for item in items: 
         prod_id = item['id']
         prod = get_model("product").browse(int(prod_id))
         val={
             'product_id' : prod.id,
             'qty' : item['qty'],
             'uom_id' : prod.uom_id.id,
             'description' : prod.description or '-',
             'unit_price': item['price'] or Decimal(0),
         }
         so['lines'].append(('create',val))
     new_so_id=get_model("sale.order").create(so,context={'action_name':'sale_retail_cash'})
     to_pay = params.get("to_pay")
     return True
コード例 #22
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def get_company(self, shop, context={}):
        print_color("get_company_profile", "yellow")

        # company_id=get_active_company()
        # if not company_id:
        #raise Exception(" company not found.")

        # FIXME
        shop_name = ''
        if shop and shop.get('shopId', None):
            shop_name = shop.get('shopName', '')
            print("Use address of Shop %s " % (shop_name))
            shop_id = int(shop.get('shopId'))
            address = get_model("pos.shop").get_address_str([shop_id])

        # comp=get_model('company').browse(company_id)
        # settings=get_model("settings").browse(1)
        # address=settings.get_address_str()
        data = {
            'name': shop_name,  # comp.name,
            'address': address,
        }

        return data
コード例 #23
0
    def import_email(self, vals):
        print("import_email from=%s to=%s cc=%s subject=%s" %
              (vals["from_addr"], vals.get("to_addrs"), vals.get("cc_addrs"),
               vals["subject"]))

        def _check_addr(addrs):
            if not addrs:
                return False
            addr_list = addrs.split(",")
            for addr in addr_list:
                addr = addr.strip()
                res = get_model("base.user").search([["email", "=ilike",
                                                      addr]])
                if res:
                    return True
                res = get_model("contact").search([["email", "=ilike", addr]])
                if res:
                    return True
                res = get_model("sale.lead").search([["email", "=ilike",
                                                      addr]])
                if res:
                    return True
            return False

        if not _check_addr(vals["from_addr"]):
            print_color(
                "email ignored: unknown 'from' address: %s" %
                vals["from_addr"], "red")
            return None
        if not _check_addr(vals.get("to_addrs")) and not _check_addr(
                vals.get("cc_addrs")):
            print_color(
                "email ignored: unknown 'to' and 'cc' address: to=%s cc=%s" %
                (vals.get("to_addrs"), vals.get("cc_addrs")), "red")
            return None
        new_id = self.create(vals)
        print_color("email imported: id=%d" % new_id, "green")
        self.link_emails([new_id])
        self.trigger([new_id], "received")
        return new_id
コード例 #24
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def download_customer(self, context={}):
     print_color("download_customer", "yellow")
     field_names = ["name"]
     customers = get_model("contact").search_read([], field_names)
     return customers
コード例 #25
0
 def get_retreive_sale(self, params={}, context={}):
     print_color("Retreive Sale params %s"%(params),'blue')
     return  True
コード例 #26
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def close_register(self, ids, context={}):
     print_color("Close register", "yellow")
     reg = get_model("pos.register").browse(ids)
     reg.write({"state": "close"})
コード例 #27
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def open_register(self, ids, context={}):
     print_color("Open register", "yellow")
     reg = get_model("pos.register").browse(ids)
     reg.write({"state": "open"})
コード例 #28
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
 def download_country(self, name, context={}):
     print_color("download_country", "yellow")
     field_names = []
     condition = []
     country = get_model("country").search_read(condition, field_names)
     return country
コード例 #29
0
ファイル: pos_interface.py プロジェクト: anastue/netforce_pos
    def upload_orders(self, orders, context={}):
        setting_obj = get_model("pos.settings")
        setting_ids = setting_obj.search([])
        if not setting_ids:
            raise Exception("Pos Setting not found.")

        # uom=get_model("uom").search_browse([['name','ilike','%Unit%']])
        # if not uom:
            #raise Exception("Unit not found in uom")
        # if not company_id:
            #raise Exception(" company not found.")

        setting = setting_obj.browse(setting_ids)[0]
        ref = setting.sale_ref or 'POS'
        global_account_id = setting.cash_account_id.id

        for order in orders:
            shop_id = order['shop_id']

            if not shop_id:
                raise Exception('Missing shop, ', order)

            shop_id = int(shop_id)
            shop = get_model("pos.shop").browse([shop_id])[0]
            company_id = shop.company_id.id

            if not company_id:
                raise Exception("Missing Company for shop: ", shop.name)

            company_id = None
            if shop.company_id:
                company_id = shop.company_id.id

            shop_account_id = shop.cash_account_id.id or global_account_id
            if not shop_account_id:
                raise Exception("Missing Shop account")

            # warehouse on sale order
            location_id = shop.location_id.id
            if not location_id:
                raise Exception('Missing Location')

            contact_id = order['contact_id']
            if contact_id:
                contact_id = int(contact_id)
            else:
                contact_id = setting.contact_id.id

            print_color("upload_order shop_id=%s contact_id=%s" % (shop_id, contact_id), "yellow")

            is_credit = order.get("is_credit", False)

            vals = {
                "contact_id": contact_id,
                "company_id": company_id,
                "date": order["date"][:10],
                "tax_type": "tax_in",
                "lines": [],
                "state": is_credit and "confirmed" or "done",
                "ref": ref,
                "company_id": company_id,
            }

            for line in order["lines"]:
                prod_id = line["product_id"] or None
                name = line['name']
                qty = line['qty'] or 0
                price = line['unit_price'] or 0
                tax_id = None
                if prod_id:
                    prod = get_model("product").browse(prod_id)
                    prod_id = prod.id
                    name = prod.name
                    uom_id = prod.uom_id.id
                    tax_id = prod.sale_tax_id.id
                line_vals = {
                    "product_id": prod_id,
                    "description": name,
                    "qty": qty,
                    "uom_id": uom_id,
                    "unit_price": price,
                    "tax_id": tax_id,
                    "location_id": location_id,
                }
                print("line_vals ", line_vals)

                vals["lines"].append(("create", line_vals))
            print("sale vals", vals)
            sale_id = get_model("sale.order").create(vals)
            sale = get_model("sale.order").browse(sale_id)

            # starting copy sale to picking
            pick_vals = {
                "type": "out",
                'date': sale.date,
                "company_id": company_id,
                "ref": sale.number,
                "related_id": "sale.order,%s" % sale.id,
                "contact_id": sale.contact_id.id,
                "lines": [],
                "state": "draft",
                "company_id": company_id,
            }

            res = get_model("stock.location").search([["type", "=", "customer"]])
            if not res:
                raise Exception("Customer location not found")
            cust_loc_id = res[0]

            wh_loc_id = sale.location_id.id

            if not wh_loc_id:
                res = get_model("stock.location").search([["type", "=", "internal"]])
                if not res:
                    raise Exception("Warehouse not found")
                wh_loc_id = res[0]

            for line in sale.lines:
                prod = line.product_id
                if prod.type not in ("stock", "consumable"):
                    continue
                qty_remain = line.qty - line.qty_delivered
                if qty_remain < 0.001:
                    continue
                line_vals = {
                    "product_id": prod.id,
                    "qty": qty_remain,
                    #"unit_price": line.unit_price or 0,
                    "uom_id": line.uom_id.id,
                    "location_from_id": wh_loc_id,
                    "location_to_id": cust_loc_id,
                }
                pick_vals["lines"].append(("create", line_vals))

            if pick_vals["lines"]:
                pick_id = get_model("stock.picking").create(pick_vals, context={"pick_type": "out"})
                pick = get_model("stock.picking").browse(pick_id)
                pick.set_done([pick_id])

                print("pick_id", pick_id)

            # starting copy sale to invoice
            # inv_id=sale.copy_to_invoice()["invoice_id"]
            inv_vals = {
                "type": "out",
                "inv_type": "invoice",
                "tax_type": sale.tax_type,
                "ref": sale.number,
                "related_id": "sale.order,%s" % sale.id,
                "contact_id": sale.contact_id.id,
                "currency_id": sale.currency_id.id,
                "company_id": company_id,
                "lines": [],
                "company_id": company_id,
            }
            for line in sale.lines:
                prod = line.product_id
                remain_qty = line.qty - line.qty_invoiced
                if remain_qty < 0.001:
                    print("remain_qty < 0.001")
                    continue
                # XXX Skip Discount
                # if not prod.id:
                    # continue
                line_vals = {
                    "product_id": prod.id,
                    "description": line.description,
                    "qty": remain_qty,
                    "uom_id": line.uom_id.id,
                    "unit_price": line.unit_price,
                    "amount": remain_qty * line.unit_price,
                    #"account_id": prod and prod.sale_account_id.id or shop__account_id, # FIXME find discount account
                    "tax_id": line.tax_id.id,
                }

                if prod.id:
                    line_vals['account_id'] = prod.sale_account_id.id or shop_account_id
                if line.description == "Discount":
                    if not shop.disc_account_id.id:
                        raise Exception("No discount account!")
                    line_vals['account_id'] = shop.disc_account_id.id

                inv_vals["lines"].append(("create", line_vals))
            inv_id = get_model("account.invoice").create(inv_vals, {"type": "out", "inv_type": "invoice"})
            inv = get_model("account.invoice").browse(inv_id)
            inv.write({"due_date": sale.date})  # FIXME should be sale date. Not close register date
            if not is_credit:
                # inv.write({"due_date":inv.date})
                get_model("account.invoice").approve([inv_id])
                # create payment
                vals = {
                    "contact_id": contact_id,
                    "company_id": company_id,
                    "type": "in",
                    "pay_type": "invoice",
                    "date": inv.date,
                    "account_id": shop_account_id,
                    "lines": [("create", {
                        "invoice_id": inv_id,
                        "amount": inv.amount_due or 0,
                    })]
                }
                print("payment vals ", vals)
                pmt_id = get_model("account.payment").create(vals, context={"type": "in"})
                get_model("account.payment").post([pmt_id])
            else:
                inv.write({"state": 'waiting_payment'})