---
# System prepended metadata

title: MARKET PLACE

---

# MARKET PLACE
Marketplace Tokped Shopee:
- invoice-office-{nama-marketplace}
- invoice-pdf-generator
  - edit
  - change value invoice number, split by comma
- result: Gdrive, Invoice Marketplace
- copy link gdrive

Grab:
- Download & extract file zip
- Upload to folder resources-> grab
- Triger resource-opperator
- Triger Grab mapping product checker
  - beda tanggal
  - CUSTOM DATE:
  - VALUE:
- Check di channel t-os-data
- Apabila ada message missing mapping product 'grab' - checked
- order-officer-Grab done
- invoice-officer-grab
  - catat nomor invoice yang sudah di generate
- invoice pdf-generator
  - edit
  - masukan invoice hasil generate di value INVOICE_NUMBERS
- result: Gdrive, Invoice Marketplace
- copy link gdrive

<br><br>

# QOALA
# Project Qoala

Related docoments:
1. Google sheet [Qoala x Printerous Order Sheet](https://docs.google.com/spreadsheets/d/1qu2WrT23DYSt8ehanDgkhVPDlOE2jclhrb-b909j2GI/edit#gid=0).
Berisi list detail, proggress, dan invoice dari order qoala. Terdiri dari beberapa sheet ex: (JKT, BDG, MDN, SBY) merepresentasikan partner yang menghandle order tersebut.
2. Google sheet [Qoala Partner Data](https://docs.google.com/spreadsheets/d/14wluZfh9OgKDqeFTMleeeKe3boZmh1uZF7XMdtkPTlQ/edit#gid=0)
Berisi data partner, prices, dan kurir yang menghandle pengiriman order tersebut.
3. Google credential files.
    * credentials.json
    * token.yaml

## Project repository and scripts dir
Semua script dan cronjob untuk menghandle project ini ada digithub `printerous/partner-platform` branch `external-project`
#### officer
`app/officer/qoala`
#### scripts
`lib/scripts/qoala`
#### k8s config file
`lib/scripts/qoala/k8s`

## Flow and Scheduled scripts
User qoala melakukan input pada kolom A sampai L pada file gsheet `Qoala x Printerous Order Sheet`. Ketika data yang diinput sudah lengkap, setiap pukul 9 dan 15 script import-data akan membuatkan Order dan PO.
1. User qoala input data order di gsheet
2. script import-order running dan create order + PO untuk data2 yg telah lengkap
3. script monitoring running setiap jam untuk update progress order
4. script manual invoice create invoice sebulan sekali setiap tanggal 26.

* **import-order** `0 2,8 * * *`
script yg running setiap jam 09:00 WIB dan 15:00, bertugas untuk membaca file gsheet `Qoala x Printerous Order Sheet`, create order dan partner order.

* **monitoring** `13 * * * *`
script ini running setiap menit 13 setiap hari, yang bertugas untuk mengisi kolom `O` sampai `X` di gsheet `Qoala x Printerous Order Sheet`.

* **fix-quantity**
script yang di trigger secara **manual** untuk melakukan perbaikan quantity, dikarenakan perubahan yang dilakukan oleh client qoala pada gsheet.\
> sesuaikan value ENV['ORDER_NUMBERS'] yang berisi nomor order pada cronjobs di dashboard kubernetes sebelum mentrigger scripts ini.

* **fix-polis**
script yang di trigger secara **manual** untuk melakukan perubahan nomor polis pada order yang sudah di create ex: (`order number`, `title`, `notes`)
> sesuaikan value ENV['POLIS_NUMBERS'] yang berisi nomor polis pada cronjobs di dashboard kubernetes sebelum mentrigger scripts ini.

* **manual-invoice** `0 2,8 * * *`
script ini running setiap pukul 01:00 WIB dini hari di tanggal 25 setiap bulannya. Bertujuan untuk membuat invoice berdasarkan order yang sudah complete dan belum masuk kedalam invoice.

---
## Update Manual QTY Qoala
```
# Prepare data
order_number = 'PA11INTAMO2100V0006050'
po_id        = '130322'
quantity     = '10'.to_i
order        = Order.find_by(number: order_number)
po           = PartnerOrder.find(po_id)
order_item   = OrderItem.find_by(number: "#{order_number}-1")
po_item      = PartnerOrderItem.find_by(order_item_id: order_item.id)

# Update order item
order_item.quantity    = quantity
order_item.subtotal    = quantity * order_item.price
order_item.tax         = quantity * order_item.price * 0.11
order_item.grand_total = quantity * order_item.price
order_item.save!

# Update partner order item
po_item.quantity    = quantity
po_item.total_price = quantity * po_item.price
po_item.save!

# Update partner order
po.price = PartnerOrderItem.where(partner_order_id: po_id).sum(&:total_price)
po.tax   = po.price * 0.11
po.save!

# Update order
order.subtotal    = OrderItem.where(order_id: order.id).sum(&:subtotal)
order.tax         = order.subtotal * 0.11
order.grand_total = order.subtotal + order.shipping_fee
order.save!

invoice_item = InvoiceItem.find_by(order_item_id: order_item.id)
if invoice_item.present?
  invoice_item.quantity    = order_item.quantity
  invoice_item.subtotal    = order_item.subtotal
  invoice_item.grand_total = order_item.grand_total
  invoice_item.save
end
```
---
### Find PO & Shipping Fee Qoala
```
numbers = ["PA99.0201.22.000003"]
numbers.map {|number|
  order = Order.find_by(number: number)
  po_id = order&.order_items&.first&.partner_order_items&.first.partner_order_id

  [number, order.subtotal.to_i, order&.order_shipping&.shipping_fee, po_id]
}
```
---
### Fix delivery date ghseet Qoala
```
awb_numbers = ["10003131655358","10002872125177"]
awb_numbers.map { |awb_number|
  partner_package = PartnerPackage.find_by(awb_number: awb_number)
  completed = partner_package.completed?

  next if partner_package.blank? && !completed

  log = PartnerPackageLog.new
  log.partner_package_id  = partner_package.id
  log.action_code = 'completed'
  log.action_date = Time.now
  log.save
}

Gsheet akan otomatis diupdate ketika cronjob monitoring_2021 running
```
<br><br>

# HELPTECH
## Prism
- kubectl -n production get pods | grep prism
- kubectl -n production exec -it nama-pods bash

---
## Invoice:
### Generate Manual Invoice
```
 items = [
    {
      number: 'PA2211388E8-LU-01',
      quantity: 50_000
    },
    {
      number: 'PA2211388E8-LU-02',
      quantity: 60_000
    }
  ]

  subtotal    = discount = shipping_fee = 0
  order       = Order.find_by number: 'PA2211388E8'
  integration = [{ id: order.id, type: 'Order' }]
  order_items = []

  items.each do |item|
    order_item = OrderItem.find_by number: item[:number]

    item_subtotal = item[:quantity] * order_item.price
    subtotal += item_subtotal

    if order.blank?
      order = order_item.order
      integration = [{ id: order.id, type: 'Order' }]
    end
    order_items << item
  end

  number          = Invoice.generate_number
  billing_address = order.order_items.map(&:billing_address).reject(&:blank?).first
  tax_policy      = :tax_inclusive
  slug            = SecureRandom.hex.slice(0, 4).upcase
  term_of_payment = order.order_terms
  top_settlement  = term_of_payment.size > 1 ? term_of_payment.last : term_of_payment.first
  top_type        = order.order_terms[0][:calculation]

  tax_template = :show_tax
  tax_amount   = (subtotal + shipping_fee - discount) * 0.111
  grand_total  = subtotal + shipping_fee - discount
  grand_total += tax_amount if order.tax_policy == 'tax_exclusive'

  invoice = InvoiceMain.create(
    parent_id: nil,
    number: number,
    billing_address_id: billing_address.id,
    billing: billing_address.address_json,
    price: grand_total,
    discount: discount,
    tax_template: tax_template,
    tax_policy: tax_policy,
    term: {},
    invoice_date: nil,
    integration: integration,
    shipping_fee: shipping_fee,
    subtotal: subtotal,
    grand_total: grand_total,
    data: { active: true }
  )

  items.each do |item|
    order_item = OrderItem.find_by number: item[:number]
    item_subtotal = item[:quantity] * order_item.price
    invoice.invoice_items.create(
      order_item_id: order_item.id,
      title: order_item.title,
      quantity: item[:quantity],
      unit: order_item.unit,
      tax_policy: order_item.tax_policy,
      subtotal: item_subtotal,
      grand_total: item_subtotal,
      integration: [{ id: order_item.id, type: 'OrderItem' }],
      slug: slug
    )
  end

  type = 'InvoiceSettlement'

  status         = top_settlement.name == 'CIA' ? 'submitted' : 'draft'
  value          = top_settlement.value.to_f
  price          = top_type == 'percentage' ? value * grand_total / 100 : value

  terms = {
    id: top_settlement.term_id,
    term: top_settlement.name,
    value: value,
    days: top_settlement.baseline_due,
    status: status,
    price: price
  }

  invoice_number = number
  due_date       = nil
  invoice_date   = nil

  if terms[:status] != 'draft'
    invoice_date = Time.now
    due_date     = DateTime.now + terms[:days].days
  end

  invoice_child = type.constantize.find_or_initialize_by(parent_id: invoice.id)
  invoice_child.parent_id          = invoice.id
  invoice_child.number             = invoice_number
  invoice_child.billing_address_id = billing_address.id
  invoice_child.billing            = billing_address.address_json
  invoice_child.price              = terms[:price]
  invoice_child.tax_template       = tax_template
  invoice_child.tax_policy         = tax_policy
  invoice_child.term               = {}
  invoice_child.invoice_date       = invoice_date
  invoice_child.due_date           = due_date
  invoice_child.status             = terms[:status]
  invoice_child.integration        = [{ id: order.id, type: 'Order' }, { id: terms[:id], type: 'OrderTerm' }]
  invoice_child.top_terms          = terms
  invoice_child.data               = { active: true }
  invoice_child.subtotal           = terms[:price]
  invoice_child.grand_total        = terms[:price]
  invoice_child.save

  get nomor invoice:
  invoice.number

  Download invoicenya:
  https://platform.printerous.com/backend/invoice-monitoring
  search by: number
```
### Invoice Update Tagihan Saat Ini
```
selain invoice proforma:

number           = 'INV/211123/9191'
price            = 6999850
tagihan_saat_ini = price.to_f
invoice = Invoice.where(number: number)
invoice.update_all(price: tagihan_saat_ini)
```

---
### Update Invoice Date & Due Date
```
number        = 'INV/211222/9F69'
invoice_date  = '2021-12-22 10:00:00'.to_datetime
due_date      = '2021-12-23 10:00:00'.to_datetime
invoice       = Invoice.find_by(number: number)
main_invoice  = invoice.invoice_main
invoice_child = main_invoice.invoice_childs&.first

invoice_child.update(invoice_date: invoice_date, due_date: due_date)
```

---
### Failed Accept PO
Cek di Table
- cek order item di PO
- order_item -> cek shipping_address_id
- Penyebabnya: Ada salah satu order item yang belum ada shipping address idnya

---
### Change Category Order to Sample
- Order -> category_nya jadi sample nominal2nya di ubah jadi 0

---
### Complete Order Item
Script ini dapat digunakan untuk order monitoring cleanup
```
numbers = %w[PA211021B0C5-1 PA211029FDE2-1]
order_items = OrderItem.where(number: numbers)
order_items.each do |order_item|
  CompleteOrderItemCleanupJob.perform_later(order_item.id)
end

Cek Result:
order_items.reload
order_items.map{|item| [item.number, item.status, item.data['monitoring_status']]}

<!-- result size must be 0 and monitoring status ['cplt'] -->
order_items.where.not(status: :completed).size

item.status harus Completed
monitoring_status harus ['cplt']
```
---
### PO Failed Auto Assign
example case:
```
PA >  PA211116E1F3-1, dari kmren statusnya CRPO tapi adanya di auto assigned, ini kenapa ya udh dari kmren sore tapi sampe sekarang belum ke create PO'a? jadi mempengaruhi SLA di procurement jatuhnya telat.

Table = order_item_prices.data, hapus aja "waiting" pada {"distribution": "waiting"}
```
---
### Complete Order
```
numbers = %w[PA2112234029]
orders = Order.where(number: numbers)
orders.each do |order|
  OrderCleanupJob.perform_later(order.id)
end
```

---
### Invoice ga ke create
number= 'PA2112234029'
order = Order.find_by(number: number)
running OrderInvoiceOfficer.new(order).perform

---
### Filenya tidak ada dilayouter
file_artwork == FA
Prism: order_items
Orion: cart_item_conversions->cart_items->project_token

<br>

https://draw.printerous.com/editors/NDkyNmEzYjIxMTc5NzFmYzQ4NGEwYjkzNTUzMTIwNmZmOTE4MmVkM2JiYzY1MTRkNTZhZThmZmZiMDYzYmQyNCxlODQ2ZmY5OTBiMDI5ZDk4YWE1NWE0ZjAzMGU1NGNmMCwxNjQxODkwMzk2


---
### Update Manual Status Order Monitoring:
```
numbers = %w[PA2110156CEE-1]
ids = [691877, 691878]
order_items = OrderItem.where(id: ids)

order_items.each do |order_item|
  order_item.status = :completed
  order_item.data['monitoring_status'] = ['cplt']
  order_item.data['monitoring_step'] = "completed"
  order_item.save

  order = order_item.order
  all_items = order.order_items.reload.where(status: %w[submitted completed])

  all_completed = all_items.all? { |item| item.status == 'completed' }

  if all_completed
    order.status = :completed
    order.save
  end
end
```
---
### Change Layoutes Status
Update status order_approval jadi approved/accepted
```
number = 'WR211122145E-1'
order_item = OrderItem.find_by(number: number)
order_item.proceed_approval.update(status: :approved)
```
---
### Dokumentasi Moments:
```
https://docs.google.com/presentation/d/1xNMQyQfqpK-zjfDxvUa8Nci7H3h8aGIFa8etGH56jEY/edit#slide=id.g1022fdf0e5d_0_8
```
### Fix Polish Order Title Qoala:
```
Example case:
Mohon bantuan perubahan tipe polis pada PO Qoala Image Plus, sbb :
PO/211214/079B
Sebelumnya tipe polis : Sompo revisi menjadi TOB
Perubahans udah dilakukan pada order sheet qoala

Update title di order_item & partner order item
```
---
### Url download invoice local:
```
ulimit -n 100000

http://platform.lvh.me:3005/backend/invoice-monitoring/42552/download.pdf
http://platform.lvh.me:3005/backend/invoice-monitoring/42668/download.pdf
http://platform.lvh.me:3005/backend/invoice-monitoring/42668/download.pdf
```

---
### Backend Pro:
https://jarvis.printerous.com/pro-account-registration

---
### Cek Harga Product Master:
https://cuanki.printerous.com/variants/1551/previews
1551 = Product variant id di cart_item

### Alur Order Website
- Create Cart
  POST: https://orion-api-staging.printerous.com/stark/cart
  params:
  ```
  {
  "cart": {
      "items": [
          {
              "partner_price_id": 709948,
              "product_id": 917180,
              "quantity": 100,
              "total_price": 12700,
              "unit_price": 127,
              "file_source": "blank_editor",
              "page_id": 2040,
              "file_url": null,
              "preview_url": null,
              "additional": null,
              "personalize": true
          }
      ]
    }
  }
```
- Upload Template:
  POST: https://vangogh-k8s.printerous.com/editors/save
  ```
    project_token=ZjgxZWM1NjEyZDgwZmFkMjc5Y2E3MmI5YWE1ZjJmZDRmZDc5NTMwYTljZGM4ODAyOTQ3ZjcwNzM0YzRiMGFjNSxhZDcwYWMxMjQ4Yjk1YWJiNjYxZjZhOGFlYzA1ODczNSwxNjM5NjM3MDE1&cc_result%5BstateId%5D=7d0236f2-1e29-416e-8cab-a88c32f2f426&cc_result%5BreturnToEditUrl%5D=https%3A%2F%2Fcanvas.printerous.com%2Fproduction%2Fcanvas%2Fedge%2Fpage%2Fiframe%2F%3FcustomStyle%3Dtoolbox-icon%26state%3D7d0236f2-1e29-416e-8cab-a88c32f2f426%26userId%3D12636&cc_result%5BuserId%5D=12636
  ``
- Create Cart:
  GET: https://orion-api-staging.printerous.com/stark/cart

- Get Shipping Courier
  GET: https://orion-api-staging.printerous.com/stark/cart-groups/6673/shipping-couriers

- Update Shipping Courier
  PUT: https://orion-api-staging.printerous.com/stark/cart-groups/6673/shipping-couriers
  shipping_courier_id: 9956

- Checkout
  POST: https://orion-api-staging.printerous.com/stark/checkout
  cart_id: 10308

- Pay
  https://orion-api.printerous.com/stark/pay

Officer generate order to prism form website
- UserCartPaymentOfficer

---
### PO Cleanup
```
numbers = ["PO/201127/890C/Rev2"]
partner_orders = PartnerOrder.where(number: numbers)
partner_orders.each do |po|
  po.partner_order_items.each do |partner_order_item|
    PartnerOrderItem::CompletionOfficer.new(partner_order_item).perform
  end

  puts po.number
end
```
---
### Void Partner Package
```
numbers      = %w[PK/1910168446/452A]
current_user = UserAdmin.find 18870
partner_packages = PartnerPackage.where(number: numbers);
partner_packages.each do |pp|
  packages = PartnerPackage::VoidOfficer.new(current_user, pp.id).perform
  if packages
    puts "Success #{pp.number}"
  else
    puts "Failed #{pp.number}"
  end
end
```
---
### Synchronize Order Pro (prtsv3) & Order Prism (prtsv4)
Jalankan URL via Postman:
```
method = POST
order_header_id = prtsv3
url: http://platform.printerous.com/api/order-migrations/order_header_id

Cek di sidekiq untuk makesure jobnya running
```
---
## Bulk Cancel Order
```
current_user = UserAdmin.find 18870
numbers = ["PA12.200.0000.21148A"]
orders = Order.find_by(number: numbers)
orders.each do |number|
  order = Order.find_by(number: number)
  chunks = order.order_items.not_cancelled.ids.each_slice(10)
  i = 0

  chunks.each do |ids|
    params = {order_item_ids: ids, reason: 31, notes: "Order double"}

    CancelBulkOrderItemJob.set(wait: i).perform_later(current_user, params)

    i += 60
  end
end
```
---
## Update Sales ID Order
numbers = ["PA2201121A58","PA220112485A","PA2201128B6A","PA2201128B6A"]
orders = Order.where(number: numbers)
orders.update_all(sales_id: 19204)

---
## LinkAja Invoice
- script link_aja_invoice : lib/scripts/fixer/link_aja_invoice.rb
- sesuaikan number dan management fee
- copas di ssh

## Create Bulk PO
- Check partnernya dulu udah sesuai belum, kalo belum update dlu di order_item_prices,
- Jasa pengiriman ga perlu di ubah partnernya
- Script create_bulk_po: lib/scripts/partner_order/create_bulk_po.rb
- Change number and deadline
- Copas di ssh

---
## Complete Invoice
- Copas script di ssh

```
  current_user = UserAdmin.find 11733 # ganti id user lu

  params       = {
    status: 'completed',
    notes: 'Completed by System'
  }

  numbers      = %w[INV/201130/EC38]
  invoices = InvoiceMain.where(number: numbers).where.not(status: :completed)

  invoices.each do |invoice|
    officer        = Invoice::ChangeStatusOfficer.new(invoice, params, current_user)
    invoice_main   = invoice
    child_invoices = invoice_main.invoice_childs
    if officer.perform
      child_invoices = invoice_main.reload.invoice_childs
      new_status     = officer.new_status

      # Hubspot integration deal stage invoiced
      if invoice.is_a?(InvoiceSettlement) && new_status == 'waiting_payment'
        HubspotOrderInvoicedStageJob.perform_later(invoice.order.id)
      end

      # Hubspot integration deal stage paid
      order = invoice.order
      hubspot_deal_id = order.get_integration_id('Hubspot::Deal')
      if invoice.is_a?(InvoiceSettlement) && new_status == 'completed' && hubspot_deal_id.present?
        cek_stage      = Hubspot::Deal::GetStatusDealOfficer.new(hubspot_deal_id).perform
        stage_complete = Hubspot::Pipeline::OfflineSales::STAGES[4]
        if cek_stage.try(:[], :properties).try(:[], :dealstage).try(:[], :value) == stage_complete || order.status == 'completed'
          HubspotOrderPaidToCompleteStageJob.perform_later(order.id, stage_complete)
        else
          HubspotOrderPaidStageJob.perform_later(order.id)
        end
      end
    end
  end
```

<br>
<br>

---
# Data Exception
---
Fix Data Exception Order
Case: Jika subtotal summary != 0, tapi di Order subtotal - 0

```
ids = [217170]
orders = Order.where(id: ids)
orders.each do |order|
  tax          = order.order_items.sum(:tax)
  discount     = order.order_items.sum(:discount)
  shipping_fee = order.order_items.sum(:shipping_fee)
  subtotal     = order.order_items.sum(:subtotal)
  grand_total  = (subtotal - discount) + tax + shipping_fee

  order.tax          = tax
  order.discount     = discount
  order.shipping_fee = shipping_fee
  order.subtotal     = subtotal
  order.grand_total  = grand_total
  order.save!
end
```
---
### Complete Order Item using Order Item ID
```
ids = [757680]
order_items = OrderItem.where(id: ids)
order_items.each do |order_item|
  CompleteOrderItemCleanupJob.perform_later(order_item.id)
end

cek result:
order_items.map {|item| [item.status, item.data['monitoring_status']]}
```
---
### Complete Order Item based on Order Number
```
numbers = ["PA04INTAMO2200V0009441B"]
orders = Order.where(number: numbers)
numbers = orders.map {|o| o.order_items.pluck(:number)}.flatten
order_items = OrderItem.where(number: numbers)
order_items.each do |order_item|
  CompleteOrderItemCleanupJob.perform_later(order_item.id)
end

cek result:
order_items.map {|item| [item.status, item.data['monitoring_status']]}
```
---
### Case: Orion Cart tidak punya cart items
- ssh ke production api
```
ids = [18410,18538,18561]
carts = Stark::Cart.where(id: ids)

- cek apakah cart punya cart items
  cart_items = carts.map { |cart| cart.cart_items }
- cek cart subtotal dan total price
  carts.map {|cart| [cart.subtotal, cart.total_price]}
- Jika cart tidak punya items dan subtotal, total_price valuenya 0, hapus cart
  carts.destroy_all
```
---
## Change QTY Order
```
old_qty      = 96
order_number = 'PA220118FBB2'
order        = Order.find_by(number: order_number)
po_id        = order.partner_order_items.first.partner_order_id
new_qty      = 1000.to_i
po           = PartnerOrder.find(po_id)
order_item   = OrderItem.find_by(number: 'PA220118FBB2-1')
po_item      = PartnerOrderItem.find_by(order_item_id: order_item.id)

# Update order item
order_item.quantity    = new_qty
order_item.subtotal    = new_qty * order_item.price
order_item.tax         = new_qty * order_item.price * 0.11
order_item.grand_total = new_qty * order_item.price
order_item.save!

# Update partner order item
po_item.quantity    = new_qty
po_item.total_price = new_qty * po_item.price
po_item.save!

# Update partner order
po.price = PartnerOrderItem.where(partner_order_id: po_id).sum(&:total_price)
po.tax   = po.price * 0.11
po.save!

# Update order
order.subtotal    = OrderItem.where(order_id: order.id).sum(&:subtotal)
order.tax         = order.subtotal * 0.11
order.grand_total = order.subtotal + order.shipping_fee
order.save!

invoice_item = InvoiceItem.find_by(order_item_id: order_item.id)
if invoice_item.present?
  invoice_item.quantity    = new_qty
  invoice_item.subtotal    = order_item.subtotal
  invoice_item.grand_total = order_item.grand_total
  invoice_item.save
end
```
---
## Change Price Order Item
```
Custom Input:
number      = 'PA211215BBB9-1'
old_price   = '352000.0'.to_f
new_price   = '96'.to_f

order_item  = OrderItem.find_by(number: number, price: old_price)
order       = Order.find_by(id: order_item.order_id)
po_id       = order.partner_order_items.first.partner_order_id
po          = PartnerOrder.find(po_id)
po_item     = PartnerOrderItem.find_by(order_item_id: order_item.id)

# Update order item
order_item.subtotal    = order_item.quantity * new_price
order_item.tax         = order_item.quantity * new_price * 0.11
order_item.grand_total = order_item.quantity * new_price
order_item.save!

# Update order
order.subtotal    = OrderItem.where(order_id: order.id).sum(&:subtotal)
order.tax         = order.subtotal * 0.11
order.grand_total = order.subtotal + order.shipping_fee
order.save!

# Update partner order item
po_item.total_price = po_item.quantity * new_price
po_item.save!

# Update partner order
po.price = PartnerOrderItem.where(partner_order_id: po_id).sum(&:total_price)
po.tax   = po.price * 0.11
po.save!

invoice_item = InvoiceItem.find_by(order_item_id: order_item.id)
if invoice_item.present?
  invoice_item.subtotal    = order_item.subtotal
  invoice_item.grand_total = order_item.grand_total
  invoice_item.save

  grand_total  = order.subtotal + order.shipping_fee - order.discount
  grand_total += order.tax if order.tax_policy == 'tax_exclusive'

  main_invoice = invoice_item.invoice_main
  main_invoice.subtotal    = order.subtotal
  main_invoice.grand_total = order.grand_total
  main_invoice.price       = grand_total
  main_invoice.save!
end
```
---
## Case: PO status rejected tp po item status finished
```
ids = [131886, 134650]
partner_orders = PartnerOrder.where(id: ids)
partner_orders.map{|po|
  po.update(status: :cancelled)
  po.partner_order_items.update_all(status: :cancelled)
}
```

---
## Change Price PO Items
```
numbers = ["PA220113BE2A-1", "PA220113BE2A-2"]
po_items = PartnerOrderItem.where(number: numbers)
price = '2500'.to_f
po_items.each do |po_item|
  po_item.price = price
  po_item.total_price = po_item.quantity * po_item.price
  po_item.save!

  po_id = po_item.partner_order_id

  po = po_item.partner_order
  po.price = PartnerOrderItem.where(partner_order_id: po_id).sum(&:total_price)
  po.tax   = po.price * 0.11
  po.save!
end
```
---
## Case Duedate PO Items Lebih awal dari created date
```
ids = [709868]
ids.map do |id|
  po_item = PartnerOrderItem.find_by(id: id)
  po_item_number = po_item.number

  order_item  = OrderItem.find_by(number: po_item_number)
  working_day = 1
  if working_day
    pw_days     = po_item.partner_order.partner.active_working_days
    created_at  = po_item.created_at
    deadline = deadline_po(working_day, pw_days, created_at)

    po_item.update(due_date: deadline)
    po_item.partner_order.update(due_date: deadline)
  end

  [id, po_item_number, po_item.due_date, po_item.created_at]
end

def partner_holiday(pw_days)
  wday = []
  pw_days.each do |day|
    next unless day[:hour] == 'Closed'

    wday << day[:last_day] unless day[:last_day].blank?

    wday << day[:first_day]
  end
  wday
end

def deadline_po(working_day, pw_days, created_at)
  if pw_days.blank? && !working_day.zero?
    created_at.to_time.in_time_zone('Asia/Jakarta').change(hour: 15, min: 0, sec: 0).to_datetime + working_day
  else
    current_datetime = created_at.to_time.in_time_zone('Asia/Jakarta')
    current_datetime += 1.days if current_datetime.hour > 12
    current_datetime = current_datetime.change(hour: 15, min: 0, sec: 0)
    wday_partner     = partner_holiday(pw_days)

    while working_day > 1
      # check next day is holiday or partner holiday
      wday               = current_datetime.wday
      is_holiday         = BusinessDayOfficer.new(current_datetime).holiday_checking
      is_partner_holiday = wday_partner.include?(wday)

      working_day -= 1 if !is_partner_holiday || !is_holiday

      current_datetime += 1.days
      wday = current_datetime.wday
      is_today_holiday = BusinessDayOfficer.new(current_datetime).holiday_checking
      is_today_partner_holiday = wday_partner.include?(wday)

      if is_today_holiday || is_today_partner_holiday
        working_day += 1
        # current_datetime = current_datetime + 1.days
      end
    end
    current_datetime.change(hour: 15, min: 0, sec: 0)
  end
end
```

<br>
<br>

---
## RFQ
- kubectl -n production get pods | grep service-rfq
- kubectl -n production exec -it nama-pods bash
---
## Nomor RFQ tidak muncul di Product Request
- Cek Spesifikasi RFQ, biasanya karena spesifikasinya kosong
- solusinya edit spec input spesifikasi
- atau create ulang RFQ dengan input specs
- jangan lupa nomor RFQ yang sebelumnya di void / didelete.

---
## Change Status Partner Package
```
number = 'PK/211230F25D/3E4A'
package = PartnerPackage.find_by(number: number)
package.update(status: :requested)
```

---
### RFP: Select Price Modal Loading Terus
url: https://dawet.printerous.com/rfp
repo: service-rfq

```
- Cek tabel inquiry_production_option_quantity_price, column: Integration
- Ganti type: PartnerPrice -> Cuanki::PartnerPrice
```
---
## Change minimum / maximum price package
db: rfq
- Cek di table inquiry_quantity_price
- Kolom bottom_price / selling_price


<br>
<br>

# Orion CMS
- kubectl -n orion get pods | grep website
- kubectl -n orion exec -it nama-pods bash

## Delete Duplicate Page
```
ids = [2366,2365,2363,2362]
ids.map do |id|
  if Page.destroy id
    distributions = Cuanki::VariantDistribution.where(page_id: id)
    distributions.delete_all
    puts id
  end
end
```

<br>
<br>
---
# Cuanki
Repo: service-product <br>

- kubectl -n production get pods | grep product
- kubectl -n production exec -it nama-pods bash

---
## Product Master
- Kendala product sudah di generate tapi belum muncul di halaman product master
- Cek di: https://cuanki.printerous.com/sidejob, pastikan job running dan tidak masuk ke tab dead, kalo masuk tab dead masuk ke halaman product master, generate ulang
- username & password sidejob:
  - username: alchemist
  - password: prts123---

