class OrderPdf < RenderPdf include ArticlesHelper attr_reader :order def initialize(order, options = {}) @order = order @orders = order super(options) end def nice_table(name, data, dimrows = []) name_options = { size: 10, style: :bold } name_height = height_of name, name_options made_table = make_table data, width: bounds.width, cell_style: { size: 8, overflow: :shrink_to_fit } do |table| # borders table.cells.borders = [:bottom] table.cells.padding_top = 2 table.cells.padding_bottom = 4 table.cells.border_color = 'dddddd' table.rows(0).border_color = '666666' # dim rows which were ordered but not received dimrows.each do |ri| table.row(ri).text_color = '999999' table.row(ri).columns(0..-1).font_style = nil end yield table if block_given? end if name_height + made_table.height < cursor down_or_page 15 else start_new_page end text name, name_options made_table.draw end protected # Return price for order_article. # # This is a separate method so that plugins can override it. # # @param article [OrderArticle] # @return [Number] Price to show # @see https://github.com/foodcoops/foodsoft/issues/445 def order_article_price(order_article) order_article.article_version.fc_group_order_price end def order_article_price_per_unit(order_article) "#{number_to_currency(order_article_price(order_article))} / #{format_group_order_unit_with_ratios(order_article.article_version)}" end def price_per_billing_unit(goa) article_version = goa.order_article.article_version "#{number_to_currency(article_version.convert_quantity(article_version.fc_price, article_version.billing_unit, article_version.supplier_order_unit))} / #{format_billing_unit_with_ratios(article_version)}" end def billing_quantity_with_tolerance(goa) article_version = goa.order_article.article_version quantity = number_with_precision( article_version.convert_quantity(goa.quantity, article_version.group_order_unit, article_version.billing_unit), strip_insignificant_zeros: true, precision: 2 ) tolerance = number_with_precision( article_version.convert_quantity(goa.tolerance, article_version.group_order_unit, article_version.billing_unit), strip_insignificant_zeros: true, precision: 2 ) goa.tolerance > 0 ? "#{quantity} + #{tolerance}" : quantity end def group_order_article_result(goa) number_with_precision goa.result, strip_insignificant_zeros: true end def billing_article_result(goa) article_version = goa.order_article.article_version number_with_precision( article_version.convert_quantity(goa.result, article_version.group_order_unit, article_version.billing_unit), precision: 2, strip_insignificant_zeros: true ) end def group_order_articles(ordergroup) GroupOrderArticle .includes(:group_order) .where(group_orders: { order_id: @orders, ordergroup_id: ordergroup }) end def order_articles OrderArticle .ordered .includes(article_version: { article: :supplier }) .includes(group_order_articles: { group_order: :ordergroup }) .where(order: @orders) .order('suppliers.name, article_versions.name, groups.name') .preload(:article_version) end def ordergroups(offset = nil, limit = nil) result = GroupOrder .ordered .where(order: @orders) .group('groups.id') .offset(offset) .limit(limit) .pluck('groups.name', 'SUM(group_orders.price)', 'ordergroup_id', 'SUM(group_orders.transport)') result.map do |item| [item.first || stock_ordergroup_name] + item[1..] end end def each_order_article(&) order_articles.each(&) end def each_ordergroup(&) ordergroups.each(&) end def each_ordergroup_batch(batch_size) offset = 0 loop do go_records = ordergroups(offset, batch_size) break unless go_records.any? group_ids = go_records.map(&:third) # get quantity for each article and ordergroup goa_records = group_order_articles(group_ids) .group('group_order_articles.order_article_id, group_orders.ordergroup_id') .pluck('group_order_articles.order_article_id', 'group_orders.ordergroup_id', Arel.sql('SUM(COALESCE(group_order_articles.result, group_order_articles.quantity))')) # transform the flat list of results in a hash (with the article as key), which contains an array for all ordergroups results = goa_records.group_by(&:first).transform_values do |value| grouped_value = value.group_by(&:second) group_ids.map do |group_id| number_with_precision grouped_value[group_id].try(:first).try(:third), strip_insignificant_zeros: true end end yield go_records, results offset += batch_size end end def each_group_order_article_for_order_article(order_article, &) order_article.group_order_articles.each(&) end def each_group_order_article_for_ordergroup(ordergroup, &) group_order_articles(ordergroup) .includes(order_article: { article_version: { article: :supplier } }) .order('suppliers.name, article_versions.name') .preload(order_article: %i[article_version order]) .each(&) end def stock_ordergroup_name users = GroupOrder.stock .eager_load(:updated_by) .where(order: @orders) .map(&:updated_by) .map { |u| u.try(&:name) || '?' } I18n.t('model.group_order.stock_ordergroup_name', user: users.uniq.sort.join(', ')) end end