'RESTful CRUD controller for inv_send'

@classmethod
def inv_send_controller(cls):

    T = current.T
    db = current.db
    s3db = current.s3db
    sendtable = s3db.inv_send
    tracktable = s3db.inv_track_item
    iitable = s3db.inv_inv_item
    request = current.request
    response = current.response
    s3 = response.s3
    error_msg = T('You    do    not    have    permission    for    any    facility    to    send    a    shipment.')
    current.auth.permitted_facilities(table=sendtable, error_msg=error_msg)
    vars = request.vars
    send_inv_item_id = vars.send_inv_item_id
    if send_inv_item_id:
        if (not vars.item_pack_id):
            vars.item_pack_id = db((iitable.id == send_inv_item_id)).select(iitable.item_pack_id, limitby=(0, 1)).first().item_pack_id
        tracktable.quantity.requires = QUANTITY_INV_ITEM(db, send_inv_item_id, vars.item_pack_id)
    def set_send_attr(status):
        sendtable.send_ref.writable = False
        if (status == SHIP_STATUS_IN_PROCESS):
            sendtable.send_ref.readable = False
        else:
            for field in sendtable.fields:
                sendtable[field].writable = False
    def set_track_attr(status):
        for field in tracktable.fields:
            tracktable[field].writable = False
        tracktable.send_id.readable = False
        tracktable.recv_id.readable = False
        tracktable.bin.readable = False
        tracktable.item_id.readable = False
        tracktable.recv_quantity.readable = False
        tracktable.return_quantity.readable = False
        tracktable.expiry_date.readable = False
        tracktable.owner_org_id.readable = False
        tracktable.supply_org_id.readable = False
        tracktable.adj_item_id.readable = False
        if (status == TRACK_STATUS_PREPARING):
            tracktable.send_inv_item_id.writable = True
            tracktable.item_pack_id.writable = True
            tracktable.quantity.writable = True
            tracktable.comments.writable = True
            tracktable.currency.readable = False
            tracktable.pack_value.readable = False
            tracktable.item_source_no.readable = False
            tracktable.inv_item_status.readable = False
        elif (status == TRACK_STATUS_ARRIVED):
            tracktable.item_source_no.readable = True
            tracktable.recv_quantity.readable = True
            tracktable.return_quantity.readable = True
            tracktable.recv_bin.readable = True
            tracktable.currency.readable = True
            tracktable.pack_value.readable = True
        elif (status == TRACK_STATUS_RETURNING):
            tracktable.return_quantity.readable = True
            tracktable.return_quantity.writable = True
            tracktable.currency.readable = False
            tracktable.pack_value.readable = False
    def prep(r):
        s3.gis.tab = 'search'
        record = db((sendtable.id == r.id)).select(sendtable.status, sendtable.req_ref, limitby=(0, 1)).first()
        if record:
            status = record.status
            if (status != SHIP_STATUS_IN_PROCESS):
                s3db.configure('inv_send', create=False, deletable=False, editable=False, listadd=False)
                s3db.configure('inv_track_item', create=False, deletable=False, editable=False, listadd=False)
        if r.component:
            record = r.record
            values = current.deployment_settings.get_inv_track_pack_values()
            if (status in (SHIP_STATUS_RECEIVED, SHIP_STATUS_CANCEL)):
                list_fields = ['status', 'item_id', 'item_pack_id', 'bin', 'quantity', 'recv_quantity', 'return_quantity', 'owner_org_id', 'supply_org_id', 'inv_item_status', 'comments']
                if values:
                    list_fields.insert(6, 'pack_value')
                    list_fields.insert(6, 'currency')
            elif (status == SHIP_STATUS_RETURNING):
                list_fields = ['status', 'item_id', 'item_pack_id', 'quantity', 'return_quantity', 'bin', 'owner_org_id', 'supply_org_id', 'inv_item_status']
                if values:
                    list_fields.insert(4, 'pack_value')
                    list_fields.insert(4, 'currency')
            else:
                list_fields = ['status', 'item_id', 'item_pack_id', 'quantity', 'bin', 'owner_org_id', 'supply_org_id', 'inv_item_status']
                if values:
                    list_fields.insert(5, 'pack_value')
                    list_fields.insert(5, 'currency')
                if (record.req_ref and r.interactive):
                    s3db.configure('inv_track_item', extra_fields=['req_item_id'])
                    tracktable.quantity_needed = Field.Method('quantity_needed', cls.inv_track_item_quantity_needed)
                    list_fields.insert(3, (T('Quantity    Needed'), 'quantity_needed'))
            s3db.configure('inv_track_item', list_fields=list_fields)
            method = r.method
            if (method in ('create', 'delete')):
                if (status != SHIP_STATUS_IN_PROCESS):
                    return False
                if (method == 'delete'):
                    return s3db.inv_track_item_deleting(r.component_id)
            query = (((iitable.quantity > 0) & ((iitable.expiry_date >= r.now) | (iitable.expiry_date == None))) & (iitable.status == 0))
            if record.get('site_id'):
                query &= (iitable.site_id == record.site_id)
            tracktable.send_inv_item_id.requires = IS_ONE_OF(db(query), 'inv_inv_item.id', s3db.inv_item_represent, orderby='inv_inv_item.id', sort=True)
            if r.component_id:
                track_record = db((tracktable.id == r.component_id)).select(tracktable.req_item_id, tracktable.send_inv_item_id, tracktable.item_pack_id, tracktable.status, tracktable.quantity, limitby=(0, 1)).first()
                set_track_attr(track_record.status)
                if (track_record and track_record.get('req_item_id')):
                    tracktable.send_inv_item_id.writable = False
                    tracktable.item_pack_id.writable = False
                    stock_qnty = track_record.quantity
                    tracktable.quantity.comment = (T('%(quantity)s    in    stock') % dict(quantity=stock_qnty))
                    tracktable.quantity.requires = QUANTITY_INV_ITEM(db, track_record.send_inv_item_id, track_record.item_pack_id)
                tracktable.item_id.readable = False
            else:
                set_track_attr(TRACK_STATUS_PREPARING)
            if r.interactive:
                crud_strings = s3.crud_strings.inv_send
                if (record.status == SHIP_STATUS_IN_PROCESS):
                    crud_strings.title_update = crud_strings.title_display = T('Process    Shipment    to    Send')
                elif (('site_id' in request.vars) and (status == SHIP_STATUS_SENT)):
                    crud_strings.title_update = crud_strings.title_display = T('Review    Incoming    Shipment    to    Receive')
        elif (r.id and request.get_vars.get('received')):
            del request.get_vars['received']
            db((sendtable.id == r.id)).update(status=SHIP_STATUS_RECEIVED)
            db((tracktable.send_id == r.id)).update(status=TRACK_STATUS_ARRIVED)
            req_ref = record.req_ref
            if req_ref:
                rtable = s3db.req_req
                req_id = db((rtable.req_ref == req_ref)).select(rtable.id, limitby=(0, 1)).first()
                ritable = s3db.req_req_item
                query = ((ritable.req_id == req_id) & (ritable.deleted == False))
                ritems = db(query).select(ritable.id, ritable.item_pack_id, ritable.quantity)
                query = ((((sendtable.status == SHIP_STATUS_RECEIVED) & (sendtable.req_ref == req_ref)) & (tracktable.send_id == r.id)) & (tracktable.deleted == False))
                sitems = db(query).select(tracktable.item_pack_id, tracktable.quantity)
                fulfil_qty = {}
                for item in sitems:
                    item_pack_id = item.item_pack_id
                    if (item_pack_id in fulfil_qty):
                        fulfil_qty[item_pack_id] += (item.quantity * item.pack_quantity())
                    else:
                        fulfil_qty[item_pack_id] = (item.quantity * item.pack_quantity())
                complete = False
                for item in ritems:
                    if (item.item_pack_id in fulfil_qty):
                        quantity_fulfil = fulfil_qty[item.item_pack_id]
                        db((ritable.id == item.id)).update(quantity_fulfil=quantity_fulfil)
                        req_quantity = (item.quantity * item.pack_quantity())
                        if (quantity_fulfil >= req_quantity):
                            complete = True
                        else:
                            complete = False
                if complete:
                    db((rtable.id == req_id)).update(fulfil_status=2)
                else:
                    db((rtable.id == req_id)).update(fulfil_status=1)
            response.confirmation = T('Shipment    received')
        elif r.id:
            record = db((sendtable.id == r.id)).select(sendtable.status, limitby=(0, 1)).first()
            set_send_attr(record.status)
        else:
            set_send_attr(SHIP_STATUS_IN_PROCESS)
            sendtable.send_ref.readable = False
        return True
    args = request.args
    if ((len(args) > 1) and (args[1] == 'track_item')):
        try:
            status = db((sendtable.id == args[0])).select(sendtable.status, limitby=(0, 1)).status
        except:
            status = None
        if status:
            editable = False
            if (status == SHIP_STATUS_RETURNING):
                editable = True
            s3db.configure('inv_track_item', create=False, deletable=False, editable=editable, listadd=False)
    s3.prep = prep
    output = current.rest_controller('inv', 'send', rheader=inv_send_rheader)
    return output
