diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-05-15 16:22:21 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-05-15 16:22:21 +0700 |
| commit | f4f150ec2492b048886e1965a0a650864295c76c (patch) | |
| tree | 37386674983c542d6730e993e09337505dfc415e | |
| parent | 6364f3d0bec6e75e3056caa928bbe11d39cc145f (diff) | |
grand total field, compute grand total, sale order print for website, fix sale order download pdf api
| -rw-r--r-- | indoteknik_api/controllers/api_v1/sale_order.py | 10 | ||||
| -rw-r--r-- | indoteknik_api/models/sale_order.py | 3 | ||||
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 3 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 5 | ||||
| -rw-r--r-- | indoteknik_custom/report/report_sale_order.xml | 273 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 1 |
6 files changed, 290 insertions, 5 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index ec39b32a..8fe1bb52 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -187,7 +187,7 @@ class SaleOrder(controller.Controller): return self.response('Unauthorized') sale_order = request.env['sale.order'].sudo().search_read([('id', '=', id)], ['name']) - pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'sale.report_saleorder')])._render_qweb_pdf([id]) + pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'indoteknik_custom.report_saleorder_website')])._render_qweb_pdf([id]) if pdf and len(sale_order) > 0: return rest_api.response_attachment({ 'content': pdf, @@ -235,7 +235,9 @@ class SaleOrder(controller.Controller): 'po_number': [], 'po_file': [], 'type': [], - 'delivery_amount': ['number', 'default:0'] + 'delivery_amount': ['number', 'default:0'], + 'carrier_id': [], + 'delivery_service_type': [] }) if not params['valid']: @@ -260,7 +262,9 @@ class SaleOrder(controller.Controller): 'partner_purchase_order_file': params['value']['po_file'], 'delivery_amt': params['value']['delivery_amount'], 'shipping_cost_covered': 'customer', - 'shipping_paid_by': 'customer' + 'shipping_paid_by': 'customer', + 'carrier_id': params['value']['carrier_id'], + 'delivery_service_type': params['value']['delivery_service_type'], } if params['value']['type'] == 'sale_order': parameters['approval_status'] = 'pengajuan1' diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index cadf9f77..9661a0ba 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -12,7 +12,7 @@ class SaleOrder(models.Model): 'sales': sale_order.user_id.name, 'amount_untaxed': sale_order.amount_untaxed, 'amount_tax': sale_order.amount_tax, - 'amount_total': sale_order.amount_total, + 'amount_total': sale_order.grand_total, 'purchase_order_name': sale_order.partner_purchase_order_name or sale_order.client_order_ref, 'purchase_order_file': True if sale_order.partner_purchase_order_file else False, 'invoice_count': sale_order.invoice_count, @@ -49,6 +49,7 @@ class SaleOrder(models.Model): data_with_detail = { 'payment_term': sale_order.payment_term_id.name or '', 'products': [], + 'delivery_amount': sale_order.delivery_amt or 0, 'address': { 'customer': res_users.api_address_response(sale_order.partner_id), 'invoice': res_users.api_address_response(sale_order.partner_invoice_id), diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index d9e98975..c52e27b7 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -79,7 +79,8 @@ 'report/report_banner_banner2.xml', 'report/purchase_order.xml', 'report/report_invoice.xml', - 'report/report_picking.xml' + 'report/report_picking.xml', + 'report/report_sale_order.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 69e96968..14c87641 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -73,6 +73,7 @@ class SaleOrder(models.Model): gross_amount = fields.Float(string='Gross Amount', help='Jumlah pembayaran yang dilakukan dengan Midtrans') notification = fields.Char(string='Notification', help='Dapat membantu error dari approval') delivery_service_type = fields.Char(string='Delivery Service Type', help='data dari rajaongkir') + grand_total = fields.Monetary(string='Grand Total', help='Amount total + amount delivery', compute='_compute_grand_total') @api.model def _generate_so_access_token(self, limit=50): @@ -362,6 +363,10 @@ class SaleOrder(models.Model): for line in self.order_line: line.product_id_change() + def _compute_grand_total(self): + for order in self: + order.grand_total = order.delivery_amt + order.amount_total + class SaleOrderLine(models.Model): _inherit = 'sale.order.line' diff --git a/indoteknik_custom/report/report_sale_order.xml b/indoteknik_custom/report/report_sale_order.xml new file mode 100644 index 00000000..595a989f --- /dev/null +++ b/indoteknik_custom/report/report_sale_order.xml @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + <record id="action_report_saleorder_website" model="ir.actions.report"> + <field name="name">Quotation / Order (Website)</field> + <field name="model">sale.order</field> + <field name="report_type">qweb-pdf</field> + <field name="report_name">indoteknik_custom.report_saleorder_website</field> + <field name="report_file">indoteknik_custom.report_saleorder_website</field> + <field name="print_report_name">(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)</field> + <field name="binding_model_id" ref="model_sale_order"/> + <field name="binding_type">report</field> + </record> + </data> + + <template id="report_saleorder_website"> + <t t-call="web.html_container"> + <t t-foreach="docs" t-as="doc"> + <t t-call="indoteknik_custom.report_saleorder_website_document" t-lang="doc.partner_id.lang"/> + </t> + </t> + </template> + + <template id="report_saleorder_website_document"> + <t t-call="web.external_layout"> + <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" /> + <t t-set="address"> + <div t-field="doc.partner_id" + t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' /> + <p t-if="doc.partner_id.vat"><t t-esc="doc.company_id.country_id.vat_label or 'Tax ID'"/>: <span t-field="doc.partner_id.vat"/></p> + </t> + <t t-if="doc.partner_shipping_id == doc.partner_invoice_id + and doc.partner_invoice_id != doc.partner_id + or doc.partner_shipping_id != doc.partner_invoice_id"> + <t t-set="information_block"> + <strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoicing and Shipping Address:</strong> + <strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoicing Address:</strong> + <div t-field="doc.partner_invoice_id" + t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/> + <t t-if="doc.partner_shipping_id != doc.partner_invoice_id"> + <strong>Shipping Address:</strong> + <div t-field="doc.partner_shipping_id" + t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/> + </t> + </t> + </t> + <div class="page"> + <div class="oe_structure"/> + + <h2 class="mt16"> + <t t-if="not (env.context.get('proforma', False) or is_pro_forma)"> + <span t-if="doc.state not in ['draft','sent']">Order # </span> + <span t-if="doc.state in ['draft','sent']">Quotation # </span> + </t> + <t t-if="env.context.get('proforma', False) or is_pro_forma"> + <span>Pro-Forma Invoice # </span> + </t> + <span t-field="doc.name"/> + </h2> + + <div class="row mt32 mb32" id="informations"> + <div t-if="doc.client_order_ref" class="col-auto col-3 mw-100 mb-2"> + <strong>Your Reference:</strong> + <p class="m-0" t-field="doc.client_order_ref"/> + </div> + <div t-if="doc.date_order and doc.state not in ['draft','sent']" class="col-auto col-3 mw-100 mb-2"> + <strong>Order Date:</strong> + <p class="m-0" t-field="doc.date_order"/> + </div> + <div t-if="doc.date_order and doc.state in ['draft','sent']" class="col-auto col-3 mw-100 mb-2"> + <strong>Quotation Date:</strong> + <p class="m-0" t-field="doc.date_order" t-options='{"widget": "date"}'/> + </div> + <div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-auto col-3 mw-100 mb-2" name="expiration_date"> + <strong>Expiration:</strong> + <p class="m-0" t-field="doc.validity_date"/> + </div> + <div t-if="doc.user_id.name" class="col-auto col-3 mw-100 mb-2"> + <strong>Salesperson:</strong> + <p class="m-0" t-field="doc.user_id"/> + </div> + </div> + + <!-- Is there a discount on at least one line? --> + <t t-set="display_discount" t-value="any(l.discount for l in doc.order_line)"/> + + <table class="table table-sm o_main_table"> + <!-- In case we want to repeat the header, remove "display: table-row-group" --> + <thead style="display: table-row-group"> + <tr> + <th name="th_description" class="text-left">Description</th> + <th name="th_quantity" class="text-right">Quantity</th> + <th name="th_priceunit" class="text-right">Unit Price</th> + <th name="th_discount" t-if="display_discount" class="text-right" groups="product.group_discount_per_so_line"> + <span>Disc.%</span> + </th> + <th name="th_taxes" class="text-right">Taxes</th> + <th name="th_subtotal" class="text-right"> + <span groups="account.group_show_line_subtotals_tax_excluded">Amount</span> + <span groups="account.group_show_line_subtotals_tax_included">Total Price</span> + </th> + </tr> + </thead> + <tbody class="sale_tbody"> + + <t t-set="current_subtotal" t-value="0"/> + + <t t-foreach="doc.order_line" t-as="line"> + + <t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/> + <t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/> + + <tr t-att-class="'bg-200 font-weight-bold o_line_section' if line.display_type == 'line_section' else 'font-italic o_line_note' if line.display_type == 'line_note' else ''"> + <t t-if="not line.display_type"> + <td name="td_name"><span t-field="line.name"/></td> + <td name="td_quantity" class="text-right"> + <span t-field="line.product_uom_qty"/> + <span t-field="line.product_uom"/> + </td> + <td name="td_priceunit" class="text-right"> + <span t-field="line.price_unit"/> + </td> + <td t-if="display_discount" class="text-right" groups="product.group_discount_per_so_line"> + <span t-field="line.discount"/> + </td> + <td name="td_taxes" class="text-right"> + <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_id))"/> + </td> + <td name="td_subtotal" class="text-right o_price_total"> + <span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/> + <span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/> + </td> + </t> + <t t-if="line.display_type == 'line_section'"> + <td name="td_section_line" colspan="99"> + <span t-field="line.name"/> + </td> + <t t-set="current_section" t-value="line"/> + <t t-set="current_subtotal" t-value="0"/> + </t> + <t t-if="line.display_type == 'line_note'"> + <td name="td_note_line" colspan="99"> + <span t-field="line.name"/> + </td> + </t> + </tr> + + <t t-if="current_section and (line_last or doc.order_line[line_index+1].display_type == 'line_section')"> + <tr class="is-subtotal text-right"> + <td name="td_section_subtotal" colspan="99"> + <strong class="mr16">Subtotal</strong> + <span + t-esc="current_subtotal" + t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}' + /> + </td> + </tr> + </t> + </t> + </tbody> + </table> + + <div class="clearfix" name="so_total_summary"> + <div id="total" class="row" name="total"> + <div t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto"> + <table class="table table-sm"> + <tr class="border-black o_subtotal" style=""> + <td name="td_amount_untaxed_label"><strong>Subtotal</strong></td> + <td name="td_amount_untaxed" class="text-right"> + <span t-field="doc.amount_untaxed"/> + </td> + </tr> + <tr> + <td name="td_amount_total_label">Tax</td> + <td name="td_amount_total" class="text-right"> + <span t-field="doc.amount_tax"/> + </td> + </tr> + <tr> + <td name="td_grand_total_label">Delivery Amount</td> + <td name="td_grand_total" class="text-right"> + <span t-field="doc.delivery_amt" t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/> + </td> + </tr> + <tr class="border-black o_total"> + <td name="td_grand_total_label"><strong>Grand Total</strong></td> + <td name="td_grand_total" class="text-right"> + <span t-field="doc.grand_total"/> + </td> + </tr> + </table> + </div> + </div> + </div> + + <div t-if="doc.signature" class="mt32 ml64 mr4" name="signature"> + <div class="offset-8"> + <strong>Signature</strong> + </div> + <div class="offset-8"> + <img t-att-src="image_data_uri(doc.signature)" style="max-height: 4cm; max-width: 8cm;"/> + </div> + <div class="offset-8 text-center"> + <p t-field="doc.signed_by"/> + </div> + </div> + + <div class="oe_structure"/> + + <p t-field="doc.note" /> + <p t-if="doc.payment_term_id.note"> + <span t-field="doc.payment_term_id.note"/> + </p> + <p id="fiscal_position_remark" t-if="doc.fiscal_position_id and doc.fiscal_position_id.sudo().note"> + <strong>Fiscal Position Remark:</strong> + <span t-field="doc.fiscal_position_id.sudo().note"/> + </p> + </div> + </t> + </template> + + <template id="report_saleorder_website_document_inherit_sale_management" inherit_id="indoteknik_custom.report_saleorder_website_document"> + <xpath expr="//div[@name='signature']" position="after"> + <div t-if="doc.sale_order_option_ids and doc.state in ['draft', 'sent']"> + <t t-set="has_option_discount" t-value="any(option.discount != 0.0 for option in doc.sale_order_option_ids)" /> + <h4 name="h_optional_products"> + <span>Options</span> + </h4> + <table name="table_optional_products" class="table table-sm"> + <thead> + <tr> + <th name="th_option_name" class="text-left">Description</th> + <th t-if="has_option_discount" name="th_option_discount" groups="product.group_discount_per_so_line" class="text-left">Disc.%</th> + <th name="th_option_price_unit" class="text-right">Unit Price</th> + </tr> + </thead> + <tbody class="sale_tbody"> + <tr t-foreach="doc.sale_order_option_ids" t-as="option"> + <td name="td_option_name"> + <span t-field="option.name"/> + </td> + <td t-if="has_option_discount" name="td_option_discount" groups="product.group_discount_per_so_line"> + <strong t-if="option.discount != 0.0" class="text-info"> + <t t-esc="((option.discount % 1) and '%s' or '%d') % option.discount"/>% + </strong> + </td> + <td name="td_option_price_unit"> + <strong class="text-right"> + <div t-field="option.price_unit" + t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}' + t-att-style="option.discount and 'text-decoration: line-through' or None" + t-att-class="option.discount and 'text-danger' or None"/> + <div t-if="option.discount"> + <t t-esc="'%.2f' % ((1-option.discount / 100.0) * option.price_unit)"/> + </div> + </strong> + </td> + </tr> + </tbody> + </table> + </div> + </xpath> + </template> + + <template id="report_saleorder_website_document_inherit_sale_stock" inherit_id="indoteknik_custom.report_saleorder_website_document"> + <xpath expr="//div[@name='expiration_date']" position="after"> + <div class="col-3" t-if="doc.incoterm" groups="sale_stock.group_display_incoterm"> + <strong>Incoterm:</strong> + <p t-field="doc.incoterm.code"/> + </div> + </xpath> + </template> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index fde93a9b..c66201a9 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -65,6 +65,7 @@ <field name="line_no" readonly="1"/> </xpath> <field name="amount_total" position="after"> + <field name="grand_total"/> <field name="total_margin"/> <field name="total_percent_margin"/> </field> |
