This file is indexed.

/usr/lib/python2.7/dist-packages/trytond/modules/sale_supply_drop_shipment/sale.py is in tryton-modules-sale-supply-drop-shipment 3.4.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#This file is part of Tryton.  The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from itertools import groupby, chain
from functools import partial
from trytond.model import fields
from trytond.pyson import Eval
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.const import OPERATORS

__all__ = ['Sale', 'SaleLine', 'SaleHandleShipmentException']
__metaclass__ = PoolMeta


class Sale:
    __name__ = 'sale.sale'

    drop_shipments = fields.Function(fields.One2Many('stock.shipment.drop',
            None, 'Drop Shipments',
            states={
                'invisible': ~Eval('drop_shipments'),
                }),
        'get_drop_shipments')

    def get_drop_shipments(self, name):
        DropShipment = Pool().get('stock.shipment.drop')
        return list(set(m.shipment.id for l in self.lines for m in l.moves
                if isinstance(m.shipment, DropShipment)))

    def create_shipment(self, shipment_type):
        shipments = super(Sale, self).create_shipment(shipment_type)
        if shipment_type == 'out':
            self.create_drop_shipment()
        return shipments

    def _get_drop_move_sale_line(self):
        '''
        Return a line of moves
        '''
        moves = []
        for line in self.lines:
            moves += line.get_drop_moves()
        return moves

    def _group_drop_shipment_key(self, moves, move):
        '''
        The key to group moves by shipments
        '''
        planned_date = max(m.planned_date for m in moves)
        return (
            ('planned_date', planned_date),
            ('supplier', move.purchase.party),
            )

    def create_drop_shipment(self):
        '''
        Create a drop shipment for the sale
        '''
        pool = Pool()
        Shipment = pool.get('stock.shipment.drop')

        moves = self._get_drop_move_sale_line()
        if not moves:
            return []
        keyfunc = partial(self._group_drop_shipment_key, moves)
        moves = sorted(moves, key=keyfunc)

        shipments = []
        for key, grouped_moves in groupby(moves, key=keyfunc):
            values = {
                'customer': self.party.id,
                'delivery_address': self.shipment_address.id,
                'reference': self.reference,
                'company': self.company.id,
                }
            values.update(dict(key))
            shipment = Shipment(**values)
            shipment.moves = [m for m in grouped_moves]
            shipment.save()
            shipments.append(shipment)
        Shipment.wait(shipments)
        return shipments


class SaleLine:
    __name__ = 'sale.line'

    def get_move(self, shipment_type):
        result = super(SaleLine, self).get_move(shipment_type)
        if (shipment_type == 'out'
                and self.supply_on_sale):
            if (self.purchase_request and self.purchase_request.customer
                    and self.purchase_request_state != 'cancel'):
                return {}
        return result

    def get_purchase_request(self):
        request = super(SaleLine, self).get_purchase_request()
        if request and request.party:
            drop_shipment = False
            if self.product and self.product.type in ('goods', 'assets'):
                # FIXME this doesn't ensure to find always the right
                # product_supplier
                for product_supplier in self.product.product_suppliers:
                    if product_supplier.party == request.party:
                        drop_shipment = product_supplier.drop_shipment
                        break
            if drop_shipment:
                request.customer = self.sale.party
                request.delivery_address = self.sale.shipment_address
        return request

    def get_drop_moves(self):
        if (self.type != 'line'
                or not self.product):
            return []
        moves = []
        if self.purchase_request and self.purchase_request.customer:
            if self.purchase_request.purchase_line:
                moves = [m
                    for m in self.purchase_request.purchase_line.moves
                    if m.state == 'draft' and not m.shipment]
        return moves

    @classmethod
    def read(cls, ids, fields_names=None):
        # Add moves from purchase_request as they can have only one origin
        PurchaseRequest = Pool().get('purchase.request')
        added = False
        if 'moves' in fields_names or []:
            if 'purchase_request' not in fields_names:
                fields_names = fields_names[:]
                fields_names.append('purchase_request')
                added = True
        values = super(SaleLine, cls).read(ids, fields_names=fields_names)
        if 'moves' in fields_names or []:
            with Transaction().set_context(_check_access=False):
                purchase_requests = PurchaseRequest.browse(
                    list(set(v['purchase_request']
                            for v in values if v['purchase_request'])))
                id2purchase_requests = dict((p.id, p)
                    for p in purchase_requests)
            for value in values:
                if value['purchase_request']:
                    purchase_request = id2purchase_requests[
                        value['purchase_request']]
                    if (purchase_request.customer
                            and purchase_request.purchase_line):
                        move_ids = tuple(m.id
                            for m in purchase_request.purchase_line.moves)
                        if value['moves'] is None:
                            value['moves'] = move_ids
                        else:
                            value['moves'] += move_ids
                if added:
                    del value['purchase_request']
        return values

    @classmethod
    def search(cls, domain, *args, **kwargs):
        def process(domain):
            domain = domain[:]
            i = 0
            while i < len(domain):
                arg = domain[i]
                if (isinstance(arg, tuple)
                        or (isinstance(arg, list)
                            and len(arg) > 2
                            and arg[1] in OPERATORS)):
                    if arg[0] == 'moves':
                        domain[i] = ['OR',
                            arg,
                            [
                                ('purchase_request.purchase_line.moves',) +
                                tuple(arg[1:]),
                                ('purchase_request.customer', '!=', None),
                                ]
                            ]
                elif isinstance(arg, list):
                    domain[i] = process(arg)
                i += 1
            return domain
        return super(SaleLine, cls).search(process(domain), *args, **kwargs)


class SaleHandleShipmentException:
    __name__ = 'sale.handle.shipment.exception'

    def transition_handle(self):
        pool = Pool()
        Purchase = pool.get('purchase.purchase')
        PurchaseLine = pool.get('purchase.line')
        Sale = pool.get('sale.sale')

        super(SaleHandleShipmentException, self).transition_handle()

        to_recreate = self.ask.recreate_moves
        domain_moves = self.ask.domain_moves
        purchases, purchaseline_write = set(), []
        sale = Sale(Transaction().context['active_id'])
        for line in sale.lines:
            if not line.purchase_request:
                continue
            purchase_line = line.purchase_request.purchase_line
            if not purchase_line:
                continue

            moves_ignored = []
            moves_recreated = []
            skip = set(purchase_line.moves_ignored)
            skip.update(purchase_line.moves_recreated)
            for move in purchase_line.moves:
                if move not in domain_moves or move in skip:
                    continue
                if move in to_recreate:
                    moves_recreated.append(move.id)
                else:
                    moves_ignored.append(move.id)
                purchases.add(purchase_line.purchase)
            purchaseline_write.append(([purchase_line], {
                        'moves_ignored': [('add', moves_ignored)],
                        'moves_recreated': [('add', moves_recreated)],
                        }))

            PurchaseLine.write(*chain(*purchaseline_write))
            Purchase.process(list(purchases))
        return 'end'