import time

from netforce.model import Model, fields, get_model
from netforce.access import get_active_user, set_active_user, get_active_company
from netforce.utils import get_data_path, get_file_path
from . import utils

class Shop(Model):
    _name="clinic.shop"
    _string="Shop"
    _name_field="number"
    _multi_company=True
    
    def _get_all(self,ids,context={}):
        res={}
        for obj in self.browse(ids):
            sub_total=0
            tax_amount=0
            for line in obj.lines:
                amt=line.amount or 0
                sub_total+=amt
            total=sub_total
            total=total-tax_amount
            for pm in obj.payments:
                total-=pm.amount_payment
            res[obj.id]={
                'sub_total': sub_total,
                'tax_amount': tax_amount,
                'total': total,
                'due_amount': total,
            }
        return res

    _fields={
        "number": fields.Char("Number",required=True,search=True),
        "ref": fields.Char("Customer Name",search=True),
        'date': fields.Date("Date",search=True),
        'due_date': fields.Date("Due Date",search=True),
        'patient_id': fields.Many2One('clinic.patient','Patient',search=True,domain=[['state','=','admit']]),
        'contact_id': fields.Many2One('partner','Contact',search=True),
        'department_id': fields.Many2One("clinic.department","Department",search=True),
        'branch_id': fields.Many2One("clinic.branch","Branch",search=True),
        'lines': fields.One2Many('clinic.shop.line','shop_id','Lines'),
        'sub_total': fields.Float("Subtotal",function="_get_all",function_multi=True),
        'total': fields.Float("Total",function="_get_all",function_multi=True),
        'due_amount': fields.Float("Due Amount",function="_get_all",function_multi=True),
        'tax_amount': fields.Float("Tax Amount",function="_get_all",function_multi=True),
        'user_id': fields.Many2One("base.user","Sale Man"),
        'state': fields.Selection([['draft','Draft'],['waiting_payment','Waiting Payment'],['paid','Paid'],['cancelled','Cancelled']],'State'),
        "pickings": fields.One2Many("stock.picking","related_id","Pickings"),
        "invoices": fields.One2Many("account.invoice","related_id","Invoices"),
        "payments": fields.One2Many("account.payment","related_id","Payments"),
        'dom_str': fields.Char("Dom Str"),
        "related_id": fields.Reference([["sale.order","Sales Order"],["purchase.order","Purchase Order"],["project","Project"],["job","Service Order"],["service.contract","Service Contract"]],"Related To"),
        'company_id': fields.Many2One("company","Company"),
        "pay_type": fields.Selection([("cash","Cash"),("credit","Credit")],"Pay Type"),
        "pay_by": fields.Selection([("cash","Cash"),("cheque","Cheque")],"Pay By"),
        'pay_date': fields.Date("Pay Date"),
        'bank_name': fields.Char("Bank"),
        'bank_branch': fields.Char("Bank Branch"),
        'cheque_no': fields.Char("Cheque No."),
        'hd_case_call': fields.Boolean("HD Case Call"),
        'note': fields.Text("Note"),
        "payment_lines": fields.One2Many("clinic.shop.payment","shop_id","Payment Lines"),
    }
    
    _order="date desc"

    def _get_related(self,context={}):
        related_id=None 
        if context.get('refer_id'):
            related_id="clinic.hd.case,%s"%context.get("refer_id")
        return related_id

    def _get_patient(self,context={}):
        patient_id=None 
        if context.get('refer_id'):
            refer_id=context.get("refer_id")
            hd_case=get_model("clinic.hd.case").browse(refer_id)
            patient_id=hd_case.patient_id.id
        return patient_id

    def _get_contact(self,context={}):
        partner_id=None 
        if context.get('refer_id'):
            refer_id=context.get("refer_id")
            hd_case=get_model("clinic.hd.case").browse(refer_id)
            patient=hd_case.patient_id
            partner=patient.partner_id
            partner_id=partner.id
        return partner_id

    def _get_hdcase_call(self,context={}):
        res=False
        if context.get('hd_case_call'):
            res=True
        return res

    def _get_number(self,context={}):
        while 1:
            seq_id=get_model("sequence").find_sequence(type="clinic_rdshop",context=context)
            num=get_model("sequence").get_next_number(seq_id,context=context)
            if not num:
                return None
            user_id=get_active_user()
            set_active_user(1)
            res=self.search([["number","=",num]])
            set_active_user(user_id)
            if not res:
                return num
            get_model("sequence").increment_number(seq_id,context=context)

    def _get_credit_number(self,context={}):
        while 1:
            seq_id=get_model("sequence").find_sequence(type="clinic_rdshop_credit",context=context)
            num=get_model("sequence").get_next_number(seq_id,context=context)
            if not num:
                return None
            user_id=get_active_user()
            set_active_user(1)
            res=get_model("account.invoice").search([["number","=",num]])
            set_active_user(user_id)
            if not res:
                return num
            get_model("sequence").increment_number(seq_id,context=context)

    def _get_cash_number(self,context={}):
        while 1:
            seq_id=get_model("sequence").find_sequence(type="clinic_rdshop_cash",context=context)
            num=get_model("sequence").get_next_number(seq_id,context=context)
            if not num:
                return None
            user_id=get_active_user()
            set_active_user(1)
            res=get_model("account.payment").search([["number","=",num]])
            set_active_user(user_id)
            if not res:
                return num
            get_model("sequence").increment_number(seq_id,context=context)

    def _get_branch(self,context={}):
        res=get_model('select.company').get_select()
        if res:
            return res['branch_id']

    def _get_department(self,context={}):
        res=get_model('select.company').get_select()
        if res:
            if res.get("department_ids"):
                return res['department_ids'][0]
            else:
                return res['department_id']

    _defaults={
        'number': '/',
        'date': lambda *a: time.strftime("%Y-%m-%d"),
        'due_date': lambda *a: time.strftime("%Y-%m-%d"),
        'user_id': lambda *a: get_active_user(),
        'company_id': lambda *a: get_active_company(),
        'branch_id': _get_branch,
        'department_id': _get_department,
        'state': 'draft',
        'related_id': _get_related,
        'patient_id': _get_patient,
        'contact_id': _get_contact,
        'pay_type': 'cash',
        'hd_case_call': _get_hdcase_call,
    }
    
    def update_all(self,context={}):
        data=context['data']
        data['total']=0
        for line in data['lines']:
            data['total']+=line['amount'] or 0
        return data
    
    def onchange_line(self,context={}):
        data=context['data']
        path=context['path']
        line=get_data_path(data,path,parent=True)
        line['amount']=(line['qty'] or 0)*(line['price'] or 0)
        data=self.update_all(context=context)
        return data

    def onchange_product(self,context={}):
        data=context['data']
        path=context['path']
        line=get_data_path(data,path,parent=True)
        prod_id=line['product_id']
        prod=get_model('product').browse(prod_id)
        line['uom_id']=prod.uom_id.id
        line['description']=prod.name or ''
        line['price']=prod.sale_price or 0
        if not line.get('qty'):
            line['qty']=1
        line['amount']=line['price']*line['qty']
        data=self.update_all(context)
        return data
    
    def onchange_categ(self,context={}):
        data=context['data']
        path=context['path']
        line=get_data_path(data,path,parent=True)
        line['product_id']=None
        return data
    
    def onchange_patient(self,context={}):
        data=context['data']
        patient_id=data['patient_id']
        patient=get_model("clinic.patient").browse(patient_id)
        dpt=patient.department_id
        branch=patient.branch_id
        contact=patient.partner_id
        data['department_id']=dpt.id
        data['branch_id']=branch.id
        data['contact_id']=contact.id
        return data

    def onchange_contact(self,context={}):
        data=context['data']
        contact_id=data['contact_id']
        data['patient_id']=None
        #data['department_id']=None
        #data['branch_id']=None
        for patient in get_model("clinic.patient").search_browse([['partner_id','=',contact_id]]):
            dpt=patient.department_id
            branch=patient.branch_id
            data['department_id']=dpt.id
            data['branch_id']=branch.id
            data['patient_id']=patient.id
        return data

    def create(self,vals,**kw):
        id=super().create(vals,**kw)
        self.function_store([id])
        return id

    def write(self,ids,vals,**kw):
        super().write(ids,vals,**kw)
        self.function_store(ids)
    
    def pay_credit(self,ids,context={}):
        obj=self.browse(ids)[0]
        active_id=obj.id
        action="clinic_shop"
        if obj.hd_case_call:
            active_id=obj.related_id.id
            action="clinic_hd_case"
        st=get_model("clinic.setting").browse(1)
        if not st.shop_type_id:
            raise Exception("Please defind Shop Type on menu Clinic Settings -> RD Shop")
        if obj.number=="/":
            context['branch_id']=obj.branch_id.id
            obj.write({
                'number': self._get_number(context=context),
            })
        obj.make_invoices()
        return {
            'next': {
                'name': action,
                'mode': 'form',
                'active_id': active_id,
            },
            'flash': 'Pay Successfully',
        }
    
    def pay_cash(self,ids,context={}):
        obj=self.browse(ids)[0]
        active_id=obj.id
        action="clinic_shop"
        if obj.hd_case_call:
            active_id=obj.related_id.id
            action="clinic_hd_case"
        st=get_model("clinic.setting").browse(1)
        if not st.shop_type_id:
            raise Exception("Please defind Shop Type on menu Clinic Settings -> RD Shop")
        if obj.number=="/":
            obj.write({
                'number': self._get_number(),
            })
        obj.make_payment()
        return {
            'next': {
                'name': action,
                'mode': 'form',
                'active_id': active_id,
            },
            'flash': 'Pay Successfully',
        }

    def make_invoices(self,ids,context={}):
        setting=get_model("settings").browse(1,context)
        cst=get_model("clinic.setting").browse(1)
        shop_type=cst.shop_type_id
        currency_id=setting.currency_id.id
        if not currency_id:
            raise Exception("Currency not found in account settings")
        company_id=get_active_company()
        uom=get_model("uom").search_browse([['name','ilike','%Unit%']])
        if not uom:
            raise Exception("Unit not found in uom")
        obj=self.browse(ids[0])
        if obj.invoices:
            for inv in obj.invoices:
                inv.void()
        context['type']='out'
        context['inv_type']='invoice'
        context['branch_id']=obj.branch_id.id
        cst=get_model('clinic.setting').browse(1)
        prod_acc=cst.get_product_account
        partner=obj.contact_id
        context['branch_id']=obj.branch_id.id
        track_id=obj.branch_id.track_id.id
        inv_lines=[]
        for line in obj.lines:
            if line.amount < 1:
                continue
            prod=line.product_id
            acc=prod_acc(prod.id,shop_type.id,'credit')
            account_id=acc.get("ar_credit_id",None)
            ar_debit_id=acc.get("ar_debit_id",None)
            if not account_id:
                raise Exception("No Income Credit Account for product [%s] %s"%(prod.code, prod.name))
            if not ar_debit_id:
                raise Exception("No Ar Debit Account for product [%s] %s"%(prod.code, prod.name))
            inv_lines.append(('create',{
                    "product_id": prod.id,
                    "description": line.description or "",
                    "qty": line.qty,
                    "uom_id": line.uom_id.id,
                    "unit_price": line.price or 0,
                    "amount": line.amount or 0,
                    'account_id': account_id,
                    'ar_debit_id': ar_debit_id,
                    'track_id': track_id,
                }))
        def group_invoice_line(invoice_lines):
            invoice_vals={}
            for mode,invoice_line in invoice_lines:
                ar_debit_id=invoice_line['ar_debit_id']
                if not invoice_vals.get(ar_debit_id):
                    invoice_vals[ar_debit_id]=[]
                del invoice_line['ar_debit_id']
                invoice_vals[ar_debit_id].append((mode,invoice_line))
            return invoice_vals
        invoices=group_invoice_line(inv_lines)
        for account_receiveable_id, lines in invoices.items():
            context['date']=obj.date
            number=self._get_credit_number(context=context),
            vals={
                'number': number,
                "type": "out",
                "inv_type": "invoice",
                "tax_type": "tax_in",
                'due_date': obj.due_date,
                "ref": obj.number or "",
                'department_id': obj.department_id.id,
                "related_id": "clinic.shop,%s"%obj.id,
                "currency_id": currency_id,
                "company_id": company_id,
                'patient_partner_id':partner.id, #to check before post
                'partner_id': partner.id,
                "lines": lines,
                'account_id': account_receiveable_id,
            }
            inv_id=get_model("account.invoice").create(vals,context=context)
            inv=get_model("account.invoice").browse(inv_id)
            inv.post()
        obj.make_pickings()
        obj.write({
            'state': 'waiting_payment',
            'pay_type': 'credit',
        })
    
    def make_pickings(self,ids,context={}):
        obj=self.browse(ids[0])
        partner=obj.contact_id
        # no picking
        if not obj.lines:
            return
        ship_address_id=None
        for address in partner.addresses:
            if address.type=="shipping":
                ship_address_id=address.id
                break
        if not ship_address_id:
            raise Exception("No shipping address for contact %s"%partner.name)

        # default journal
        cust_loc_id=None
        wh_loc_id=None
        # find location
        # 1. from department -> branch -> stock journal -> from, to
        department=obj.department_id
        if department:
            stock_journal=department.pick_out_journal_id
            if stock_journal:
                wh_loc_id=stock_journal.location_from_id.id
                cust_loc_id=stock_journal.location_to_id.id
        pick_vals={
            "type": "out",
            'journal_id': stock_journal.id,
            "ref": obj.number,
            "related_id": "clinic.shop,%s"%obj.id,
            "partner_id": partner.id,
            "ship_address_id": ship_address_id,
            "state": "draft",
            "lines": [],
        }

        if not cust_loc_id:
            res=get_model("stock.location").search([["type","=","customer"]])
            if not res:
                raise Exception("Customer location not found!")
            cust_loc_id=res[0]
        for line in obj.lines:
            if line.qty < 1:
                continue
            prod=line.product_id
            if prod.type != 'stock':
                continue
            if not wh_loc_id:
                wh_loc_id=prod.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]
            line_vals={
                "product_id": prod.id,
                "qty": line.qty,
                "uom_id": prod.uom_id.id,
                "location_from_id": wh_loc_id,
                "location_to_id": cust_loc_id,
            }
            #XXX whare house in profile product
            if prod.location_id:
                line_vals['location_from_id']=prod.location_id.id
            pick_vals["lines"].append(("create",line_vals))
        if not pick_vals["lines"]:
            return {
                "flash": "Nothing left to deliver",
            }
        picking_obj=get_model("stock.picking")
        context={
            'pick_type': 'out',
            'journal_id': pick_vals['journal_id'],
            'branch_id': obj.branch_id.id,
            'date': obj.date,
        }
        pick_id=picking_obj.create(pick_vals,context=context)
        pick=picking_obj.browse(pick_id)
        pick.set_done([pick_id])

    def make_payment(self,ids,context={}):
        obj=self.browse(ids)[0]
        partner=obj.contact_id
        cst=get_model('clinic.setting').browse(1)
        shop_type=cst.shop_type_id
        cash_account_id=cst.cash_account_id.id
        income_account_id=cst.income_account_id.id
        if not cash_account_id:
            raise Exception("No Cash Account")
        if not income_account_id:
            raise Exception("No Income Account")
        company_id=get_active_company()
        context['branch_id']=obj.branch_id.id
        context['date']=obj.date
        number=self._get_cash_number(context=context),
        vals={
            'number': number,
            "partner_id": partner.id,
            "company_id": company_id,
            "type": "in",
            "pay_type": "direct",
            'date': time.strftime("%Y-%m-%d"),
            "account_id": cash_account_id,
            'related_id': "clinic.shop,%s"%obj.id,
            'ref': obj.number,
            'direct_lines': [],
        }
        prod_acc=cst.get_product_account
        track_id=obj.branch_id.track_id.id
        for line in obj.lines:
            prod=line.product_id
            acc=prod_acc(prod.id,shop_type.id,'cash')
            account_id=acc.get("ar_credit_id",None)
            ar_debit_id=acc.get("ar_debit_id",None)
            if not account_id:
                raise Exception("No Income Credit Account for product [%s] %s"%(prod.code, prod.name))
            if not ar_debit_id:
                raise Exception("No Ar Debit Account for product [%s] %s"%(prod.code, prod.name))
            desc="[%s] %s"%(prod.code, line.description or "")
            vals['direct_lines'].append(('create',{
                    "description": desc,
                    "qty": line.qty,
                    "unit_price": line.price or 0,
                    "amount": line.amount or 0,
                    'account_id': account_id,
                    'track_id': track_id,
                }))

        context={
            'type': 'in',
            'branch_id': obj.branch_id.id,
            'date': obj.date,
        }
        payment_id=get_model("account.payment").create(vals,context=context)
        payment=get_model('account.payment').browse(payment_id)
        payment.post()
        obj.make_pickings()
        obj.write({
            'state': 'paid',
            'pay_type': 'cash',
            'payment_lines': [('create',{
                        'payment_id': payment_id,
                        'amount': payment.amount_payment,
                    })],
        })
    
    def to_draft(self,ids,context={}):
        for obj in self.browse(ids):
            for payment in obj.payments:
                payment.to_draft()
                payment.delete()
            for inv in obj.invoices:
                inv.write({
                    'state': 'draft',
                })
                if inv.move_id:
                    inv.move_id.to_draft()
                    inv.move_id.delete()
                inv.delete()
            for picking in obj.pickings:
                picking.to_draft(context=context)
                picking.delete()
            for pm_line in obj.payment_lines:
                pm_line.delete()
            obj.write({
                'state': 'draft',
            })
        if obj:
            return {
                'next': {
                    'name': {
                        'next': 'clinic_shop',
                        'mode': 'form',
                        'active_id': obj.id,
                    },
                    'flash': '%s has been set to draft'%obj.number or "",
                }
            }

    def view_payment(self,ids,context={}):
        return {
            'next': {
                'name': 'payment',
                'mode': 'form',
                'active_id': ids[0],
            },
        }

    def get_invoice_page(self,context={}):
        if not context.get('refer_id'):
            return {}
        shop_id=int(context['refer_id'])
        shop=self.browse(shop_id)
        comp_id=get_active_company()
        comp=get_model('company').browse(comp_id)
        context['branch_id']=shop.branch_id.id
        st=get_model('settings').browse(1,context=context)
        cst=get_model('clinic.setting').browse(1)
        cust=shop.contact_id
        cust_tax_no=cust.tax_no or ''
        cust_name=cust.name or ''
        cust_addr=''
        if cust.addresses:
            cust_addr=cust.addresses[0].address_text
        if 'your' in cust_addr:
            cust_addr=''
        
        if cust.walkin_cust:
            cust_name=shop.ref or ''
        no=1
        sub_total=0
        amount_total=0
        lines=[]
        for line in shop.lines:
            amt=line.amount or 0
            prod=line.product_id
            lines.append({
                'no': no,
                'product_name': prod.name or '',
                'description': line.description or '',
                'uom_name': line.uom_id.name or '',
                'qty': line.qty or 0,
                'price': line.price or 0,
                'amount': amt,
            })
            sub_total+=amt
            no+=1
        amount_total=sub_total #XXX
        is_draft=shop.state=='draft' and True or False 
        is_cheque=False
        pay_type=shop.pay_type or ''
        user_id=get_active_user()
        user=get_model("base.user").browse(user_id)
        comp_name=comp.name or ""
        if st.default_address_id.company:
            comp_name=st.default_address_id.company or ""
        number="/"
        ref=""
        payment_terms=''
        currency_code=''
        due_date=shop.due_date
        for inv in shop.invoices:
            number=inv.number or ""
            ref=shop.number or ""
            payment_terms=inv.payment_terms or ""
            currency_code=inv.currency_id.code or ""
            due_date=inv.due_date
        add=st.default_address_id
        data={
            'partner_name': cust_name,
            'partner_address': cust_addr,
            'partner_tax_no': cust_tax_no,
            'due_date': due_date,
            'currency_code': currency_code,
            'payment_terms': payment_terms,
            'comp_name': comp_name,
            'add_address': add.address or '',
            'add_address2': add.address2 or '',
            'add_province_name': add.province_id.name or '',
            'add_district_name': add.district_id.name or '',
            'add_subdistrict_name': add.subdistrict_id.name or '',
            'add_city': add.city or '',
            'add_postal_code': add.postal_code or '',
            'add_phone': add.phone or '',
            'add_fax': add.fax or '',
            'tax_no': st.tax_no or '',
            'number': number,
            'ref': ref,
            'date': shop.date,
            'datenow': shop.date or time.strftime("%d/%m/%Y"),
            'dateprint': shop.date or time.strftime("%d/%m/%Y %H:%M:%S"),
            'note': shop.note or '',
            'lines':lines,
            'amount_subtotal': sub_total,
            'amount_total': amount_total,
            'total_text': utils.num2word(amount_total),
            'is_cheque': is_cheque,
            'is_draft': is_draft,
            'user_name': user.name or "",
            'state': shop.state or "",
        }
        blank_dot=''
        if pay_type=='cash':
            data['pay_type']='Cash'
            if shop.cheque_no:
                data['is_cheque']=True
                data['bank_name']=shop.bank_name or blank_dot
                data['branch_name']=shop.branch_name or blank_dot
                data['cheque_no']=shop.cheque_no or blank_dot
                data['cheque_date']=shop.pay_date or blank_dot
        else:
            data['pay_type']='Credit'
        if st.logo:
            data['logo']=get_file_path(st.logo)
        if cst.signature:
            data['signature']=get_file_path(cst.signature)
        return data

    def get_receipt_page(self,context={}):
        if not context.get('refer_id'):
            return {}
        shop_id=int(context['refer_id'])
        shop=self.browse(shop_id)
        comp_id=get_active_company()
        comp=get_model('company').browse(comp_id)
        context['branch_id']=shop.branch_id.id
        st=get_model('settings').browse(1,context=context)
        cst=get_model('clinic.setting').browse(1)
        cust=shop.contact_id
        cust_name=cust.name or ''
        cust_addr=''
        if cust.addresses:
            cust_addr=cust.addresses[0].address_text
        if 'your' in cust_addr:
            cust_addr=''
        
        if cust.walkin_cust:
            cust_name=shop.ref or ''
        no=1
        sub_total=0
        amount_total=0
        lines=[]
        for line in shop.lines:
            amt=line.amount or 0
            prod=line.product_id
            lines.append({
                'no': no,
                'product_name': prod.name or '',
                'description': line.description or '',
                'uom_name': line.uom_id.name or '',
                'qty': line.qty or 0,
                'price': line.price or 0,
                'amount': amt,
            })
            sub_total+=amt
            no+=1
        amount_total=sub_total #XXX
        is_draft=shop.state=='draft' and True or False 
        is_cheque=False
        pay_type=shop.pay_type or ''
        user_id=get_active_user()
        user=get_model("base.user").browse(user_id)
        comp_name=comp.name or ""
        if st.default_address_id.company:
            comp_name=st.default_address_id.company or ""
        number="/"
        ref=""
        for pm in shop.payments:
            number=pm.number or ""
            ref=shop.number or ""
        add=st.default_address_id
        data={
            'comp_name': comp_name,
            'add_address': add.address or '',
            'add_address2': add.address2 or '',
            'add_province_name': add.province_id.name or '',
            'add_district_name': add.district_id.name or '',
            'add_subdistrict_name': add.subdistrict_id.name or '',
            'add_city': add.city or '',
            'add_postal_code': add.postal_code or '',
            'add_phone': add.phone or '',
            'add_fax': add.fax or '',
            'tax_no': st.tax_no or '',
            'number': number,
            'ref': ref,
            'date': shop.date,
            'datenow': shop.date or time.strftime("%d/%m/%Y"),
            'dateprint': shop.date or time.strftime("%d/%m/%Y %H:%M:%S"),
            'cust_name': cust_name,
            'cust_addr': cust_addr,
            'note': shop.note or '',
            'lines':lines,
            'amount_subtotal': sub_total,
            'amount_total': amount_total,
            'total_text': utils.num2word(amount_total),
            'is_cheque': is_cheque,
            'is_draft': is_draft,
            'user_name': user.name or "",
            'state': shop.state or "",
        }
        blank_dot=''
        if pay_type=='cash':
            data['pay_type']='Cash'
            if shop.cheque_no:
                data['is_cheque']=True
                data['bank_name']=shop.bank_name or blank_dot
                data['branch_name']=shop.branch_name or blank_dot
                data['cheque_no']=shop.cheque_no or blank_dot
                data['cheque_date']=shop.pay_date or blank_dot
        else:
            data['pay_type']='Credit'
        if st.logo:
            data['logo']=get_file_path(st.logo)
        if cst.signature:
            data['signature']=get_file_path(cst.signature)
        return data

    def is_pay_by_cheque(self,ids,context={}):
        obj=self.browse(ids)[0]
        res=obj.pay_type or obj.pay_by or obj.pay_date or obj.bank_name  or obj.bank_branch or False
        return res

    def get_receipt_data(self,ids,context={}):
        settings=get_model('settings').browse(1)
        pages=[]
        for obj in get_model('clinic.shop').browse(ids):
            context['refer_id']=obj.id
            data=get_model('clinic.shop').get_receipt_page(context=context)
            limit_item=13
            if obj.is_pay_by_cheque(context=context):
                limit_item-=1
            if data['state']=='draft':
                limit_item-=3
            for i in  range(len(data['lines']),limit_item):
                data['lines'].append({
                    'no': '',
                    'product_name': '',
                    'description': '',
                    'uom_name': '',
                    'qty': None,
                    'price': None,
                    'amount': None,
                })
            pages.append(data)
        if pages:
            pages[-1]["is_last_page"]=True
        return {
            "pages": pages,
            "logo": get_file_path(settings.logo),
        }

    def get_invoice_data(self,ids,context={}):
        settings=get_model('settings').browse(1)
        pages=[]
        for obj in get_model('clinic.shop').browse(ids):
            context['refer_id']=obj.id
            data=get_model('clinic.shop').get_invoice_page(context=context)
            limit_item=13
            if obj.is_pay_by_cheque(context=context):
                limit_item-=1
            if data['state']=='draft':
                limit_item-=3
            for i in  range(len(data['lines']),limit_item):
                data['lines'].append({
                    'no': '',
                    'product_name': '',
                    'description': '',
                    'uom_name': '',
                    'qty': None,
                    'price': None,
                    'amount': None,
                })
            pages.append(data)
        if pages:
            pages[-1]["is_last_page"]=True
        return {
            "pages": pages,
            "logo": get_file_path(settings.logo),
        }
    
    def pay(self,ids,context={}):
        res={}
        obj=self.browse(ids)[0]
        if not obj.lines:
            raise Exception("No item")
        res=obj.pay_cash()
        return res

    def approve(self,ids,context={}):
        res={}
        obj=self.browse(ids)[0]
        if not obj.lines:
            raise Exception("No item")
        res=obj.pay_credit()
        return res

    def onchange_branch(self,context={}):
        data=context['data']
        data['department_id']=None
        return data

    def void(self,ids,context={}):
        for obj in self.browse(ids):
            obj.write({
                'state': 'cancelled',
            })
    
    def get_shop_data(self,context={}):
        records=[]
        dom=[
            ['date','>=',context['date_from']],
            ['date','<=',context['date_to']],
            ['state','not in',['draft','cancelled']],
        ]
        product_id=context.get('product_id')
        if product_id:
            dom.append([
                'product_id','=',product_id,
            ])
        branch_id=context.get('branch_id')
        if branch_id:
            dom.append([
                'branch_id','=',branch_id,
            ])
        department_id=context.get('department_id')
        if department_id:
            dom.append([
                'department_id','=',department_id,
            ])
        for shop in get_model("clinic.shop").search_browse(dom):
            patient=shop.patient_id
            pm_id=None
            pm_number=""
            for pm in shop.payments:
                pm_id=pm.id
                pm_number=pm.number
            inv_id=None
            inv_number=""
            inv_ref=""
            for inv in shop.invoices:
                inv_id=inv.id
                inv_number=inv.number
                inv_ref=inv.ref
            pick_id=None
            pick_number=''
            for pick in shop.pickings:
                pick_id=pick.id
                pick_number=pick.number
            st=get_model('clinic.setting').browse(1)
            ct_ids=[]
            for ct in st.product_categ_view:
                ct_ids.append(ct.id)
            for line in shop.lines:
                prod=line.product_id
                categ=line.categ_id
                amount=line.amount or 0
                mdc=0
                lab=0
                misc=0
                fee=0
                dlz=0
                mdc_names=[]
                #if categ.parent_id:
                    #if categ.parent_id.code=='MDC': #XXX
                if categ:
                    if categ.id in ct_ids:
                        mdc+=amount
                        name=prod.name or ""
                        name=name.split("-")
                        name=name[0].title()
                        mdc_names.append(name)
                    else:
                        misc+=amount
                    continue
                if categ.code=='DLZ':
                    dlz+=amount
                elif categ.code=='FEE':
                    fee+=amount
                elif categ.code=='LAB':
                    lab+=amount
                else:
                    misc+=amount
            vals={
                'is_shop': True,
                'hdcase_id': None,
                'date':  shop.date,
                'pay_type': shop.ptype,
                'epo_name': "",
                'ptype_color': "warning",
                'dname': "",
                'pname': patient.name or "",
                'hn': patient.hn or "",
                'idcard': patient.card_no or "",
                'pm_id': pm_id,
                'pm_number': pm_number,
                'inv_number': inv_number,
                'inv_id': inv_number,
                'inv_ref': inv_ref,
                'inv_id': inv_id,
                'fee': fee,
                'mdc': mdc,
                'mdc_name': ','.join([n for n in mdc_names]),
                'dlz_name': "",
                'dlz_id': "",
                'dlz': dlz,
                'lab': lab,
                'misc': misc,
                'pick_ref': pick_number,
                'pick_id': pick_id,
            }
            records.append(vals)
        data={
            'records': records,
        }
        print('total records: ',len(records))
        return data

Shop.register()