Esempio n. 1
0
    def _get_carrier_context(self):
        Uom = Pool().get('product.uom')

        context = super(ShipmentOut, self)._get_carrier_context()
        if not self.carrier:
            return context
        if self.carrier.carrier_cost_method != 'weight':
            return context
        context = context.copy()
        weights = []
        context['weights'] = weights

        lines = self.inventory_moves or []
        keyfunc = partial(self._group_parcel_key, lines)
        lines = sorted(lines, key=keyfunc)

        for key, parcel in groupby(lines, key=keyfunc):
            weight = 0
            for line in parcel:
                if (line.product
                        and line.quantity
                        and line.uom
                        and line.product.weight):
                    quantity = Uom.compute_qty(line.uom, line.quantity,
                        line.product.default_uom, round=False)
                    weight += Uom.compute_qty(line.product.weight_uom,
                        line.product.weight * quantity,
                        self.carrier.weight_uom, round=False)
            weights.append(weight)
        return context
Esempio n. 2
0
    def _get_carrier_context(self):
        Uom = Pool().get('product.uom')

        context = super(Sale, self)._get_carrier_context()

        if self.carrier.carrier_cost_method != 'weight':
            return context
        context = context.copy()
        weights = []
        context['weights'] = weights

        lines = self.lines or []
        keyfunc = partial(self._group_parcel_key, lines)
        lines = sorted(lines, key=keyfunc)

        for key, parcel in groupby(lines, key=keyfunc):
            weight = 0
            for line in parcel:
                if (getattr(line, 'product', None)
                        and getattr(line, 'quantity', None)
                        and getattr(line, 'unit', None)):
                    quantity = Uom.compute_qty(line.unit, line.quantity,
                        line.product.default_uom, round=False)
                    if line.product.weight:
                        weight += Uom.compute_qty(line.product.weight_uom,
                            line.product.weight * quantity,
                            self.carrier.weight_uom, round=False)
            weights.append(weight)
        return context
Esempio n. 3
0
    def compute(self, party, product, unit_price, quantity, uom,
            pattern=None):
        '''
        Compute price based on price list of party

        :param unit_price: a Decimal for the default unit price in the
            company's currency and default uom of the product
        :param quantity: the quantity of product
        :param uom: a instance of the product.uom
        :param pattern: a dictionary with price list field as key
            and match value as value
        :return: the computed unit price
        '''

        Uom = Pool().get('product.uom')

        if pattern is None:
            pattern = {}

        pattern = pattern.copy()
        pattern['product'] = product and product.id or None
        pattern['quantity'] = Uom.compute_qty(uom, quantity,
                product.default_uom, round=False)

        for line in self.lines:
            if line.match(pattern):
                with Transaction().set_context(
                        self._get_context_price_list_line(party, product,
                            unit_price, quantity, uom)):
                    return line.get_unit_price()
        return unit_price
Esempio n. 4
0
    def on_change_supplier_invoice_line(self):
        pool = Pool()
        Currency = pool.get('currency.currency')
        Unit = Pool().get('product.uom')

        if not self.supplier_invoice_line:
            self.quantity = None
            self.value = None
            self.start_date = self.default_start_date()
            return

        invoice_line = self.supplier_invoice_line
        invoice = invoice_line.invoice
        if invoice.company.currency != invoice.currency:
            with Transaction().set_context(date=invoice.currency_date):
                self.value = Currency.compute(
                    invoice.currency, invoice_line.amount,
                    invoice.company.currency)
        else:
            self.value = invoice_line.amount
        if invoice.invoice_date:
            self.purchase_date = invoice.invoice_date
            self.start_date = invoice.invoice_date
            if invoice_line.product.depreciation_duration:
                duration = relativedelta.relativedelta(
                    months=int(invoice_line.product.depreciation_duration),
                    days=-1)
                self.end_date = self.start_date + duration

        if not self.unit:
            self.quantity = invoice_line.quantity
        else:
            self.quantity = Unit.compute_qty(invoice_line.unit,
                invoice_line.quantity, self.unit)
Esempio n. 5
0
    def get_shipping_rate(self, carrier, carrier_service=None, silent=False):
        """
        Call the rates service and get possible quotes for shipment for eligible
        mail classes
        """
        Currency = Pool().get('currency.currency')
        UOM = Pool().get('product.uom')
        ModelData = Pool().get('ir.model.data')

        if carrier.carrier_cost_method != "endicia":
            return super(Sale, self).get_shipping_rate(
                carrier, carrier_service, silent
            )

        from_address = self._get_ship_from_address()
        if self.shipment_address.country.code == "US":
            mailclass_type = "Domestic"
        else:
            mailclass_type = "International"

        uom_oz = UOM.search([('symbol', '=', 'oz')])[0]

        # Endicia only support 1 decimal place in weight
        weight_oz = "%.1f" % UOM.compute_qty(
            self.weight_uom, self.weight, uom_oz
        )
        to_zip = self.shipment_address.zip
        if mailclass_type == 'Domestic':
            to_zip = to_zip and to_zip[:5]
        else:
            # International
            to_zip = to_zip and to_zip[:15]
        postage_rates_request = PostageRatesAPI(
            mailclass=mailclass_type,
            weightoz=weight_oz,
            from_postal_code=from_address.zip[:5],
            to_postal_code=to_zip,
            to_country_code=self.shipment_address.country.code,
            accountid=carrier.endicia_account_id,
            requesterid=carrier.endicia_requester_id,
            passphrase=carrier.endicia_passphrase,
            test=carrier.endicia_is_test,
        )

        # Logging.
        logger.debug(
            'Making Postage Rates Request for shipping rates of'
            'Sale ID: {0} and Carrier ID: {1}'
            .format(self.id, carrier.id)
        )
        logger.debug('--------POSTAGE RATES REQUEST--------')
        logger.debug(str(postage_rates_request.to_xml()))
        logger.debug('--------END REQUEST--------')

        try:
            response_xml = postage_rates_request.send_request()
            response = objectify_response(response_xml)
        except RequestError, e:
            self.raise_user_error(unicode(e))
Esempio n. 6
0
    def get_weight(self, weight_uom, silent=False):
        """
        Returns weight as required for carriers

        :param weight_uom: Weight uom used by carriers
        :param silent: Raise error if not silent
        """
        ProductUom = Pool().get('product.uom')

        if not self.product or self.quantity <= 0 or \
                self.product.type == 'service':
            return 0

        if not self.product.weight:
            if silent:
                return 0
            self.raise_user_error(
                'weight_required',
                error_args=(self.product.name,)
            )

        # Find the quantity in the default uom of the product as the weight
        # is for per unit in that uom
        if self.unit != self.product.default_uom:
            quantity = ProductUom.compute_qty(
                self.unit,
                self.quantity,
                self.product.default_uom
            )
        else:
            quantity = self.quantity

        weight = self.product.weight * quantity

        # Compare product weight uom with the weight uom used by carrier
        # and calculate weight if botth are not same
        if self.product.weight_uom.symbol != weight_uom.symbol:
            weight = ProductUom.compute_qty(
                self.product.weight_uom,
                weight,
                weight_uom,
            )

        return weight
Esempio n. 7
0
    def _get_rate_request_xml(self, carrier, carrier_service):
        SaleConfiguration = Pool().get("sale.configuration")
        Uom = Pool().get("product.uom")
        config = SaleConfiguration(1)

        code = length = width = height = dimensions_symbol = None
        box_type = config.ups_box_type
        if box_type:
            code = box_type.code
            length = box_type.length
            height = box_type.height
            width = box_type.width
            dimensions_symbol = box_type.distance_unit and box_type.distance_unit.symbol.upper()

        package_type = RatingService.packaging_type(Code=code)

        package_weight = RatingService.package_weight_type(
            Weight="%.2f" % Uom.compute_qty(self.weight_uom, self.weight, carrier.ups_weight_uom),
            Code=carrier.ups_weight_uom_code,
        )
        package_service_options = RatingService.package_service_options_type(
            RatingService.insured_value_type(MonetaryValue="0")
        )

        args = [package_type, package_weight, package_service_options]

        # Only send dimensions if box type has all information
        if length and width and height and dimensions_symbol:
            package_dimensions = RatingService.dimensions_type(
                Code=dimensions_symbol, Length=str(length), Width=str(width), Height=str(height)
            )
            args.append(package_dimensions)

        shipment_args = [RatingService.package_type(*args)]

        from_address = self._get_ship_from_address()

        shipment_args.extend(
            [
                from_address.to_ups_shipper(carrier=carrier),  # Shipper
                self.shipment_address.to_ups_to_address(),  # Ship to
                from_address.to_ups_from_address(),  # Ship from
            ]
        )

        if carrier.ups_negotiated_rates:
            shipment_args.append(RatingService.rate_information_type(negotiated=True))

        if carrier_service:
            # TODO: handle ups_saturday_delivery
            shipment_args.append(RatingService.service_type(Code=carrier_service.code))
            request_option = E.RequestOption("Rate")
        else:
            request_option = E.RequestOption("Shop")

        return RatingService.rating_request_type(E.Shipment(*shipment_args), RequestOption=request_option)
Esempio n. 8
0
 def compute_factor(self, product, quantity, uom):
     """
     Compute factor for an output product
     """
     Uom = Pool().get("product.uom")
     for output in self.outputs:
         if output.product == product:
             if not output.quantity:
                 return 0.0
             quantity = Uom.compute_qty(uom, quantity, output.uom, round=False)
             return quantity / output.quantity
Esempio n. 9
0
    def on_change_asset(self):
        Uom = Pool().get('product.uom')

        if self.asset:
            quantity = self.asset.quantity
            if self.unit:
                quantity = Uom.compute_qty(self.asset.unit, quantity,
                    self.unit)
                self.quantity = quantity
            else:
                self.quantity = quantity
                self.unit = self.unit
Esempio n. 10
0
 def compute_factor(self, product, quantity, uom):
     '''
     Compute factor for an output product
     '''
     Uom = Pool().get('product.uom')
     for output in self.outputs:
         if output.product == product:
             if not output.quantity:
                 return 0.0
             quantity = Uom.compute_qty(uom, quantity,
                 output.uom, round=False)
             return quantity / output.quantity
Esempio n. 11
0
    def on_change_asset(self):
        Uom = Pool().get('product.uom')

        if self.asset:
            quantity = self.asset.quantity
            if self.unit:
                quantity = Uom.compute_qty(self.asset.unit, quantity,
                    self.unit)
                self.quantity = quantity
            else:
                self.quantity = quantity
                self.unit = self.unit
Esempio n. 12
0
 def get_weight(self, name):
     """
     Returns package weight if weight is not overriden
     otherwise returns overriden weight
     """
     UOM = Pool().get('product.uom')
     if self.override_weight:
         return UOM.compute_qty(
             self.override_weight_uom,
             self.override_weight,
             self.weight_uom
         )
     return self.get_computed_weight()
Esempio n. 13
0
    def get_weight(self, weight_uom, silent=False):
        """
        Returns weight as required for carriers

        :param weight_uom: Weight uom used by carriers
        :param silent: Raise error if not silent
        """
        ProductUom = Pool().get('product.uom')

        if not self.product or self.quantity <= 0 or \
                self.product.type == 'service':
            return 0

        if not self.product.weight:
            if silent:
                return 0
            self.raise_user_error('weight_required',
                                  error_args=(self.product.name, ))

        # Find the quantity in the default uom of the product as the weight
        # is for per unit in that uom
        if self.unit != self.product.default_uom:
            quantity = ProductUom.compute_qty(self.unit, self.quantity,
                                              self.product.default_uom)
        else:
            quantity = self.quantity

        weight = self.product.weight * quantity

        # Compare product weight uom with the weight uom used by carrier
        # and calculate weight if botth are not same
        if self.product.weight_uom != weight_uom:
            weight = ProductUom.compute_qty(
                self.product.weight_uom,
                weight,
                weight_uom,
            )

        return weight
Esempio n. 14
0
 def get_total_volume(self, _ids):
     """Compute the total volume sum"""
     if self.total_volume_uom is None:
         return 0.0
     total = 0.0
     for trunks in self.trunks:
         if trunks is None or trunks.total_cubing is None:
             continue
         total += trunks.get_total_cubing(None)
     Uom = Pool().get('product.uom')
     m3_id = Id('product', 'uom_cubic_meter').pyson()
     m3 = Uom(m3_id)
     return Uom.compute_qty(m3, total, self.total_volume_uom)
    def get_weight_for_endicia(self):
        """
        Returns weight as required for endicia.

        Upward rounded integral values in Oz
        """
        ProductUom = Pool().get('product.uom')

        if self.product.type == 'service':
            return 0

        if not self.product.weight:
            self.raise_user_error(
                'weight_required',
                error_args=(self.product.name,)
            )

        # Find the quantity in the default uom of the product as the weight
        # is for per unit in that uom
        if self.uom != self.product.default_uom:
            quantity = ProductUom.compute_qty(
                self.uom,
                self.quantity,
                self.product.default_uom
            )
        else:
            quantity = self.quantity

        weight = float(self.product.weight) * quantity

        # Endicia by default uses oz for weight purposes
        if self.product.weight_uom.symbol != 'oz':
            ounce, = ProductUom.search([('symbol', '=', 'oz')])
            weight = ProductUom.compute_qty(
                self.product.weight_uom,
                weight,
                ounce
            )
        return math.ceil(weight)
Esempio n. 16
0
 def get_mean_volume(self, ids):
     """Return the mean volume in the selected unit"""
     if self.total_trunks_count == 0 or self.mean_volume_uom is None:
         return 0.0
     total = 0.0
     for trunks in self.trunks:
         if trunks is None or trunks.total_cubing is None:
             continue
         total += trunks.get_total_cubing(None)
     Uom = Pool().get('product.uom')
     m3_id = Id('product', 'uom_cubic_meter').pyson()
     m3 = Uom(m3_id)
     return Uom.compute_qty(m3, total / float(self.total_trunks_count), self.mean_volume_uom)
Esempio n. 17
0
    def get_monetary_value_for_ups(self):
        """
        Returns monetary_value as required for ups
        """
        ProductUom = Pool().get("product.uom")

        # Find the quantity in the default uom of the product as the weight
        # is for per unit in that uom
        if self.uom != self.product.default_uom:
            quantity = ProductUom.compute_qty(self.uom, self.quantity, self.product.default_uom)
        else:
            quantity = self.quantity

        return Decimal(self.product.list_price) * Decimal(quantity)
Esempio n. 18
0
    def _fill_line_from_kit_line(self, kit_line, line):
        ProductUom = Pool().get('product.uom')

        self.product = kit_line.product
        if kit_line.unit.category.id != line.unit.category.id:
            quantity = kit_line.quantity * line.quantity
        else:
            quantity = ProductUom.compute_qty(
                    kit_line.unit, kit_line.quantity, line.unit
                    ) * line.quantity
        self.quantity = quantity
        self.unit = kit_line.unit
        self.type = 'line'
        self.kit_parent_line = line
Esempio n. 19
0
    def _update_fifo_out_product_cost_price(self):
        """
        Update the product cost price of the given product on the move. Update
        fifo_quantity on the concerned incomming moves. Return the
        cost price for outputing the given product and quantity.
        """

        Uom = Pool().get("product.uom")

        total_qty = Uom.compute_qty(self.uom, self.quantity, self.product.default_uom, round=False)

        fifo_moves = self.product.template.get_fifo_move(total_qty)

        cost_price = Decimal("0.0")
        consumed_qty = 0.0
        for move, move_qty in fifo_moves:
            consumed_qty += move_qty

            move_unit_price = Uom.compute_price(move.uom, move.unit_price, move.product.default_uom)
            cost_price += move_unit_price * Decimal(str(move_qty))

            move.quantity = move_qty
            move._update_product_cost_price("out")

            move_qty = Uom.compute_qty(self.product.default_uom, move_qty, move.uom, round=False)
            # Use write as move instance quantity was modified to call
            # _update_product_cost_price
            self.write([self.__class__(move.id)], {"fifo_quantity": (move.fifo_quantity or 0.0) + move_qty})

        if Decimal(str(consumed_qty)) != Decimal("0"):
            cost_price = cost_price / Decimal(str(consumed_qty))

        if cost_price != Decimal("0"):
            digits = self.__class__.cost_price.digits
            return cost_price.quantize(Decimal(str(10.0 ** -digits[1])))
        else:
            return self.product.cost_price
Esempio n. 20
0
    def get_ups_package_container_rate(self):
        """
        Return UPS package container for a single package
        """
        Uom = Pool().get('product.uom')

        shipment = self.shipment
        carrier = shipment.carrier

        if self.box_type:
            code = self.box_type.code
            length = self.box_type.length
            height = self.box_type.height
            width = self.box_type.width
            dimensions_symbol = self.box_type.distance_unit and \
                self.box_type.distance_unit.symbol.upper()
        else:
            code = '02'
            length = self.length
            height = self.height
            width = self.width
            dimensions_symbol = self.distance_unit and \
                self.distance_unit.symbol.upper()

        package_type = RatingService.packaging_type(Code=code)
        package_weight = RatingService.package_weight_type(
            Weight="%.2f" % Uom.compute_qty(
                self.weight_uom, self.weight, carrier.ups_weight_uom
            ),
            Code=carrier.ups_weight_uom_code,
        )
        package_service_options = RatingService.package_service_options_type(
            RatingService.insured_value_type(MonetaryValue='0')
        )

        args = [package_type, package_weight, package_service_options]

        # Only send dimensions if the box type is 'Customer Supplied Package'
        if code == '02' and length and width and height and dimensions_symbol:
            package_dimensions = RatingService.dimensions_type(
                Code=dimensions_symbol,
                Length=str(length),
                Width=str(width),
                Height=str(height)
            )
            args.append(package_dimensions)

        package_container = RatingService.package_type(*args)
        return package_container
Esempio n. 21
0
 def create(cls, vlist):
     Uom = Pool().get('product.uom')
     for v in vlist:
         default_uom = cls.get_count_uom(v['product'], default_uom=True)
         if 'quantity' not in v:
             v['quantity'] = 0.0
         if 'quantity_1' not in v:
             uom_1 = cls.get_count_uom(v['product'])
             if default_uom.id == uom_1.id:
                 v['quantity_1'] = v['quantity']
             else:
                 v['quantity_1'] = Uom.compute_qty(default_uom,
                                                   v['quantity'], uom_1)
             v['uom_1'] = uom_1.id
     return super(InventoryLine, cls).create(vlist)
        def compute_quantites(sql_where):
            Uom = Pool().get('product.uom')

            query = move.select(move.id.as_('move_id'),
                                where=sql_where,
                                order_by=move.effective_date.desc)
            cursor.execute(*query)
            move_ids = [m[0] for m in cursor.fetchall()]
            moves = Move.browse(move_ids)
            total = sum([
                Uom.compute_qty(m.uom, m.quantity, m.product.default_uom, True)
                for m in moves
            ])
            moves = [DualRecord(m) for m in moves]
            return total, moves
Esempio n. 23
0
    def get_monetary_value_for_ups(self):
        """
        Returns monetary_value as required for ups
        """
        ProductUom = Pool().get('product.uom')

        # Find the quantity in the default uom of the product as the weight
        # is for per unit in that uom
        if self.uom != self.product.default_uom:
            quantity = ProductUom.compute_qty(self.uom, self.quantity,
                                              self.product.default_uom)
        else:
            quantity = self.quantity

        return Decimal(self.product.list_price) * Decimal(quantity)
Esempio n. 24
0
    def get_total_cubing(self, _name):
        """Compute the total cubing nd convert it to the select UOM"""
        total = 0.0
        if self.trunks_count is None:
            return 0.0
        for trunk in self.trunks_count:
            diameter = (trunk.diam_class.diameter_min + trunk.diam_class.diameter_max) / 2.0
            total += self.get_volume(trunk.height_m, diameter) * trunk.count

        # Unit conversion
        Uom = Pool().get('product.uom')
        m3_id = Id('product', 'uom_cubic_meter').pyson()
        m3 = Uom(m3_id)
        # call compute_qty to round the number
        return Uom.compute_qty(m3, total, m3)
Esempio n. 25
0
    def get_weight(self, name=None):
        """
        Returns sum of weight associated with each package or
        move line otherwise
        """
        Uom = Pool().get('product.uom')

        if self.packages:
            return sum(
                map(
                    lambda p: Uom.compute_qty(p.weight_uom, p.weight, self.
                                              weight_uom), self.packages))

        return sum(
            map(lambda move: move.get_weight(self.weight_uom, silent=True),
                self.carrier_cost_moves))
Esempio n. 26
0
 def compute_factor(self, product, quantity, uom):
     '''
     Compute factor for an output product
     '''
     Uom = Pool().get('product.uom')
     output_quantity = 0
     for output in self.outputs:
         if output.product == product:
             output_quantity += Uom.compute_qty(output.uom,
                                                output.quantity,
                                                uom,
                                                round=False)
     if output_quantity:
         return quantity / output_quantity
     else:
         return 0
Esempio n. 27
0
    def on_change_with_cost(self):
        Uom = Pool().get('product.uom')

        cost = Decimal(0)
        if not self.inputs:
            return cost

        for input_ in self.inputs:
            if (input_.product is None or input_.uom is None
                    or input_.quantity is None):
                continue
            product = input_.product
            quantity = Uom.compute_qty(input_.uom, input_.quantity,
                                       product.default_uom)
            cost += Decimal(str(quantity)) * product.cost_price
        return cost
Esempio n. 28
0
    def on_change_with_cost(self):
        Uom = Pool().get('product.uom')

        cost = Decimal(0)
        if not self.inputs:
            return cost

        for input_ in self.inputs:
            if (input_.product is None
                    or input_.uom is None
                    or input_.quantity is None):
                continue
            product = input_.product
            quantity = Uom.compute_qty(input_.uom, input_.quantity,
                product.default_uom)
            cost += Decimal(str(quantity)) * product.cost_price
        return cost
Esempio n. 29
0
    def on_change_asset(self):
        Uom = Pool().get('product.uom')

        if self.asset:
            quantity = self.asset.quantity
            if self.unit:
                quantity = Uom.compute_qty(self.asset.unit, quantity,
                    self.unit)
                return {
                    'quantity': quantity,
                    }
            else:
                return {
                    'quantity': quantity,
                    'unit': self.unit.id,
                    'unit.rec_name': self.unit.rec_name,
                    }
        return {}
Esempio n. 30
0
    def get_weight(self, name=None):
        """
        Returns sum of weight associated with each package or
        move line otherwise
        """
        Uom = Pool().get('product.uom')

        if self.packages:
            return sum(map(
                lambda p: Uom.compute_qty(
                    p.weight_uom, p.weight, self.weight_uom
                ),
                self.packages
            ))

        return sum(map(
            lambda move: move.get_weight(self.weight_uom, silent=True),
            self.carrier_cost_moves
        ))
Esempio n. 31
0
    def on_change_with_minimum_quantity(self, name=None):
        Uom = Pool().get('product.uom')
        if not self.product or not self.purchase.party:
            return

        product_suppliers = list(
            self.product.product_suppliers_used(
                **{'party': self.purchase.party.id}))

        if not product_suppliers:
            return

        product_supplier = product_suppliers[0]
        minimum_quantity = product_supplier.minimum_quantity
        uom_category = self.product.purchase_uom.category
        if (minimum_quantity and self.unit and self.unit in uom_category.uoms):
            return Uom.compute_qty(self.product.purchase_uom, minimum_quantity,
                                   self.unit)
        return minimum_quantity
Esempio n. 32
0
    def compute(self, party, product, unit_price, quantity, uom,
            pattern=None):
        'Compute price based on price list of party'

        Uom = Pool().get('product.uom')

        if pattern is None:
            pattern = {}

        pattern = pattern.copy()
        pattern['product'] = product and product.id or None
        pattern['quantity'] = Uom.compute_qty(uom, quantity,
            product.default_uom, round=False) if product else quantity

        context = self.get_context_formula(
            party, product, unit_price, quantity, uom)
        for line in self.lines:
            if line.match(pattern):
                return line.get_unit_price(**context)
        return unit_price
Esempio n. 33
0
    def compute(self, party, product, unit_price, quantity, uom, pattern=None):
        'Compute price based on price list of party'

        Uom = Pool().get('product.uom')

        if pattern is None:
            pattern = {}

        pattern = pattern.copy()
        pattern['product'] = product and product.id or None
        pattern['quantity'] = Uom.compute_qty(
            uom, quantity, product.default_uom,
            round=False) if product else quantity

        context = self.get_context_formula(party, product, unit_price,
                                           quantity, uom)
        for line in self.lines:
            if line.match(pattern):
                return line.get_unit_price(**context)
        return unit_price
Esempio n. 34
0
    def compute(self, product, unit_price, quantity, uom,
            pattern=None):
        'Compute price based on price list of party'

        def get_unit_price(**context):
            'Return unit price (as Decimal)'
            context.setdefault('functions', {})['Decimal'] = Decimal
            return simple_eval(decistmt(self.formula), **context)
        Uom = Pool().get('product.uom')

        if pattern is None:
            pattern = {}

        pattern = pattern.copy()
        pattern['product'] = product and product.id or None
        pattern['quantity'] = Uom.compute_qty(uom, quantity,
            product.default_uom, round=False) if product else quantity

        context = self.get_context_formula(
            product, unit_price, quantity, uom)
        return get_unit_price(**context)
Esempio n. 35
0
    def get_fedex_items_details(self, fedex_request):
        '''
        Computes the details of the shipment items and passes to fedex request
        '''
        ProductUom = Pool().get('product.uom')

        item = fedex_request.get_element_from_type(
            'RequestedPackageLineItem'
        )
        weight_uom, = ProductUom.search([('symbol', '=', 'lb')])
        item.SequenceNumber = 1
        item.Weight.Units = 'LB'
        item.Weight.Value = ProductUom.compute_qty(
            self.weight_uom, self.package_weight, weight_uom
        )

        # From sale you cannot define packages per shipment, so single
        # package per shipment.
        item.GroupPackageCount = 1
        fedex_request.RequestedShipment.PackageCount = 1

        fedex_request.RequestedShipment.RequestedPackageLineItems = [item]
Esempio n. 36
0
    def get_fedex_items_details(self, fedex_request):
        '''
        Computes the details of the shipment items and passes to fedex request
        '''
        ProductUom = Pool().get('product.uom')

        item = fedex_request.get_element_from_type(
            'RequestedPackageLineItem'
        )
        weight_uom, = ProductUom.search([('symbol', '=', 'lb')])
        item.SequenceNumber = 1
        item.Weight.Units = 'LB'
        item.Weight.Value = ProductUom.compute_qty(
            self.weight_uom, self.package_weight, weight_uom
        )

        # From sale you cannot define packages per shipment, so single
        # package per shipment.
        item.GroupPackageCount = 1
        fedex_request.RequestedShipment.PackageCount = 1

        fedex_request.RequestedShipment.RequestedPackageLineItems = [item]
Esempio n. 37
0
    def on_change_supplier_invoice_line(self):
        pool = Pool()
        Currency = pool.get('currency.currency')
        Unit = Pool().get('product.uom')

        new_values = {}
        if not self.supplier_invoice_line:
            new_values['quantity'] = None
            new_values['value'] = None
            new_values['start_date'] = self.default_start_date()
            return new_values

        invoice_line = self.supplier_invoice_line
        invoice = invoice_line.invoice
        if invoice.company.currency != invoice.currency:
            with Transaction().set_context(date=invoice.currency_date):
                new_values['value'] = Currency.compute(
                    invoice.currency, invoice_line.amount,
                    invoice.company.currency)
        else:
            new_values['value'] = invoice_line.amount
        if invoice.invoice_date:
            new_values['purchase_date'] = invoice.invoice_date
            new_values['start_date'] = invoice.invoice_date
            if invoice_line.product.depreciation_duration:
                duration = relativedelta.relativedelta(
                    months=int(invoice_line.product.depreciation_duration),
                    days=-1)
                new_values['end_date'] = new_values['start_date'] + duration

        if not self.unit:
            new_values['quantity'] = invoice_line.quantity
            return new_values

        new_values['quantity'] = Unit.compute_qty(invoice_line.unit,
            invoice_line.quantity, self.unit)

        return new_values
Esempio n. 38
0
    def compute(self, party, product, unit_price, quantity, uom, pattern=None):
        'Compute price based on price list of party'

        Uom = Pool().get('product.uom')

        def parents(categories):
            for category in categories:
                while category:
                    yield category
                    category = category.parent

        if pattern is None:
            pattern = {}

        pattern = pattern.copy()
        if product:
            pattern['categories'] = [
                c.id for c in parents(product.categories_all)
            ]
            pattern['product'] = product.id
        pattern['quantity'] = Uom.compute_qty(
            uom, quantity, self.get_uom(product),
            round=False) if product else quantity

        context = self.get_context_formula(party,
                                           product,
                                           unit_price,
                                           quantity,
                                           uom,
                                           pattern=pattern)
        for line in self.lines:
            if line.match(pattern):
                unit_price = line.get_unit_price(**context)
                if isinstance(unit_price, Null):
                    unit_price = None
                break
        return unit_price
Esempio n. 39
0
    def make_fedex_labels(self):
        """
        Make labels for the given shipment

        :return: Tracking number as string
        """
        Currency = Pool().get('currency.currency')
        Attachment = Pool().get('ir.attachment')
        Package = Pool().get('stock.package')
        Uom = Pool().get('product.uom')

        if self.state not in ('packed', 'done'):
            self.raise_user_error('invalid_state')

        if not self.carrier.carrier_cost_method == 'fedex':
            self.raise_user_error('wrong_carrier')

        if self.tracking_number:
            self.raise_user_error('tracking_number_already_present')

        fedex_credentials = self.carrier.get_fedex_credentials()

        ship_request = ProcessShipmentRequest(fedex_credentials)
        requested_shipment = ship_request.RequestedShipment

        requested_shipment.DropoffType = self.fedex_drop_off_type.value
        requested_shipment.ServiceType = self.fedex_service_type.value
        requested_shipment.PackagingType = self.fedex_packaging_type.value

        uom_pound, = Uom.search([('symbol', '=', 'lb')])

        if len(self.packages) > 1:
            requested_shipment.TotalWeight.Units = 'LB'
            requested_shipment.TotalWeight.Value = Uom.compute_qty(
                self.weight_uom, self.weight, uom_pound
            )

        # Shipper & Recipient
        requested_shipment.Shipper.AccountNumber = \
            fedex_credentials.AccountNumber

        if not self.warehouse.address:
            self.raise_user_error('warehouse_address_required')

        self.warehouse.address.set_fedex_address(requested_shipment.Shipper)
        self.delivery_address.set_fedex_address(requested_shipment.Recipient)

        # Shipping Charges Payment
        shipping_charges = requested_shipment.ShippingChargesPayment
        shipping_charges.PaymentType = 'SENDER'
        shipping_charges.Payor.ResponsibleParty = requested_shipment.Shipper

        # Express Freight Detail
        fright_detail = requested_shipment.ExpressFreightDetail
        fright_detail.PackingListEnclosed = 1  # XXX
        fright_detail.ShippersLoadAndCount = 2  # XXX
        fright_detail.BookingConfirmationNumber = 'Ref-%s' % self.reference

        if self.is_international_shipping:
            # Customs Clearance Detail
            self.get_fedex_customs_details(ship_request)

        # Label Specification
        # Maybe make them as configurable items in later versions
        requested_shipment.LabelSpecification.LabelFormatType = 'COMMON2D'
        requested_shipment.LabelSpecification.ImageType = 'PNG'
        requested_shipment.LabelSpecification.LabelStockType = 'PAPER_4X6'

        requested_shipment.RateRequestTypes = ['ACCOUNT']

        master_tracking_number = None

        for index, package in enumerate(self.packages, start=1):
            item = ship_request.get_element_from_type(
                'RequestedPackageLineItem'
            )
            item.SequenceNumber = index

            # TODO: some country needs item.ItemDescription

            item.Weight.Units = 'LB'
            item.Weight.Value = Uom.compute_qty(
                package.weight_uom, package.weight, uom_pound
            )

            ship_request.RequestedShipment.RequestedPackageLineItems = [item]
            ship_request.RequestedShipment.PackageCount = len(self.packages)

            if master_tracking_number is not None:
                tracking_id = ship_request.get_element_from_type(
                    'TrackingId'
                )
                tracking_id.TrackingNumber = master_tracking_number
                ship_request.RequestedShipment.MasterTrackingId = tracking_id

            try:
                response = ship_request.send_request(str(self.id))
            except RequestError, error:
                self.raise_user_error('error_label', error_args=(error,))

            package_details = response.CompletedShipmentDetail.CompletedPackageDetails  # noqa
            tracking_number = package_details[0].TrackingIds[0].TrackingNumber

            if self.packages.index(package) == 0:
                master_tracking_number = tracking_number

            Package.write([package], {
                'tracking_number': tracking_number,
            })

            for id, image in enumerate(package_details[0].Label.Parts):
                Attachment.create([{
                    'name': "%s_%s_Fedex.png" % (tracking_number, id),
                    'type': 'data',
                    'data': buffer(base64.decodestring(image.Image)),
                    'resource': '%s,%s' % (self.__name__, self.id)
                }])
Esempio n. 40
0
 def get_height_m(self, _name):
     """Convert the height to meters"""
     Uom = Pool().get('product.uom')
     m_id = Id('product', 'uom_meter').pyson()
     m = Uom(m_id)
     return Uom.compute_qty(self.height_uom, self.height, m)
Esempio n. 41
0
 def _get_internal_quantity(quantity, uom, product):
     Uom = Pool().get('product.uom')
     internal_quantity = Uom.compute_qty(uom, quantity,
         product.default_uom, round=True)
     return internal_quantity
Esempio n. 42
0
    def make_fedex_labels(self):
        """
        Make labels for the given shipment

        :return: Tracking number as string
        """
        Currency = Pool().get('currency.currency')
        Attachment = Pool().get('ir.attachment')
        Package = Pool().get('stock.package')
        Uom = Pool().get('product.uom')

        if self.state not in ('packed', 'done'):
            self.raise_user_error('invalid_state')

        if not self.carrier.carrier_cost_method == 'fedex':
            self.raise_user_error('wrong_carrier')

        if self.tracking_number:
            self.raise_user_error('tracking_number_already_present')

        fedex_credentials = self.carrier.get_fedex_credentials()

        ship_request = ProcessShipmentRequest(fedex_credentials)
        requested_shipment = ship_request.RequestedShipment

        requested_shipment.DropoffType = self.fedex_drop_off_type.value
        requested_shipment.ServiceType = self.fedex_service_type.value
        requested_shipment.PackagingType = self.fedex_packaging_type.value

        uom_pound, = Uom.search([('symbol', '=', 'lb')])

        if len(self.packages) > 1:
            requested_shipment.TotalWeight.Units = 'LB'
            requested_shipment.TotalWeight.Value = Uom.compute_qty(
                self.weight_uom, self.weight, uom_pound
            )

        # Shipper & Recipient
        requested_shipment.Shipper.AccountNumber = \
            fedex_credentials.AccountNumber

        from_address = self._get_ship_from_address()
        from_address.set_fedex_address(requested_shipment.Shipper)
        self.delivery_address.set_fedex_address(requested_shipment.Recipient)

        # Shipping Charges Payment
        shipping_charges = requested_shipment.ShippingChargesPayment
        shipping_charges.PaymentType = 'SENDER'
        shipping_charges.Payor.ResponsibleParty = requested_shipment.Shipper

        # Express Freight Detail
        fright_detail = requested_shipment.ExpressFreightDetail
        fright_detail.PackingListEnclosed = 1  # XXX
        fright_detail.ShippersLoadAndCount = 2  # XXX
        fright_detail.BookingConfirmationNumber = 'Ref-%s' % self.reference

        if self.is_international_shipping:
            # Customs Clearance Detail
            self.get_fedex_customs_details(ship_request)

        # Label Specification
        # Maybe make them as configurable items in later versions
        requested_shipment.LabelSpecification.LabelFormatType = 'COMMON2D'
        requested_shipment.LabelSpecification.ImageType = 'PNG'
        requested_shipment.LabelSpecification.LabelStockType = 'PAPER_4X6'

        requested_shipment.RateRequestTypes = ['ACCOUNT']

        master_tracking_number = None

        for index, package in enumerate(self.packages, start=1):
            item = ship_request.get_element_from_type(
                'RequestedPackageLineItem'
            )
            item.SequenceNumber = index

            # TODO: some country needs item.ItemDescription

            item.Weight.Units = 'LB'
            item.Weight.Value = Uom.compute_qty(
                package.weight_uom, package.weight, uom_pound
            )

            ship_request.RequestedShipment.RequestedPackageLineItems = [item]
            ship_request.RequestedShipment.PackageCount = len(self.packages)

            if master_tracking_number is not None:
                tracking_id = ship_request.get_element_from_type(
                    'TrackingId'
                )
                tracking_id.TrackingNumber = master_tracking_number
                ship_request.RequestedShipment.MasterTrackingId = tracking_id

            try:
                response = ship_request.send_request(str(self.id))
            except RequestError, error:
                self.raise_user_error('error_label', error_args=(error,))

            package_details = response.CompletedShipmentDetail.CompletedPackageDetails  # noqa
            tracking_number = package_details[0].TrackingIds[0].TrackingNumber

            if self.packages.index(package) == 0:
                master_tracking_number = tracking_number

            Package.write([package], {
                'tracking_number': tracking_number,
            })

            for id, image in enumerate(package_details[0].Label.Parts):
                Attachment.create([{
                    'name': "%s_%s_Fedex.png" % (tracking_number, id),
                    'type': 'data',
                    'data': buffer(base64.decodestring(image.Image)),
                    'resource': '%s,%s' % (self.__name__, self.id)
                }])
    def mass_balance_report_data(self, requested_product, direction, lot=None):
        Uom = Pool().get('product.uom')

        digits = self.uom and self.uom.digits or 2
        quantity = 0.0
        for move in getattr(
                self, 'outputs' if direction == 'backward' else 'inputs'):
            if move.state == 'cancelled':
                continue
            if move.product == requested_product:
                # skip moves that same product but different lot
                if lot and lot != move.lot:
                    continue
                quantity += Uom.compute_qty(move.uom, move.quantity,
                                            move.product.default_uom, False)

        moves = {}
        for move in getattr(
                self, 'inputs' if direction == 'backward' else 'outputs'):
            if move.state == 'cancelled':
                continue
            product = move.product
            mqty = Uom.compute_qty(move.uom, move.quantity,
                                   move.product.default_uom, False)
            if moves.get(product):
                moves[product] += mqty
            else:
                moves[product] = mqty

        res = {}
        for product, qty in moves.items():
            item = res.setdefault(product, {})
            item.setdefault('balance_quantity', 0.0)
            item.setdefault('balance_consumption', 0.0)
            item.setdefault('balance_plan_consumption', 0.0)
            item.setdefault('balance_difference', 0.0)
            item.setdefault('productions', [])

            if direction == 'backward':
                balance_quantity = quantity
                balance_consumption = qty
                balance_plan_consumption = balance_difference = balance_difference_percent = 0.0
                if self.bom:
                    bom = self.bom
                    for bm in bom.inputs:
                        if bm.product == product:
                            default_uom = self.product.default_uom
                            bqty = Uom.compute_qty(bm.uom, bm.quantity,
                                                   bm.product.default_uom,
                                                   False)
                            factor = bom.compute_factor(
                                self.product, bqty, default_uom)
                            balance_plan_consumption = default_uom.ceil(
                                self.quantity * factor)
                            break

                    balance_difference = round(qty - balance_plan_consumption,
                                               digits)
                    if balance_consumption and balance_plan_consumption:
                        balance_difference_percent = (
                            (balance_consumption - balance_plan_consumption) /
                            balance_plan_consumption) * 100
                item['balance_quantity'] = balance_quantity
                item['balance_consumption'] += balance_consumption
                item['balance_plan_consumption'] += balance_plan_consumption
                item['balance_difference'] += balance_difference
                item['balance_quantity_uom'] = requested_product.default_uom
                item['balance_consumption_uom'] = product.default_uom
                item['balance_plan_consumption_uom'] = product.default_uom
                item['balance_difference_uom'] = product.default_uom
            else:
                balance_quantity = qty
                balance_consumption = quantity
                balance_plan_consumption = balance_difference = balance_difference_percent = 0.0
                if self.bom:
                    bom = self.bom
                    for bm in bom.inputs:
                        if bm.product == requested_product:
                            default_uom = self.product.default_uom
                            bqty = Uom.compute_qty(bm.uom, bm.quantity,
                                                   bm.product.default_uom,
                                                   False)
                            factor = bom.compute_factor(
                                self.product, bqty, default_uom)
                            balance_plan_consumption = default_uom.ceil(
                                self.quantity * factor)
                            break

                    balance_difference = round(
                        quantity - balance_plan_consumption, digits)
                    if balance_consumption and balance_plan_consumption:
                        balance_difference_percent = (
                            (balance_consumption - balance_plan_consumption) /
                            balance_plan_consumption) * 100
                item['balance_quantity'] = balance_quantity
                item['balance_consumption'] += balance_consumption
                item['balance_plan_consumption'] += balance_plan_consumption
                item['balance_difference'] += balance_difference
                item['balance_quantity_uom'] = product.default_uom
                item['balance_consumption_uom'] = requested_product.default_uom
                item[
                    'balance_plan_consumption_uom'] = requested_product.default_uom
                item['balance_difference_uom'] = requested_product.default_uom

            vals = {
                'id':
                self.id,
                'name':
                self.rec_name,
                'product':
                self.product,
                'uom':
                self.uom,
                'default_uom':
                product.default_uom,
                'balance_quantity':
                balance_quantity,
                'balance_consumption':
                balance_consumption,
                'balance_plan_consumption':
                balance_plan_consumption,
                'balance_difference':
                balance_difference,
                'balance_difference_percent':
                balance_difference_percent,
                'balance_quantity_uom':
                item['balance_quantity_uom'],
                'balance_consumption_uom':
                item['balance_consumption_uom'],
                'balance_plan_consumption_uom':
                item['balance_plan_consumption_uom'],
                'balance_difference_uom':
                item['balance_difference_uom'],
            }
            item['productions'].append(vals)

        return res
Esempio n. 44
0
    def generate_shipping_labels(self, **kwargs):
        """
        Make labels for the given shipment

        :return: Tracking number as string
        """
        Attachment = Pool().get('ir.attachment')
        Tracking = Pool().get('shipment.tracking')
        Uom = Pool().get('product.uom')

        if self.carrier_cost_method != 'endicia':
            return super(ShipmentOut, self).generate_shipping_labels(**kwargs)

        label_request = LabelRequest(
            Test=self.carrier.endicia_is_test and 'YES' or 'NO',
            LabelType=(
                'International' in self.carrier_service.code
            ) and 'International' or 'Default',
            # TODO: Probably the following have to be configurable
            ImageFormat="PNG",
            LabelSize="6x4",
            ImageResolution="203",
            ImageRotation="Rotate270",
        )

        try:
            package, = self.packages
        except ValueError:
            self.raise_user_error(
                "There should be exactly one package to generate USPS label"
                "\n Multi Piece shipment is not supported yet"
            )

        oz, = Uom.search([('symbol', '=', 'oz')])
        # Endicia only support 1 decimal place in weight
        weight_oz = "%.1f" % Uom.compute_qty(
            package.weight_uom, package.weight, oz
        )
        shipping_label_request = ShippingLabelAPI(
            label_request=label_request,
            weight_oz=weight_oz,
            partner_customer_id=self.delivery_address.id,
            partner_transaction_id=self.id,
            mail_class=self.carrier_service.code,
            accountid=self.carrier.endicia_account_id,
            requesterid=self.carrier.endicia_requester_id,
            passphrase=self.carrier.endicia_passphrase,
            test=self.carrier.endicia_is_test,
        )

        shipping_label_request.mailpieceshape = package.box_type and \
            package.box_type.code

        # Dimensions required for priority mail class and
        # all values must be in inches
        to_uom, = Uom.search([('symbol', '=', 'in')])
        from_uom, = Uom.search([('symbol', '=', package.distance_unit.symbol)])
        if (package.length and package.width and package.height):
            length, width, height = package.length, package.width, package.height
            if from_uom != to_uom:
                length = "%.1f" % Uom.compute_qty(
                    from_uom, package.length, to_uom
                )
                width = "%.1f" % Uom.compute_qty(
                    from_uom, package.width, to_uom
                )
                height = "%.1f" % Uom.compute_qty(
                    from_uom, package.height, to_uom
                )
            shipping_label_request.mailpiecedimensions = {
                'Length': length,
                'Width': width,
                'Height': height
            }

        from_address = self._get_ship_from_address()

        shipping_label_request.add_data(
            from_address.address_to_endicia_from_address().data
        )
        shipping_label_request.add_data(
            self.delivery_address.address_to_endicia_to_address().data
        )
        shipping_label_request.add_data({
            'LabelSubtype': self.endicia_label_subtype,
            'IncludePostage':
                self.endicia_include_postage and 'TRUE' or 'FALSE',
        })

        if self.endicia_label_subtype != 'None':
            # Integrated form type needs to be sent for international shipments
            shipping_label_request.add_data({
                'IntegratedFormType': self.endicia_integrated_form_type,
            })

        if self.delivery_address.country.code != 'US':
            self._update_endicia_item_details(shipping_label_request)

        # Logging.
        logger.debug(
            'Making Shipping Label Request for'
            'Shipment ID: {0} and Carrier ID: {1}'
            .format(self.id, self.carrier.id)
        )
        logger.debug('--------SHIPPING LABEL REQUEST--------')
        logger.debug(str(shipping_label_request.to_xml()))
        logger.debug('--------END REQUEST--------')

        try:
            response = shipping_label_request.send_request()
        except RequestError, error:
            self.raise_user_error('error_label', error_args=(error.message,))
Esempio n. 45
0
 def _get_internal_quantity(quantity, uom, product):
     Uom = Pool().get('product.uom')
     internal_quantity = Uom.compute_qty(uom, quantity,
         product.default_uom, round=True)
     return internal_quantity