# [PH] [PRO] Purchase Order
## Endpoints Phoenix
### GET "/phoenix/items/:id/purchase-order-items"
#### Request:
```json=
{
"query": "",
"page": "",
"per": ""
}
```
#### Response:
```json=
[{
"id": ID,
"purchase_order_id": 1,
"addresses_count": 2,
"with_proof": "true|false",
"inquiry_id": ID,
"purchase_order_item_timelines": [{
"step":"",
"due_date":"",
"status":""
}]
}]
```
---
### GET "/phoenix/purchase-orders/ongoing" (status: submitted, approved)
### GET "/phoenix/purchase-orders/completed" (status: completed)
### GET "/phoenix/purchase-orders/rejected" (status: rejected)
#### Request:
```json=
{
"query": "",
"sort_by": "",
"sort_direction: "",
"page": "",
"per": "",
"status": ""
}
```
#### Response:
```json=
[{
"id": ID,
"purchase_order_group_id": 1,
"partner_id": 2,
"billing_address_id": 3,
"number": "PO/OM/211201/ABCD"
"file_url": "URL",
"pdf_url": "URL",
"status": "submitted|approved|completed|cancelled|rejected",
"total_cost": 100000.00,
"purchase_order_items_count": 2,
"partner":{
"id": ID,
"name": "NAME"
},
"purchase_order_timelines":[{
"step":"",
"due_date":"",
"status":""
}]
}]
```
### POST "/phoenix/purchase-order-items/:id/reorder"
#### Response:
```json=
{
"See Purchase Basket Detail"
}
```
### GET "/phoenix/purchase-orders/:id"
#### Response:
```json=
{
"id": ID,
"purchase_order_group_id": 1,
"partner_id": 2,
"billing_address_id": 3,
"number": "PO/OM/211201/ABCD"
"file_url": "URL",
"pdf_url": "URL",
"status": "submitted|approved|completed|cancelled|rejected",
"total_cost": 100000.00,
"partner":{
"id": ID,
"name": "NAME"
}
}
```
### GET "/phoenix/purchase-orders/:id/download-pdf"
#### Response:
```json=
{
"pdf_url": "PO.pdf_url || URL_TO_PO_PDF"
}
```
#### Logic:
- saat po issue, create job to generate po pdf
- validasi if pdf_url blank, generate pdf
- post to "#{ENV.fetch('PHOENIX_HOST_URL')}/pdf/purchase-orders/#{po.id}/download.pdf"
### GET "/phoenix/purchase-orders/:id/shipments"
### Response:
```json=
[{
"id": 1,
"purchase_order_id": 1,
"shipping_address_id": 1,
"shipping": {},
"quantity": 10,
"unit": "Pcs",
"weight": 10,
"dimension": "",
"courier": "",
"service": "",
"airwaybill": "",
"shipping_cost": "",
"lead_time ": "",
"shipping_date ": "",
"delivery_date": "",
"status": "",
"purchase_order_shipment_items_count": 1
}]
```
### GET "/phoenix/purchase-orders/:id/items"
#### Response:
```json=
[{
"id": 1,
"purchase_order_id": 10,
"inquiry_id": 15,
"bidding_submission_id": 100,
"name": "",
"expired_at": "",
"quantity": 100,
"unit": "Pcs",
"design_note": "",
"design_note_attachment": "",
"addresses_count": 1,
"designs_count": 1,
"quotation": {},
"bidding_submission": {
"id": 2211,
"quantity": 100,
"unit": "100 ",
"spec_set": [{
"key": "Jumlah Sisi",
"value": "1 Sisi",
"position": 2,
"custom_size": {},
"spec_key_id": 4,
"spec_value_id": 6
}],
"suggested_reason": null,
"suggested": false,
"lead_time": 3,
"specs_differences": [],
"proof_available": false,
"city": "Kota Tangerang"
},
"bidding_submission_proof": {},
"bidding_submission_summary": {},
"purchase_order_item_timelines": [{
}]
}]
```
### GET "/phoenix/purchase-order-groups/:id/people"
#### Response:
```json=
{
"pic":{
"id": ID,
"name": "NAME",
"job_position":"POSITION"
},
"collaborators":[{
"id": ID,
"name": "NAME",
"job_position":"POSITION"
}]
}
```
### PROOF ACCEPT & PROOF REJECT
### tables
#### purchase_order_item_final_artworks (vh)
- id
- purchase_order_item_proof_approval_id
- file_url
- name
- size
- deleted_at
#### purchase_order_item_proof_prints (vh)
- id
- purchase_order_item_proof_approval_id
- file_url
- name
- size
- deleted_at
#### purchase_order_item_proof_approvals
- id
- purchase_order_item_id
- status (waiting: 0, accepted:1 | rejected: 2)
- notes
- response_by
- response_at
- deleted_at
#### purchase_order_item_proof_shipments (pending)
- id
- purchase_order_item_id
- shipping
- courier
- service
-
## Endpoints
### PATCH /niffler/purchase-order-items/:id/final-artworks
#### Request:
```json=
{
"files":[{
"url": "",
"name": "",
"size": ""
}]
}
```
#### Response:
```json=
[{
"url": "",
"name": "",
"size": ""
}]
```
### PATCH /niffler/purchase-order-items/:id/proof-prints
#### Request:
```json=
{
"files":[{
"url": "",
"name": "",
"size": ""
}]
}
```
#### Response:
```json=
[{
"url": "",
"name": "",
"size": ""
}]
```
### PATCH /phoenix/po-item-approvals/:id/accept
#### Request:
```json=
{
"notes": ""
}
```
#### Response:
```json=
{ "Success" }
```
### PATCH /phoenix/po-item-approvals/:id/reject
#### Request:
```json=
{
"notes": ""
}
```
#### Response:
```json=
{ "Success" }
```
### Notes:
- kalau misal proofnya di reject, apa perlu extend timelinenya?
### Logic:
- di endpoint purchase-orders/:id/items tambahkan attribute proof_need_review
-
### PATCH "/phoenix/purchase-orders/:id/complete"
#### Response:
```json=
{
"Success"
}
```
### Notes:
- ada tag price expired di po item, gimana tau price expired utk smart sourcing?
- filter2 di shipment tracking
- filter search di organization items tab orders by partner tapi gak dimunculin partnernya
### POST "/phoenix/purchase-order-groups/:id/issue"
#### Response:
```json=
{
"Success"
}
```
## Endpoints Niffler
### GET "/niffler/purchase-orders/assigned" (status: submitted)
### GET "/niffler/purchase-orders/active" (status: approved)
### GET "/niffler/purchase-orders/completed" (status: completed)
### GET "/niffler/purchase-orders/cancelled" (status: cancelled)
### GET "/niffler/purchase-orders/rejected" (status: rejected)
#### Request:
```json=
{
"query": "",
"sort_by": "",
"sort_direction: "",
"page": "",
"per": ""
}
```
#### Response:
```json=
[{
"id": ID,
"purchase_order_group_id": 1,
"partner_id": 2,
"billing_address_id": 3,
"number": "PO/OM/211201/ABCD"
"file_url": "URL",
"pdf_url": "URL",
"status": "submitted|approved|completed|cancelled|rejected",
"total_cost": 100000.00,
"organization":{
"id": ID,
"name": "NAME"
},
"purchase_order_timelines":[{
"step":"",
"due_date":"",
"status":""
}]
}]
```
### GET "/niffler/purchase-orders/:id"
#### Response:
```json=
{
"id": ID,
"purchase_order_group_id": 1,
"partner_id": 2,
"billing_address_id": 3,
"number": "PO/OM/211201/ABCD"
"file_url": "URL",
"pdf_url": "URL",
"status": "submitted|approved|completed|cancelled|rejected",
"total_cost": 100000.00,
"organization":{
"id": ID,
"name": "NAME",
"legal_name": "LEGAL NAME",
"logo": ""
},
"purchase_order_shipments": [{
}],
"purchase_order_items": [{
"id": 1,
"purchase_order_id": 10,
"inquiry_id": 15,
"bidding_submission_id": 100,
"name": "",
"expired_at": "",
"quantity": 100,
"unit": "Pcs",
"design_note": "",
"design_note_attachment": "",
"addresses_count": 1,
"designs_count": 1,
"bidding_submission_spec": {
"bidding_submission": {},
"bidding_submission_proof": {}
},
"purchase_order_item_timelines": [{
}]
}]
}
```
### GET "/niffler/purchase-order-items/:id/download"
#### Response:
```json=
{
"url": "ZIP_URL"
}
```
### Notes
- perlu tanya soal calculation total, shipping, discount, ppn per purchase order
- download di page po detail
- nambah kolom top di tabel purchase_orders
- buat table purchase_order_rejections & purchase_order_rejection_reasons
- tambahkan table purchase_order_approvals
- tanya apa itu FA File, proof print, respon customer
### GET "/niffler/po-rejection-reasons"
#### Response:
```json=
[{
"id": 1,
"code": "",
"name": ""
}]
```
### PATCH "/niffler/purchase-orders/:id/accept"
#### Response:
```json=
{
"Success"
}
```
### PATCH "/niffler/purchase-orders/:id/reject"
#### Params:
```json=
{
"reason_ids": [],
"other_reason": ""
}
```
#### Response:
```json=
{
"Success"
}
```
### GET "/niffler/purchase-orders/:id/shipments"
### Case Shipments
```
PO Item 1 Partner A:
name: Spanduk
shipping_address_id: 1
PO Item 2 Partner A:
name: Brosur
shipping_address_id: 2
PO Item 3 Partner A:
name: Brosur
shipping_address_id: 1
```
### LOGIC:
```ruby=
po = Phoenix::PurchaseOrder.find(2)
po_shipment = po.purchase_order_shipments.find_or_initialize_by(shipping_address_id: shipping_address.id)
po_shipment.purchase_order_shipment_items.find_or_initialize_by(purchase_order_item_id: po_item.id)
po.purchase_order_items.each do |po_item|
submission = po_item.bidding_submission
submission.bidding_submission_coverages.each do |bs_coverage|
bs_shipping = bs_coverage.shipping
po_shipment = po.purchase_order_shipments
.find_or_initialize_by(shipping_address_id: bs_coverage.shipping_address_id)
po_shipment.shipping = bs_shiping.shipping
# Save or update another property
po_shipment.save!
po_shipment_item = po_shipment.purchase_order_shipment_items
.find_or_initialize_by(purchase_order_item_id: po_item.id)
po_shipment_item.save!
end
po_item.addresses_count = po.purchase_order_shipments
.joins(:purchase_order_shipment_items)
.where('purchase_order_shipment_items.purchase_order_item_id': po_item.id)
.size
po_item.save!
end
```